diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -1800,15 +1800,23 @@ return; if (Entry.isFile()) { SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc(); - if (IncludeLoc.isInvalid()) + bool IncludedInFID = + (IncludeLoc.isValid() && isInFileID(IncludeLoc, FID)) || + // Predefined header doesn't have a valid include location in main + // file, but any files created by it should still be skipped when + // computing macro args expanded in the main file. + (FID == MainFileID && Entry.getFile().Filename == ""); + if (IncludedInFID) { + // Skip the files/macros of the #include'd file, we only care about + // macros that lexed macro arguments from our file. + if (Entry.getFile().NumCreatedFIDs) + ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/; continue; - if (!isInFileID(IncludeLoc, FID)) - return; // No more files/macros that may be "contained" in this file. - - // Skip the files/macros of the #include'd file, we only care about macros - // that lexed macro arguments from our file. - if (Entry.getFile().NumCreatedFIDs) - ID += Entry.getFile().NumCreatedFIDs - 1/*because of next ++ID*/; + } else if (IncludeLoc.isValid()) { + // If file was included but not from FID, there is no more files/macros + // that may be "contained" in this file. + return; + } continue; } diff --git a/clang/lib/Lex/PPLexerChange.cpp b/clang/lib/Lex/PPLexerChange.cpp --- a/clang/lib/Lex/PPLexerChange.cpp +++ b/clang/lib/Lex/PPLexerChange.cpp @@ -415,7 +415,10 @@ } if (!isEndOfMacro && CurPPLexer && - SourceMgr.getIncludeLoc(CurPPLexer->getFileID()).isValid()) { + (SourceMgr.getIncludeLoc(CurPPLexer->getFileID()).isValid() || + // Predefines file doesn't have a valid include location. + (PredefinesFileID.isValid() && + CurPPLexer->getFileID() == PredefinesFileID))) { // Notify SourceManager to record the number of FileIDs that were created // during lexing of the #include'd file. unsigned NumFIDs = diff --git a/clang/unittests/Basic/SourceManagerTest.cpp b/clang/unittests/Basic/SourceManagerTest.cpp --- a/clang/unittests/Basic/SourceManagerTest.cpp +++ b/clang/unittests/Basic/SourceManagerTest.cpp @@ -294,10 +294,16 @@ TrivialModuleLoader ModLoader; HeaderSearch HeaderInfo(std::make_shared(), SourceMgr, Diags, LangOpts, &*Target); + Preprocessor PP(std::make_shared(), Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader, /*IILookup =*/nullptr, /*OwnsHeaderSearch =*/false); + // Ensure we can get expanded locations in presence of implicit includes. + // These are different than normal includes since predefines buffer doesn't + // have a valid insertion location. + PP.setPredefines("#include \"/implicit-header.h\""); + FileMgr.getVirtualFile("/implicit-header.h", 0, 0); PP.Initialize(*Target); PP.EnterMainSourceFile(); diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp --- a/clang/unittests/Lex/LexerTest.cpp +++ b/clang/unittests/Lex/LexerTest.cpp @@ -556,4 +556,17 @@ EXPECT_THAT(GeneratedByNextToken, ElementsAre("abcd", "=", "0", ";", "int", "xyz", "=", "abcd", ";")); } + +TEST_F(LexerTest, CreatedFIDCountForPredefinedBuffer) { + TrivialModuleLoader ModLoader; + auto PP = CreatePP("", ModLoader); + while (1) { + Token tok; + PP->Lex(tok); + if (tok.is(tok::eof)) + break; + } + EXPECT_EQ(SourceMgr.getNumCreatedFIDsForFileID(PP->getPredefinesFileID()), + 1U); +} } // anonymous namespace