Skip to content

Commit a2a93f0

Browse files
authored
[clang] Cleanup IncludeLocMap (#106241)
CompilerInstance can re-use same SourceManager across multiple frontendactions. During this process it calls `SourceManager::clearIDTables` to reset any caches based on FileIDs. It didn't reset IncludeLocMap, resulting in wrong include locations for workflows that triggered multiple frontend-actions through same CompilerInstance.
1 parent 1b32c3e commit a2a93f0

File tree

2 files changed

+61
-0
lines changed

2 files changed

+61
-0
lines changed

clang/lib/Basic/SourceManager.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ void SourceManager::clearIDTables() {
350350
LastLineNoContentCache = nullptr;
351351
LastFileIDLookup = FileID();
352352

353+
IncludedLocMap.clear();
353354
if (LineTable)
354355
LineTable->clear();
355356

clang/unittests/Basic/SourceManagerTest.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "clang/Lex/PreprocessorOptions.h"
2121
#include "llvm/ADT/SmallString.h"
2222
#include "llvm/Config/llvm-config.h"
23+
#include "llvm/Support/MemoryBuffer.h"
2324
#include "llvm/Support/Process.h"
2425
#include "gtest/gtest.h"
2526
#include <cstddef>
@@ -453,6 +454,65 @@ TEST_F(SourceManagerTest, loadedSLocEntryIsInTheSameTranslationUnit) {
453454

454455
#if defined(LLVM_ON_UNIX)
455456

457+
// A single SourceManager instance is sometimes reused across multiple
458+
// compilations. This test makes sure we're resetting caches built for tracking
459+
// include locations that are based on FileIDs, to make sure we don't report
460+
// wrong include locations when FileIDs coincide between two different runs.
461+
TEST_F(SourceManagerTest, ResetsIncludeLocMap) {
462+
auto ParseFile = [&] {
463+
TrivialModuleLoader ModLoader;
464+
HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
465+
Diags, LangOpts, &*Target);
466+
Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
467+
SourceMgr, HeaderInfo, ModLoader,
468+
/*IILookup =*/nullptr,
469+
/*OwnsHeaderSearch =*/false);
470+
PP.Initialize(*Target);
471+
PP.EnterMainSourceFile();
472+
PP.LexTokensUntilEOF();
473+
EXPECT_FALSE(Diags.hasErrorOccurred());
474+
};
475+
476+
auto Buf = llvm::MemoryBuffer::getMemBuffer("");
477+
FileEntryRef HeaderFile =
478+
FileMgr.getVirtualFileRef("/foo.h", Buf->getBufferSize(), 0);
479+
SourceMgr.overrideFileContents(HeaderFile, std::move(Buf));
480+
481+
Buf = llvm::MemoryBuffer::getMemBuffer(R"cpp(#include "/foo.h")cpp");
482+
FileEntryRef BarFile =
483+
FileMgr.getVirtualFileRef("/bar.h", Buf->getBufferSize(), 0);
484+
SourceMgr.overrideFileContents(BarFile, std::move(Buf));
485+
SourceMgr.createFileID(BarFile, {}, clang::SrcMgr::C_User);
486+
487+
Buf = llvm::MemoryBuffer::getMemBuffer(R"cpp(#include "/foo.h")cpp");
488+
FileID MFID = SourceMgr.createFileID(std::move(Buf));
489+
SourceMgr.setMainFileID(MFID);
490+
491+
ParseFile();
492+
auto FooFID = SourceMgr.getOrCreateFileID(HeaderFile, clang::SrcMgr::C_User);
493+
auto IncFID = SourceMgr.getDecomposedIncludedLoc(FooFID).first;
494+
EXPECT_EQ(IncFID, MFID);
495+
496+
// Clean up source-manager state before we start next parse.
497+
SourceMgr.clearIDTables();
498+
499+
// Set up a new main file.
500+
Buf = llvm::MemoryBuffer::getMemBuffer(R"cpp(
501+
// silly comment 42
502+
#include "/bar.h")cpp");
503+
MFID = SourceMgr.createFileID(std::move(Buf));
504+
SourceMgr.setMainFileID(MFID);
505+
506+
ParseFile();
507+
// Make sure foo.h got the same file-id in both runs.
508+
EXPECT_EQ(FooFID,
509+
SourceMgr.getOrCreateFileID(HeaderFile, clang::SrcMgr::C_User));
510+
auto BarFID = SourceMgr.getOrCreateFileID(BarFile, clang::SrcMgr::C_User);
511+
IncFID = SourceMgr.getDecomposedIncludedLoc(FooFID).first;
512+
// Check that includer is bar.h during this run.
513+
EXPECT_EQ(IncFID, BarFID);
514+
}
515+
456516
TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
457517
const char *header =
458518
"#define FM(x,y) x\n";

0 commit comments

Comments
 (0)