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 @@ -136,22 +136,33 @@ } std::vector -collectMacroReferences(ParsedAST &AST) { +convertMacroReferences(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( - {Tok.location(), - include_cleaner::Macro{/*Name=*/PP.getIdentifierInfo(Tok.text(SM)), - DefLoc}, - include_cleaner::RefType::Explicit}); + std::vector Macros; + for (const auto &MAndRefs : AST.getMacros().MacroRefs) { + for (const auto &Ref : MAndRefs.second) { + auto L = sourceLocationInMainFile(SM, Ref.Rng.start); + if (!L) { + llvm::consumeError(L.takeError()); + continue; + } + if (const auto *Tok = + AST.getTokens().spelledTokenAt(*L)) { + auto Macro = locateMacroAt(*Tok, PP); + if (!Macro) + continue; + + if (auto DefLoc = Macro->Info->getDefinitionLoc(); DefLoc.isValid()) + Macros.push_back( + {Tok->location(), + include_cleaner::Macro{ + /*Name=*/PP.getIdentifierInfo(Tok->text(SM)), DefLoc}, + Ref.InConditionalDirective + ? include_cleaner::RefType::Implicit + : include_cleaner::RefType::Explicit}); + } + } } return Macros; } @@ -360,7 +371,7 @@ const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID()); std::vector Macros = - collectMacroReferences(AST); + convertMacroReferences(AST); std::vector MissingIncludes; llvm::DenseSet Used; trace::Span Tracer("include_cleaner::walkUsed"); 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 @@ -189,6 +189,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]]();