[clang-tools-extra] [clangd] Do not collect macros when clang-tidy checks call into the preprocessor (PR #106329)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Aug 27 19:52:54 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-tools-extra
Author: Nathan Ridge (HighCommander4)
<details>
<summary>Changes</summary>
Fixes https://github.com/llvm/llvm-project/issues/99617
---
Full diff: https://github.com/llvm/llvm-project/pull/106329.diff
4 Files Affected:
- (modified) clang-tools-extra/clangd/CollectMacros.cpp (+1)
- (modified) clang-tools-extra/clangd/CollectMacros.h (+8)
- (modified) clang-tools-extra/clangd/ParsedAST.cpp (+7-1)
- (modified) clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp (+17)
``````````diff
diff --git a/clang-tools-extra/clangd/CollectMacros.cpp b/clang-tools-extra/clangd/CollectMacros.cpp
index c5ba8d903ba482..96298ee3ea50ae 100644
--- a/clang-tools-extra/clangd/CollectMacros.cpp
+++ b/clang-tools-extra/clangd/CollectMacros.cpp
@@ -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);
diff --git a/clang-tools-extra/clangd/CollectMacros.h b/clang-tools-extra/clangd/CollectMacros.h
index e3900c08e5df7b..e7198641d8d53c 100644
--- a/clang-tools-extra/clangd/CollectMacros.h
+++ b/clang-tools-extra/clangd/CollectMacros.h
@@ -82,6 +82,14 @@ class CollectMainFileMacros : public PPCallbacks {
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);
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp
index 2bd1fbcad2ada0..ee012846da9f5e 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -681,7 +681,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));
@@ -702,6 +704,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).
diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
index 25d2f03e0b366b..096f77e414f5a5 100644
--- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp
@@ -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:
``````````
</details>
https://github.com/llvm/llvm-project/pull/106329
More information about the cfe-commits
mailing list