Skip to content

Commit 11d612a

Browse files
committed
[clang][Preprocessor] Replace the slow translateFile call by a new, faster isMainFile check
The commit 3c28a2d introduced the check that checks if we're trying to re-enter a main file when building a preamble. Unfortunately this slowed down the preamble compilation by 80-90% in some test cases, as translateFile is really slow. This change checks to see if the FileEntry is the main file without calling translateFile, but by using the new isMainFile check instead. This speeds up preamble building by 1.5-2x for certain test cases that we have. rdar://59361291 Differential Revision: https://reviews.llvm.org/D79834
1 parent 428d0b6 commit 11d612a

File tree

4 files changed

+38
-2
lines changed

4 files changed

+38
-2
lines changed

clang/include/clang/Basic/SourceManager.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,11 @@ class SourceManager : public RefCountedBase<SourceManager> {
813813
MainFileID = FID;
814814
}
815815

816+
/// Returns true when the given FileEntry corresponds to the main file.
817+
///
818+
/// The main file should be set prior to calling this function.
819+
bool isMainFile(FileEntryRef SourceFile);
820+
816821
/// Set the file ID for the precompiled preamble.
817822
void setPreambleFileID(FileID Preamble) {
818823
assert(PreambleFileID.isInvalid() && "PreambleFileID already set!");

clang/lib/Basic/SourceManager.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,14 @@ void SourceManager::clearIDTables() {
389389
createExpansionLoc(SourceLocation(), SourceLocation(), SourceLocation(), 1);
390390
}
391391

392+
bool SourceManager::isMainFile(FileEntryRef SourceFile) {
393+
assert(MainFileID.isValid() && "expected initialized SourceManager");
394+
auto FE = getFileEntryRefForID(MainFileID);
395+
if (!FE)
396+
return false;
397+
return FE->getUID() == SourceFile.getUID();
398+
}
399+
392400
void SourceManager::initializeForReplay(const SourceManager &Old) {
393401
assert(MainFileID.isInvalid() && "expected uninitialized SourceManager");
394402

clang/lib/Lex/PPDirectives.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2054,8 +2054,7 @@ Preprocessor::ImportAction Preprocessor::HandleHeaderIncludeOrImport(
20542054
// some directives (e.g. #endif of a header guard) will never be seen.
20552055
// Since this will lead to confusing errors, avoid the inclusion.
20562056
if (Action == Enter && File && PreambleConditionalStack.isRecording() &&
2057-
SourceMgr.translateFile(&File->getFileEntry()) ==
2058-
SourceMgr.getMainFileID()) {
2057+
SourceMgr.isMainFile(*File)) {
20592058
Diag(FilenameTok.getLocation(),
20602059
diag::err_pp_including_mainfile_in_preamble);
20612060
return {ImportAction::None};

clang/unittests/Basic/SourceManagerTest.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,30 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
491491
EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[10].Loc, Macros[11].Loc));
492492
}
493493

494+
TEST_F(SourceManagerTest, isMainFile) {
495+
const char *Source = "int x;";
496+
497+
std::unique_ptr<llvm::MemoryBuffer> Buf =
498+
llvm::MemoryBuffer::getMemBuffer(Source);
499+
const FileEntry *SourceFile =
500+
FileMgr.getVirtualFile("mainFile.cpp", Buf->getBufferSize(), 0);
501+
SourceMgr.overrideFileContents(SourceFile, std::move(Buf));
502+
503+
std::unique_ptr<llvm::MemoryBuffer> Buf2 =
504+
llvm::MemoryBuffer::getMemBuffer(Source);
505+
const FileEntry *SecondFile =
506+
FileMgr.getVirtualFile("file2.cpp", Buf2->getBufferSize(), 0);
507+
SourceMgr.overrideFileContents(SecondFile, std::move(Buf2));
508+
509+
FileID MainFileID = SourceMgr.getOrCreateFileID(SourceFile, SrcMgr::C_User);
510+
SourceMgr.setMainFileID(MainFileID);
511+
512+
EXPECT_TRUE(SourceMgr.isMainFile(FileEntryRef("mainFile.cpp", *SourceFile)));
513+
EXPECT_TRUE(
514+
SourceMgr.isMainFile(FileEntryRef("anotherName.cpp", *SourceFile)));
515+
EXPECT_FALSE(SourceMgr.isMainFile(FileEntryRef("mainFile.cpp", *SecondFile)));
516+
}
517+
494518
#endif
495519

496520
} // anonymous namespace

0 commit comments

Comments
 (0)