[ASTImporter] import macro source locations
Summary: Implement full import of macro expansion info with spelling and expansion locations. Reviewers: a.sidorin, klimek, martong, balazske, xazax.hun Reviewed By: martong Subscribers: thakis, xazax.hun, balazske, rnkovacs, cfe-commits Differential Revision: https://reviews.llvm.org/D47698 llvm-svn: 336269
This commit is contained in:
parent
da4a966e1c
commit
29f37fbb8b
|
@ -7164,19 +7164,13 @@ SourceLocation ASTImporter::Import(SourceLocation FromLoc) {
|
|||
return {};
|
||||
|
||||
SourceManager &FromSM = FromContext.getSourceManager();
|
||||
|
||||
// For now, map everything down to its file location, so that we
|
||||
// don't have to import macro expansions.
|
||||
// FIXME: Import macro expansions!
|
||||
FromLoc = FromSM.getFileLoc(FromLoc);
|
||||
|
||||
std::pair<FileID, unsigned> Decomposed = FromSM.getDecomposedLoc(FromLoc);
|
||||
SourceManager &ToSM = ToContext.getSourceManager();
|
||||
FileID ToFileID = Import(Decomposed.first);
|
||||
if (ToFileID.isInvalid())
|
||||
return {};
|
||||
SourceLocation ret = ToSM.getLocForStartOfFile(ToFileID)
|
||||
.getLocWithOffset(Decomposed.second);
|
||||
return ret;
|
||||
SourceManager &ToSM = ToContext.getSourceManager();
|
||||
return ToSM.getComposedLoc(ToFileID, Decomposed.second);
|
||||
}
|
||||
|
||||
SourceRange ASTImporter::Import(SourceRange FromRange) {
|
||||
|
@ -7184,41 +7178,56 @@ SourceRange ASTImporter::Import(SourceRange FromRange) {
|
|||
}
|
||||
|
||||
FileID ASTImporter::Import(FileID FromID) {
|
||||
llvm::DenseMap<FileID, FileID>::iterator Pos
|
||||
= ImportedFileIDs.find(FromID);
|
||||
llvm::DenseMap<FileID, FileID>::iterator Pos = ImportedFileIDs.find(FromID);
|
||||
if (Pos != ImportedFileIDs.end())
|
||||
return Pos->second;
|
||||
|
||||
|
||||
SourceManager &FromSM = FromContext.getSourceManager();
|
||||
SourceManager &ToSM = ToContext.getSourceManager();
|
||||
const SrcMgr::SLocEntry &FromSLoc = FromSM.getSLocEntry(FromID);
|
||||
assert(FromSLoc.isFile() && "Cannot handle macro expansions yet");
|
||||
|
||||
// Include location of this file.
|
||||
SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
|
||||
|
||||
// Map the FileID for to the "to" source manager.
|
||||
|
||||
// Map the FromID to the "to" source manager.
|
||||
FileID ToID;
|
||||
const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
|
||||
if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
|
||||
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
|
||||
// disk again
|
||||
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
|
||||
// than mmap the files several times.
|
||||
const FileEntry *Entry = ToFileManager.getFile(Cache->OrigEntry->getName());
|
||||
if (!Entry)
|
||||
return {};
|
||||
ToID = ToSM.createFileID(Entry, ToIncludeLoc,
|
||||
FromSLoc.getFile().getFileCharacteristic());
|
||||
if (FromSLoc.isExpansion()) {
|
||||
const SrcMgr::ExpansionInfo &FromEx = FromSLoc.getExpansion();
|
||||
SourceLocation ToSpLoc = Import(FromEx.getSpellingLoc());
|
||||
SourceLocation ToExLocS = Import(FromEx.getExpansionLocStart());
|
||||
unsigned TokenLen = FromSM.getFileIDSize(FromID);
|
||||
SourceLocation MLoc;
|
||||
if (FromEx.isMacroArgExpansion()) {
|
||||
MLoc = ToSM.createMacroArgExpansionLoc(ToSpLoc, ToExLocS, TokenLen);
|
||||
} else {
|
||||
SourceLocation ToExLocE = Import(FromEx.getExpansionLocEnd());
|
||||
MLoc = ToSM.createExpansionLoc(ToSpLoc, ToExLocS, ToExLocE, TokenLen,
|
||||
FromEx.isExpansionTokenRange());
|
||||
}
|
||||
ToID = ToSM.getFileID(MLoc);
|
||||
} else {
|
||||
// FIXME: We want to re-use the existing MemoryBuffer!
|
||||
const llvm::MemoryBuffer *
|
||||
FromBuf = Cache->getBuffer(FromContext.getDiagnostics(), FromSM);
|
||||
std::unique_ptr<llvm::MemoryBuffer> ToBuf
|
||||
= llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
|
||||
FromBuf->getBufferIdentifier());
|
||||
ToID = ToSM.createFileID(std::move(ToBuf),
|
||||
FromSLoc.getFile().getFileCharacteristic());
|
||||
// Include location of this file.
|
||||
SourceLocation ToIncludeLoc = Import(FromSLoc.getFile().getIncludeLoc());
|
||||
|
||||
const SrcMgr::ContentCache *Cache = FromSLoc.getFile().getContentCache();
|
||||
if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
|
||||
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
|
||||
// disk again
|
||||
// FIXME: We definitely want to re-use the existing MemoryBuffer, rather
|
||||
// than mmap the files several times.
|
||||
const FileEntry *Entry =
|
||||
ToFileManager.getFile(Cache->OrigEntry->getName());
|
||||
if (!Entry)
|
||||
return {};
|
||||
ToID = ToSM.createFileID(Entry, ToIncludeLoc,
|
||||
FromSLoc.getFile().getFileCharacteristic());
|
||||
} else {
|
||||
// FIXME: We want to re-use the existing MemoryBuffer!
|
||||
const llvm::MemoryBuffer *FromBuf =
|
||||
Cache->getBuffer(FromContext.getDiagnostics(), FromSM);
|
||||
std::unique_ptr<llvm::MemoryBuffer> ToBuf =
|
||||
llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(),
|
||||
FromBuf->getBufferIdentifier());
|
||||
ToID = ToSM.createFileID(std::move(ToBuf),
|
||||
FromSLoc.getFile().getFileCharacteristic());
|
||||
}
|
||||
}
|
||||
|
||||
ImportedFileIDs[FromID] = ToID;
|
||||
|
|
|
@ -1577,6 +1577,66 @@ TEST_P(ASTImporterTestBase,
|
|||
ToTU, cxxRecordDecl(unless(isImplicit()))));
|
||||
}
|
||||
|
||||
static void CompareSourceLocs(FullSourceLoc Loc1, FullSourceLoc Loc2) {
|
||||
EXPECT_EQ(Loc1.getExpansionLineNumber(), Loc2.getExpansionLineNumber());
|
||||
EXPECT_EQ(Loc1.getExpansionColumnNumber(), Loc2.getExpansionColumnNumber());
|
||||
EXPECT_EQ(Loc1.getSpellingLineNumber(), Loc2.getSpellingLineNumber());
|
||||
EXPECT_EQ(Loc1.getSpellingColumnNumber(), Loc2.getSpellingColumnNumber());
|
||||
}
|
||||
static void CompareSourceRanges(SourceRange Range1, SourceRange Range2,
|
||||
SourceManager &SM1, SourceManager &SM2) {
|
||||
CompareSourceLocs(FullSourceLoc{ Range1.getBegin(), SM1 },
|
||||
FullSourceLoc{ Range2.getBegin(), SM2 });
|
||||
CompareSourceLocs(FullSourceLoc{ Range1.getEnd(), SM1 },
|
||||
FullSourceLoc{ Range2.getEnd(), SM2 });
|
||||
}
|
||||
TEST_P(ASTImporterTestBase, ImportSourceLocs) {
|
||||
Decl *FromTU = getTuDecl(
|
||||
R"(
|
||||
#define MFOO(arg) arg = arg + 1
|
||||
|
||||
void foo() {
|
||||
int a = 5;
|
||||
MFOO(a);
|
||||
}
|
||||
)",
|
||||
Lang_CXX);
|
||||
auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
|
||||
auto ToD = Import(FromD, Lang_CXX);
|
||||
|
||||
auto ToLHS = LastDeclMatcher<DeclRefExpr>().match(ToD, declRefExpr());
|
||||
auto FromLHS = LastDeclMatcher<DeclRefExpr>().match(FromTU, declRefExpr());
|
||||
auto ToRHS = LastDeclMatcher<IntegerLiteral>().match(ToD, integerLiteral());
|
||||
auto FromRHS =
|
||||
LastDeclMatcher<IntegerLiteral>().match(FromTU, integerLiteral());
|
||||
|
||||
SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
|
||||
SourceManager &FromSM = FromD->getASTContext().getSourceManager();
|
||||
CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
|
||||
FromSM);
|
||||
CompareSourceRanges(ToLHS->getSourceRange(), FromLHS->getSourceRange(), ToSM,
|
||||
FromSM);
|
||||
CompareSourceRanges(ToRHS->getSourceRange(), FromRHS->getSourceRange(), ToSM,
|
||||
FromSM);
|
||||
}
|
||||
|
||||
TEST_P(ASTImporterTestBase, DISABLED_ImportNestedMacro) {
|
||||
Decl *FromTU = getTuDecl(
|
||||
R"(
|
||||
#define FUNC_INT void declToImport
|
||||
#define FUNC FUNC_INT
|
||||
FUNC(int a);
|
||||
)",
|
||||
Lang_CXX);
|
||||
auto FromD = FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl());
|
||||
auto ToD = Import(FromD, Lang_CXX);
|
||||
|
||||
SourceManager &ToSM = ToAST->getASTContext().getSourceManager();
|
||||
SourceManager &FromSM = FromD->getASTContext().getSourceManager();
|
||||
CompareSourceRanges(ToD->getSourceRange(), FromD->getSourceRange(), ToSM,
|
||||
FromSM);
|
||||
}
|
||||
|
||||
TEST_P(
|
||||
ASTImporterTestBase,
|
||||
ImportDefinitionOfClassTemplateSpecIfThereIsAnExistingFwdDeclAndDefinition)
|
||||
|
|
Loading…
Reference in New Issue