Skip to content

Commit f8fb043

Browse files
committed
[clang] Cleanup IncludeLocMap
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 fdca2c3 commit f8fb043

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-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: 56 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,61 @@ TEST_F(SourceManagerTest, loadedSLocEntryIsInTheSameTranslationUnit) {
453454

454455
#if defined(LLVM_ON_UNIX)
455456

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

0 commit comments

Comments
 (0)