Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -7029,19 +7029,13 @@ 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 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) { @@ -7049,41 +7043,56 @@ } FileID ASTImporter::Import(FileID FromID) { - llvm::DenseMap::iterator Pos - = ImportedFileIDs.find(FromID); + llvm::DenseMap::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 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 ToBuf = + llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), + FromBuf->getBufferIdentifier()); + ToID = ToSM.createFileID(std::move(ToBuf), + FromSLoc.getFile().getFileCharacteristic()); + } } ImportedFileIDs[FromID] = ToID; Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -1518,6 +1518,66 @@ 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().match(FromTU, functionDecl()); + auto ToD = Import(FromD, Lang_CXX); + + auto ToLHS = LastDeclMatcher().match(ToD, declRefExpr()); + auto FromLHS = LastDeclMatcher().match(FromTU, declRefExpr()); + auto ToRHS = LastDeclMatcher().match(ToD, integerLiteral()); + auto FromRHS = + LastDeclMatcher().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().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)