summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Stahl <r.stahl@tum.de>2018-07-04 13:34:05 +0000
committerRafael Stahl <r.stahl@tum.de>2018-07-04 13:34:05 +0000
commit06787e3d57b9ee0cc5e3bf5003b2f95f4c357c9a (patch)
treeba51dd8cf79a07d28887feffee9b7b03df82d2fa
parent1d7006dc77d3ac7d4b6a2392bc8436f69a7244de (diff)
downloadclang-06787e3d57b9ee0cc5e3bf5003b2f95f4c357c9a.tar.gz
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336269 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ASTImporter.cpp83
-rw-r--r--unittests/AST/ASTImporterTest.cpp60
2 files changed, 106 insertions, 37 deletions
diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp
index 37ddfea7be..bc75d80a55 100644
--- a/lib/AST/ASTImporter.cpp
+++ b/lib/AST/ASTImporter.cpp
@@ -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;
diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp
index b1e6e42b5a..dfcb6c1893 100644
--- a/unittests/AST/ASTImporterTest.cpp
+++ b/unittests/AST/ASTImporterTest.cpp
@@ -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)