[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:
Rafael Stahl 2018-07-04 13:34:05 +00:00
parent da4a966e1c
commit 29f37fbb8b
2 changed files with 106 additions and 37 deletions

View File

@ -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;

View File

@ -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)