mirror of
https://github.com/intel/llvm.git
synced 2026-02-06 23:31:50 +08:00
[clangd] Do not collect macros when clang-tidy checks call into the preprocessor (#106329)
Fixes https://github.com/llvm/llvm-project/issues/99617
This commit is contained in:
@@ -32,6 +32,7 @@ void CollectMainFileMacros::add(const Token &MacroNameTok, const MacroInfo *MI,
|
||||
if (Loc.isInvalid() || Loc.isMacroID())
|
||||
return;
|
||||
|
||||
assert(isInsideMainFile(Loc, SM));
|
||||
auto Name = MacroNameTok.getIdentifierInfo()->getName();
|
||||
Out.Names.insert(Name);
|
||||
size_t Start = SM.getFileOffset(Loc);
|
||||
|
||||
@@ -82,6 +82,14 @@ public:
|
||||
|
||||
void SourceRangeSkipped(SourceRange R, SourceLocation EndifLoc) override;
|
||||
|
||||
// Called when the AST build is done to disable further recording
|
||||
// of macros by this class. This is needed because some clang-tidy
|
||||
// checks can trigger PP callbacks by calling directly into the
|
||||
// preprocessor. Such calls are not interleaved with FileChanged()
|
||||
// in the expected way, leading this class to erroneously process
|
||||
// macros that are not in the main file.
|
||||
void doneParse() { InMainFile = false; }
|
||||
|
||||
private:
|
||||
void add(const Token &MacroNameTok, const MacroInfo *MI,
|
||||
bool IsDefinition = false, bool InConditionalDirective = false);
|
||||
|
||||
@@ -688,7 +688,9 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
|
||||
Marks = Patch->marks();
|
||||
}
|
||||
auto &PP = Clang->getPreprocessor();
|
||||
PP.addPPCallbacks(std::make_unique<CollectMainFileMacros>(PP, Macros));
|
||||
auto MacroCollector = std::make_unique<CollectMainFileMacros>(PP, Macros);
|
||||
auto *MacroCollectorPtr = MacroCollector.get(); // so we can call doneParse()
|
||||
PP.addPPCallbacks(std::move(MacroCollector));
|
||||
|
||||
PP.addPPCallbacks(
|
||||
collectPragmaMarksCallback(Clang->getSourceManager(), Marks));
|
||||
@@ -709,6 +711,10 @@ ParsedAST::build(llvm::StringRef Filename, const ParseInputs &Inputs,
|
||||
log("Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
|
||||
toString(std::move(Err)));
|
||||
|
||||
// Disable the macro collector for the remainder of this function, e.g.
|
||||
// clang-tidy checkers.
|
||||
MacroCollectorPtr->doneParse();
|
||||
|
||||
// We have to consume the tokens before running clang-tidy to avoid collecting
|
||||
// tokens from running the preprocessor inside the checks (only
|
||||
// modernize-use-trailing-return-type does that today).
|
||||
|
||||
@@ -940,6 +940,23 @@ TEST(DiagnosticTest, ClangTidySelfContainedDiagsFormatting) {
|
||||
withFix(equalToFix(ExpectedFix2))))));
|
||||
}
|
||||
|
||||
TEST(DiagnosticsTest, ClangTidyCallingIntoPreprocessor) {
|
||||
std::string Main = R"cpp(
|
||||
extern "C" {
|
||||
#include "b.h"
|
||||
}
|
||||
)cpp";
|
||||
std::string Header = R"cpp(
|
||||
#define EXTERN extern
|
||||
EXTERN int waldo();
|
||||
)cpp";
|
||||
auto TU = TestTU::withCode(Main);
|
||||
TU.AdditionalFiles["b.h"] = Header;
|
||||
TU.ClangTidyProvider = addTidyChecks("modernize-use-trailing-return-type");
|
||||
// Check that no assertion failures occur during the build
|
||||
TU.build();
|
||||
}
|
||||
|
||||
TEST(DiagnosticsTest, Preprocessor) {
|
||||
// This looks like a preamble, but there's an #else in the middle!
|
||||
// Check that:
|
||||
|
||||
Reference in New Issue
Block a user