diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -418,7 +418,7 @@ Preprocessor *PP = &Compiler.getPreprocessor(); Preprocessor *ModuleExpanderPP = PP; - if (Context.getLangOpts().Modules && OverlayFS != nullptr) { + if (Context.canEnableModularHeadersExpansion() && Context.getLangOpts().Modules && OverlayFS != nullptr) { auto ModuleExpander = std::make_unique( &Compiler, OverlayFS); ModuleExpanderPP = ModuleExpander->getPreprocessor(); diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.h @@ -70,7 +70,8 @@ public: /// Initializes \c ClangTidyContext instance. ClangTidyContext(std::unique_ptr OptionsProvider, - bool AllowEnablingAnalyzerAlphaCheckers = false); + bool AllowEnablingAnalyzerAlphaCheckers = false, + bool DisableModularHeadersExpansion = false); /// Sets the DiagnosticsEngine that diag() will emit diagnostics to. // FIXME: this is required initialization, and should be a constructor param. // Fix the context -> diag engine -> consumer -> context initialization cycle. @@ -198,6 +199,10 @@ return AllowEnablingAnalyzerAlphaCheckers; } + bool canEnableModularHeadersExpansion() const { + return !DisableModularHeadersExpansion; + } + void setSelfContainedDiags(bool Value) { SelfContainedDiags = Value; } bool areDiagsSelfContained() const { return SelfContainedDiags; } @@ -245,6 +250,7 @@ std::string ProfilePrefix; bool AllowEnablingAnalyzerAlphaCheckers; + bool DisableModularHeadersExpansion; bool SelfContainedDiags; diff --git a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp --- a/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidyDiagnosticConsumer.cpp @@ -161,10 +161,12 @@ ClangTidyContext::ClangTidyContext( std::unique_ptr OptionsProvider, - bool AllowEnablingAnalyzerAlphaCheckers) + bool AllowEnablingAnalyzerAlphaCheckers, + bool DisableModularHeadersExpansion) : DiagEngine(nullptr), OptionsProvider(std::move(OptionsProvider)), Profile(false), AllowEnablingAnalyzerAlphaCheckers(AllowEnablingAnalyzerAlphaCheckers), + DisableModularHeadersExpansion(DisableModularHeadersExpansion), SelfContainedDiags(false) { // Before the first translation unit we can get errors related to command-line // parsing, use empty string for the file name in this case. diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp --- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -263,6 +263,16 @@ cl::init(false), cl::Hidden, cl::cat(ClangTidyCategory)); +static cl::opt + DisableModularHeadersExpansion("disable-modular-headers-expansion", desc(R"( +Experimental option: Disable modular header +expansion in C++20 and above. This option +serves as a workaround for addressing known +issues #50087 and #62447. +)"), + cl::init(false), cl::Hidden, + cl::cat(ClangTidyCategory)); + static cl::opt ExportFixes("export-fixes", desc(R"( YAML file to store suggested fixes in. The stored fixes can be applied to the input source @@ -659,7 +669,8 @@ llvm::InitializeAllAsmParsers(); ClangTidyContext Context(std::move(OwningOptionsProvider), - AllowEnablingAnalyzerAlphaCheckers); + AllowEnablingAnalyzerAlphaCheckers, + DisableModularHeadersExpansion); std::vector Errors = runClangTidy(Context, OptionsParser->getCompilations(), PathList, BaseFS, FixNotes, EnableCheckProfile, ProfilePrefix);