diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h --- a/clang-tools-extra/clangd/AST.h +++ b/clang-tools-extra/clangd/AST.h @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/MacroInfo.h" +#include "llvm/ADT/StringRef.h" namespace clang { class SourceManager; @@ -69,7 +70,7 @@ /// macro (e.g. a change in definition offset can result in a different USR). We /// could change these semantics in the future by reimplementing this funcure /// (e.g. avoid USR for macros). -llvm::Optional getSymbolID(const IdentifierInfo &II, +llvm::Optional getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI, const SourceManager &SM); diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp --- a/clang-tools-extra/clangd/AST.cpp +++ b/clang-tools-extra/clangd/AST.cpp @@ -203,13 +203,13 @@ return SymbolID(USR); } -llvm::Optional getSymbolID(const IdentifierInfo &II, +llvm::Optional getSymbolID(const llvm::StringRef MacroName, const MacroInfo *MI, const SourceManager &SM) { if (MI == nullptr) return None; llvm::SmallString<128> USR; - if (index::generateUSRForMacro(II.getName(), MI->getDefinitionLoc(), SM, USR)) + if (index::generateUSRForMacro(MacroName, MI->getDefinitionLoc(), SM, USR)) return None; return SymbolID(USR); } @@ -225,7 +225,7 @@ unsigned DifferentAt = 0; while (DifferentAt < MinLength && - CurrentParts[DifferentAt] == OriginalParts[DifferentAt]) { + CurrentParts[DifferentAt] == OriginalParts[DifferentAt]) { DifferentAt++; } @@ -235,15 +235,12 @@ return join(Result, "::"); } -std::string printType(const QualType QT, const DeclContext & Context){ +std::string printType(const QualType QT, const DeclContext &Context) { PrintingPolicy PP(Context.getParentASTContext().getPrintingPolicy()); PP.SuppressUnwrittenScope = 1; PP.SuppressTagKeyword = 1; - return shortenNamespace( - QT.getAsString(PP), - printNamespaceScope(Context) ); + return shortenNamespace(QT.getAsString(PP), printNamespaceScope(Context)); } - } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp --- a/clang-tools-extra/clangd/CodeComplete.cpp +++ b/clang-tools-extra/clangd/CodeComplete.cpp @@ -492,7 +492,7 @@ return clang::clangd::getSymbolID(R.Declaration); } case CodeCompletionResult::RK_Macro: - return clang::clangd::getSymbolID(*R.Macro, R.MacroDefInfo, SM); + return clang::clangd::getSymbolID(R.Macro->getName(), R.MacroDefInfo, SM); case CodeCompletionResult::RK_Keyword: return None; } @@ -1765,8 +1765,7 @@ Options.IncludeBriefComments = false; IncludeStructure PreambleInclusions; // Unused for signatureHelp semaCodeComplete( - std::make_unique(Options, Index, Result), - Options, + std::make_unique(Options, Index, Result), Options, {FileName, Command, Preamble, Contents, *Offset, std::move(VFS)}); return Result; } diff --git a/clang-tools-extra/clangd/CollectMacros.h b/clang-tools-extra/clangd/CollectMacros.h --- a/clang-tools-extra/clangd/CollectMacros.h +++ b/clang-tools-extra/clangd/CollectMacros.h @@ -9,10 +9,13 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTEDMACROS_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_COLLECTEDMACROS_H +#include "AST.h" #include "Protocol.h" #include "SourceCode.h" +#include "index/SymbolID.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Lex/PPCallbacks.h" +#include "llvm/ADT/DenseMap.h" #include namespace clang { @@ -23,6 +26,7 @@ // Instead of storing SourceLocation, we have to store the token range because // SourceManager from preamble is not available when we build the AST. std::vector Ranges; + llvm::DenseMap> MacroRefs; }; /// Collects macro references (e.g. definitions, expansions) in the main file. @@ -39,6 +43,12 @@ void FileChanged(SourceLocation Loc, FileChangeReason, SrcMgr::CharacteristicKind, FileID) override { InMainFile = isInsideMainFile(Loc, SM); + if (InMainFile) { + auto MainFilePath = + getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM); + if (MainFilePath) + MainFileURI = URIForFile::canonicalize(*MainFilePath, *MainFilePath); + } } void MacroDefined(const Token &MacroName, const MacroDirective *MD) override { @@ -82,9 +92,17 @@ if (auto Range = getTokenRange(SM, LangOpts, Loc)) { Out.Names.insert(MacroNameTok.getIdentifierInfo()->getName()); Out.Ranges.push_back(*Range); + if (auto SID = getSymbolID(MacroNameTok.getIdentifierInfo()->getName(), + MI, SM)) { + Location Loc; + Loc.uri = MainFileURI; + Loc.range = *Range; + Out.MacroRefs[*SID].insert(Loc); + } } } const SourceManager &SM; + URIForFile MainFileURI; const LangOptions &LangOpts; bool InMainFile = true; MainFileMacros &Out; diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -21,6 +21,7 @@ #include "index/Merge.h" #include "index/Relation.h" #include "index/SymbolCollector.h" +#include "index/SymbolID.h" #include "index/SymbolLocation.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" @@ -47,6 +48,7 @@ #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" +#include namespace clang { namespace clangd { @@ -891,7 +893,20 @@ } auto Loc = SM.getMacroArgExpandedLocation( getBeginningOfIdentifier(Pos, SM, AST.getASTContext().getLangOpts())); - // TODO: should we handle macros, too? + + // Handle macros. + if (auto Macro = locateMacroAt(Loc, AST.getPreprocessor())) { + if (auto MacroSID = getSymbolID(Macro->Name, Macro->Info, SM)) { + const auto &IDToRefs = AST.getMacros().MacroRefs; + auto Refs = IDToRefs.find(*MacroSID); + if (Refs != IDToRefs.end()) + Results.insert(Results.end(), Refs->second.begin(), Refs->second.end()); + } + if (Results.size() > Limit) + Results.resize(Limit); + return Results; + } + // We also show references to the targets of using-decls, so we include // DeclRelation::Underlying. DeclRelationSet Relations = DeclRelation::TemplatePattern | @@ -911,8 +926,7 @@ MainFileRefs.end()); for (const auto &Ref : MainFileRefs) { if (auto Range = - getTokenRange(AST.getASTContext().getSourceManager(), - AST.getASTContext().getLangOpts(), Ref.Loc)) { + getTokenRange(SM, AST.getASTContext().getLangOpts(), Ref.Loc)) { Location Result; Result.range = *Range; Result.uri = URIForFile::canonicalize(*MainFilePath, *MainFilePath); diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -377,7 +377,7 @@ Roles & static_cast(index::SymbolRole::Definition))) return true; - auto ID = getSymbolID(*Name, MI, SM); + auto ID = getSymbolID(Name->getName(), MI, SM); if (!ID) return true; @@ -473,14 +473,14 @@ // First, drop header guards. We can't identify these until EOF. for (const IdentifierInfo *II : IndexedMacros) { if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo()) - if (auto ID = getSymbolID(*II, MI, PP->getSourceManager())) + if (auto ID = getSymbolID(II->getName(), MI, PP->getSourceManager())) if (MI->isUsedForHeaderGuard()) Symbols.erase(*ID); } // Now increment refcounts. for (const IdentifierInfo *II : ReferencedMacros) { if (const auto *MI = PP->getMacroDefinition(II).getMacroInfo()) - if (auto ID = getSymbolID(*II, MI, PP->getSourceManager())) + if (auto ID = getSymbolID(II->getName(), MI, PP->getSourceManager())) IncRef(*ID); } } diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -2050,6 +2050,23 @@ } // namespace ns int main() { [[^ns]]::Foo foo; } )cpp", + + R"cpp(// Macros + #define [[FOO]](x,y) (x + y) + // FIXME: No references for nested macros. + #define BAR(x,y,z) (FOO(x, y) * FOO(y, z)) + int main() { + int x = [[FOO]](1, 2); + int y = [[FOO]]([[FO^O]](x, 1), [[FOO]](1, 1)); + int z = BAR(1, 2, 3); + } + #define FOO(x) (x + 1) + )cpp", + + R"cpp(// Macros: Cursor on definition. + #define [[F^OO]](x,y) (x + y) + int main() { int x = [[FOO]](1, 2); } + )cpp", }; for (const char *Test : Tests) { Annotations T(Test);