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 @@ -1799,6 +1799,14 @@ if (Invalid) return; if (Entry.isFile()) { + // Predefined header doesn't have a valid include location in main faile, + // but any files created by it should still be skipped when computing + // macro args expanded in the main file. + if (Entry.getFile().Filename == "" && FID == getMainFileID()) { + if (Entry.getFile().NumCreatedFIDs) + ID += Entry.getFile().NumCreatedFIDs - 1 /*because of next ++ID*/; + continue; + } SourceLocation IncludeLoc = Entry.getFile().getIncludeLoc(); if (IncludeLoc.isInvalid()) 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,9 @@ } if (!isEndOfMacro && CurPPLexer && - SourceMgr.getIncludeLoc(CurPPLexer->getFileID()).isValid()) { + (SourceMgr.getIncludeLoc(CurPPLexer->getFileID()).isValid() || + // Predefines file doesn't have a valid include location. + CurPPLexer->FID == getPredefinesFileID())) { // 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