Skip to content

Commit a37734f

Browse files
committed
[ASTImporter] Prevent the ASTImporter from creating multiple main FileIDs.
Summary: When importing the main FileID the ASTImporter currently gives it no include location. This means that any SourceLocations produced for this FileID look to Clang as if they are coming from the main FileID (as the main FileID has no include location). Clang seems to expect that there is only one main FileID in one translation unit (which makes sense during normal compilation), so this behavior leads to several problems when producing diagnostics, one being that when calling `SourceManager::isBeforeInTranslationUnit` on two SourceLocations that come from two different ASTContext instances, Clang fails to sort the SourceLocations as the include chains of the FileIDs don't end up in a single FileID. This causes that Clang crashes with "Unsortable locations found" in this function. This patch gives any imported main FileIDs the main FileID of the To ASTContext as its include location. This allows Clang to sort all imported SourceLocations as now all include chains point to the main FileID of the To ASTContext. The exact include location is currently set to the start of the To main file (just because that should always be a valid SourceLocation). Reviewers: martong, a_sidorin, a.sidorin, shafik, balazske Reviewed By: martong, a_sidorin, shafik Subscribers: balazske, rnkovacs, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D74542
1 parent 69906fe commit a37734f

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

clang/lib/AST/ASTImporter.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8479,6 +8479,15 @@ Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) {
84798479
if (!ToIncludeLoc)
84808480
return ToIncludeLoc.takeError();
84818481

8482+
// Every FileID that is not the main FileID needs to have a valid include
8483+
// location so that the include chain points to the main FileID. When
8484+
// importing the main FileID (which has no include location), we need to
8485+
// create a fake include location in the main file to keep this property
8486+
// intact.
8487+
SourceLocation ToIncludeLocOrFakeLoc = *ToIncludeLoc;
8488+
if (FromID == FromSM.getMainFileID())
8489+
ToIncludeLocOrFakeLoc = ToSM.getLocForStartOfFile(ToSM.getMainFileID());
8490+
84828491
if (Cache->OrigEntry && Cache->OrigEntry->getDir()) {
84838492
// FIXME: We probably want to use getVirtualFile(), so we don't hit the
84848493
// disk again
@@ -8490,7 +8499,7 @@ Expected<FileID> ASTImporter::Import(FileID FromID, bool IsBuiltin) {
84908499
// point to a valid file and we get no Entry here. In this case try with
84918500
// the memory buffer below.
84928501
if (Entry)
8493-
ToID = ToSM.createFileID(*Entry, *ToIncludeLoc,
8502+
ToID = ToSM.createFileID(*Entry, ToIncludeLocOrFakeLoc,
84948503
FromSLoc.getFile().getFileCharacteristic());
84958504
}
84968505
}

clang/unittests/AST/ASTImporterTest.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5845,6 +5845,48 @@ TEST_P(ImportAutoFunctions, ReturnWithTypeInSwitch) {
58455845
EXPECT_TRUE(isa<AutoType>(To->getReturnType()));
58465846
}
58475847

5848+
struct ImportSourceLocations : ASTImporterOptionSpecificTestBase {};
5849+
5850+
TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {
5851+
// Tests that the FileID tree structure (with the links being the include
5852+
// chains) is preserved while importing other files (which need to be
5853+
// added to this structure with fake include locations.
5854+
5855+
SourceLocation Location1;
5856+
{
5857+
auto Pattern = varDecl(hasName("X"));
5858+
Decl *FromTU = getTuDecl("int X;", Lang_C, "input0.c");
5859+
auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5860+
5861+
Location1 = Import(FromD, Lang_C)->getLocation();
5862+
}
5863+
SourceLocation Location2;
5864+
{
5865+
auto Pattern = varDecl(hasName("Y"));
5866+
Decl *FromTU = getTuDecl("int Y;", Lang_C, "input1.c");
5867+
auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern);
5868+
5869+
Location2 = Import(FromD, Lang_C)->getLocation();
5870+
}
5871+
5872+
SourceManager &ToSM = ToAST->getSourceManager();
5873+
FileID FileID1 = ToSM.getFileID(Location1);
5874+
FileID FileID2 = ToSM.getFileID(Location2);
5875+
5876+
// Check that the imported files look like as if they were included from the
5877+
// start of the main file.
5878+
SourceLocation FileStart = ToSM.getLocForStartOfFile(ToSM.getMainFileID());
5879+
EXPECT_NE(FileID1, ToSM.getMainFileID());
5880+
EXPECT_NE(FileID2, ToSM.getMainFileID());
5881+
EXPECT_EQ(ToSM.getIncludeLoc(FileID1), FileStart);
5882+
EXPECT_EQ(ToSM.getIncludeLoc(FileID2), FileStart);
5883+
5884+
// Let the SourceManager check the order of the locations. The order should
5885+
// be the order in which the declarations are imported.
5886+
EXPECT_TRUE(ToSM.isBeforeInTranslationUnit(Location1, Location2));
5887+
EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1));
5888+
}
5889+
58485890
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
58495891
DefaultTestValuesForRunOptions, );
58505892

@@ -5903,5 +5945,8 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
59035945
INSTANTIATE_TEST_CASE_P(ParameterizedTests, LLDBLookupTest,
59045946
DefaultTestValuesForRunOptions, );
59055947

5948+
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportSourceLocations,
5949+
DefaultTestValuesForRunOptions, );
5950+
59065951
} // end namespace ast_matchers
59075952
} // end namespace clang

0 commit comments

Comments
 (0)