diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp --- a/clang-tools-extra/clangd/IncludeCleaner.cpp +++ b/clang-tools-extra/clangd/IncludeCleaner.cpp @@ -353,20 +353,29 @@ std::vector collectMacroReferences(ParsedAST &AST) { const auto &SM = AST.getSourceManager(); - // FIXME: !!this is a hacky way to collect macro references. - std::vector Macros; auto &PP = AST.getPreprocessor(); - for (const syntax::Token &Tok : - AST.getTokens().spelledTokens(SM.getMainFileID())) { - auto Macro = locateMacroAt(Tok, PP); - if (!Macro) - continue; - if (auto DefLoc = Macro->Info->getDefinitionLoc(); DefLoc.isValid()) - Macros.push_back( - {include_cleaner::Macro{/*Name=*/PP.getIdentifierInfo(Tok.text(SM)), - DefLoc}, - Tok.location(), include_cleaner::RefType::Explicit}); + std::vector Macros; + for (const auto &[_, Refs] : AST.getMacros().MacroRefs) { + for (const auto &Ref : Refs) { + SourceLocation Loc = SM.getLocForStartOfFile(SM.getMainFileID()) + .getLocWithOffset(Ref.StartOffset); + const auto *Tok = AST.getTokens().spelledTokenAt(Loc); + if (!Tok) + continue; + auto Macro = locateMacroAt(*Tok, PP); + if (!Macro) + continue; + + if (auto DefLoc = Macro->NameLoc; DefLoc.isValid()) + Macros.push_back( + {include_cleaner::Macro{ + /*Name=*/PP.getIdentifierInfo(Tok->text(SM)), DefLoc}, + Tok->location(), + Ref.InConditionalDirective ? include_cleaner::RefType::Ambiguous + : include_cleaner::RefType::Explicit}); + } } + return Macros; } diff --git a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp --- a/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp +++ b/clang-tools-extra/clangd/unittests/IncludeCleanerTests.cpp @@ -186,6 +186,10 @@ #define DEF(X) const Foo *X; #define BAZ(X) const X x +// No missing include insertion for ambiguous macro refs. +#if defined(FOO) +#endif + void foo() { $b[[b]]();