diff --git a/clang-tools-extra/clangd/FindTarget.h b/clang-tools-extra/clangd/FindTarget.h --- a/clang-tools-extra/clangd/FindTarget.h +++ b/clang-tools-extra/clangd/FindTarget.h @@ -75,15 +75,19 @@ /// / \ /// RecordDecl S TypeAliasDecl T /// +/// Note that this function only returns NamedDecls. Generally other decls +/// don't have references in this sense, just the node itself. +/// If callers want to support such decls, they should cast the node directly. +/// /// FIXME: some AST nodes cannot be DynTypedNodes, these cannot be specified. -llvm::SmallVector +llvm::SmallVector targetDecl(const ast_type_traits::DynTypedNode &, DeclRelationSet Mask); /// Similar to targetDecl(), however instead of applying a filter, all possible /// decls are returned along with their DeclRelationSets. /// This is suitable for indexing, where everything is recorded and filtering /// is applied later. -llvm::SmallVector, 1> +llvm::SmallVector, 1> allTargetDecls(const ast_type_traits::DynTypedNode &); enum class DeclRelation : unsigned { diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -119,10 +119,10 @@ struct TargetFinder { using RelSet = DeclRelationSet; using Rel = DeclRelation; - llvm::SmallDenseMap Decls; + llvm::SmallDenseMap Decls; RelSet Flags; - static const Decl *getTemplatePattern(const Decl *D) { + static const NamedDecl *getTemplatePattern(const NamedDecl *D) { if (const CXXRecordDecl *CRD = dyn_cast(D)) { return CRD->getTemplateInstantiationPattern(); } else if (const FunctionDecl *FD = dyn_cast(D)) { @@ -134,12 +134,12 @@ } else if (const auto *ED = dyn_cast(D)) { return ED->getInstantiatedFromMemberEnum(); } else if (isa(D) || isa(D)) { - const auto *ND = cast(D); - if (const DeclContext *Parent = dyn_cast_or_null( - getTemplatePattern(llvm::cast(ND->getDeclContext())))) - for (const NamedDecl *BaseND : Parent->lookup(ND->getDeclName())) - if (!BaseND->isImplicit() && BaseND->getKind() == ND->getKind()) - return BaseND; + if (const auto *Parent = llvm::dyn_cast(D->getDeclContext())) + if (const DeclContext *ParentPat = + dyn_cast_or_null(getTemplatePattern(Parent))) + for (const NamedDecl *BaseND : ParentPat->lookup(D->getDeclName())) + if (!BaseND->isImplicit() && BaseND->getKind() == D->getKind()) + return BaseND; } else if (const auto *ECD = dyn_cast(D)) { if (const auto *ED = dyn_cast(ECD->getDeclContext())) { if (const EnumDecl *Pattern = ED->getInstantiatedFromMemberEnum()) { @@ -156,14 +156,15 @@ nodeToString(ast_type_traits::DynTypedNode::create(Node))); } - void report(const Decl *D, RelSet Flags) { + void report(const NamedDecl *D, RelSet Flags) { dlog("--> [{0}] {1}", Flags, nodeToString(ast_type_traits::DynTypedNode::create(*D))); Decls[D] |= Flags; } public: - void add(const Decl *D, RelSet Flags) { + void add(const Decl *Dcl, RelSet Flags) { + const NamedDecl *D = llvm::dyn_cast(Dcl); if (!D) return; debug(*D, Flags); @@ -405,7 +406,7 @@ } // namespace -llvm::SmallVector, 1> +llvm::SmallVector, 1> allTargetDecls(const ast_type_traits::DynTypedNode &N) { dlog("allTargetDecls({0})", nodeToString(N)); TargetFinder Finder; @@ -428,9 +429,9 @@ return {Finder.Decls.begin(), Finder.Decls.end()}; } -llvm::SmallVector +llvm::SmallVector targetDecl(const ast_type_traits::DynTypedNode &N, DeclRelationSet Mask) { - llvm::SmallVector Result; + llvm::SmallVector Result; for (const auto &Entry : allTargetDecls(N)) { if (!(Entry.second & ~Mask)) Result.push_back(Entry.first); @@ -456,12 +457,12 @@ if (D.second & ~Mask) continue; if (D.second & DeclRelation::TemplatePattern) { - TemplatePatterns.push_back(llvm::cast(D.first)); + TemplatePatterns.push_back(D.first); continue; } if (D.second & DeclRelation::TemplateInstantiation) SeenTemplateInstantiations = true; - Targets.push_back(llvm::cast(D.first)); + Targets.push_back(D.first); } if (!SeenTemplateInstantiations) Targets.insert(Targets.end(), TemplatePatterns.begin(), 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 @@ -53,7 +53,7 @@ // - for kinds that allow multiple definitions (e.g. namespaces), return nullptr // Kinds of nodes that always return nullptr here will not have definitions // reported by locateSymbolAt(). -const Decl *getDefinition(const Decl *D) { +const NamedDecl *getDefinition(const NamedDecl *D) { assert(D); // Decl has one definition that we can find. if (const auto *TD = dyn_cast(D)) @@ -129,13 +129,14 @@ return Merged.CanonicalDeclaration; } -std::vector getDeclAtPosition(ParsedAST &AST, SourceLocation Pos, - DeclRelationSet Relations) { +std::vector getDeclAtPosition(ParsedAST &AST, + SourceLocation Pos, + DeclRelationSet Relations) { FileID FID; unsigned Offset; std::tie(FID, Offset) = AST.getSourceManager().getDecomposedSpellingLoc(Pos); SelectionTree Selection(AST.getASTContext(), AST.getTokens(), Offset); - std::vector Result; + std::vector Result; if (const SelectionTree::Node *N = Selection.commonAncestor()) { auto Decls = targetDecl(N->ASTNode, Relations); Result.assign(Decls.begin(), Decls.end()); @@ -251,9 +252,9 @@ // Emit all symbol locations (declaration or definition) from AST. DeclRelationSet Relations = DeclRelation::TemplatePattern | DeclRelation::Alias; - for (const Decl *D : getDeclAtPosition(AST, SourceLoc, Relations)) { - const Decl *Def = getDefinition(D); - const Decl *Preferred = Def ? Def : D; + for (const NamedDecl *D : getDeclAtPosition(AST, SourceLoc, Relations)) { + const NamedDecl *Def = getDefinition(D); + const NamedDecl *Preferred = Def ? Def : D; // If we're at the point of declaration of a template specialization, // it's more useful to navigate to the template declaration. @@ -272,8 +273,7 @@ continue; Result.emplace_back(); - if (auto *ND = dyn_cast(Preferred)) - Result.back().Name = printName(AST.getASTContext(), *ND); + Result.back().Name = printName(AST.getASTContext(), *D); Result.back().PreferredDeclaration = *Loc; // Preferred is always a definition if possible, so this check works. if (Def == Preferred) @@ -332,9 +332,9 @@ }; ReferenceFinder(ASTContext &AST, Preprocessor &PP, - const std::vector &TargetDecls) + const std::vector &TargetDecls) : AST(AST) { - for (const Decl *D : TargetDecls) + for (const NamedDecl *D : TargetDecls) CanonicalTargets.insert(D->getCanonicalDecl()); } @@ -372,7 +372,7 @@ }; std::vector -findRefs(const std::vector &Decls, ParsedAST &AST) { +findRefs(const std::vector &Decls, ParsedAST &AST) { ReferenceFinder RefFinder(AST.getASTContext(), AST.getPreprocessor(), Decls); index::IndexingOptions IndexOpts; IndexOpts.SystemSymbolFilter = @@ -506,18 +506,16 @@ // DeclRelation::Underlying. DeclRelationSet Relations = DeclRelation::TemplatePattern | DeclRelation::Alias | DeclRelation::Underlying; - for (const Decl *D : getDeclAtPosition(AST, Loc, Relations)) { + for (const NamedDecl *D : getDeclAtPosition(AST, Loc, Relations)) { SymbolDetails NewSymbol; - if (const NamedDecl *ND = dyn_cast(D)) { - std::string QName = printQualifiedName(*ND); - std::tie(NewSymbol.containerName, NewSymbol.name) = - splitQualifiedName(QName); - - if (NewSymbol.containerName.empty()) { - if (const auto *ParentND = - dyn_cast_or_null(ND->getDeclContext())) - NewSymbol.containerName = printQualifiedName(*ParentND); - } + std::string QName = printQualifiedName(*D); + std::tie(NewSymbol.containerName, NewSymbol.name) = + splitQualifiedName(QName); + + if (NewSymbol.containerName.empty()) { + if (const auto *ParentND = + dyn_cast_or_null(D->getDeclContext())) + NewSymbol.containerName = printQualifiedName(*ParentND); } llvm::SmallString<32> USR; if (!index::generateUSRForDecl(D, USR)) { @@ -680,7 +678,7 @@ if (Decls.empty()) return nullptr; - const Decl *D = Decls[0]; + const NamedDecl *D = Decls[0]; if (const VarDecl *VD = dyn_cast(D)) { // If this is a variable, use the type of the variable. diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -86,15 +86,12 @@ return {}; llvm::DenseSet Result; - for (const auto *D : + for (const NamedDecl *D : targetDecl(SelectedNode->ASTNode, DeclRelation::Alias | DeclRelation::TemplatePattern)) { - const auto *ND = llvm::dyn_cast(D); - if (!ND) - continue; // Get to CXXRecordDecl from constructor or destructor. - ND = tooling::getCanonicalSymbolDeclaration(ND); - Result.insert(ND); + D = tooling::getCanonicalSymbolDeclaration(D); + Result.insert(D); } return Result; } diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp --- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp +++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp @@ -34,7 +34,7 @@ struct PrintedDecl { PrintedDecl(const char *Name, DeclRelationSet Relations = {}) : Name(Name), Relations(Relations) {} - PrintedDecl(const Decl *D, DeclRelationSet Relations = {}) + PrintedDecl(const NamedDecl *D, DeclRelationSet Relations = {}) : Relations(Relations) { std::string S; llvm::raw_string_ostream OS(S); diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -598,6 +598,9 @@ func<1>(); } )cpp", + R"cpp(// non-named decls don't get hover. Don't crash! + ^static_assert(1, ""); + )cpp", }; for (const auto &Test : Tests) {