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 @@ -107,9 +107,14 @@ /// This declaration is an alias that was referred to. /// e.g. using llvm::StringRef (the UsingDecl directly referenced). Alias, - /// This is the underlying declaration for an alias, decltype etc. + + /// Underlying declarations for renaming alias (typedef decl, type alias decl) + AliasUnderlying, + /// Underlying declarations for non-renaming alias, decltype, etc. /// e.g. class llvm::StringRef (the underlying declaration referenced). - Underlying, + NonAliasUnderlying, + + LastKind = NonAliasUnderlying, }; llvm::raw_ostream &operator<<(llvm::raw_ostream &, DeclRelation); @@ -161,7 +166,7 @@ // Boring implementation details of bitfield. class DeclRelationSet { - using Set = std::bitset(DeclRelation::Underlying) + 1>; + using Set = std::bitset(DeclRelation::LastKind) + 1>; Set S; DeclRelationSet(Set S) : S(S) {} 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 @@ -339,14 +339,14 @@ D = UDD->getNominatedNamespaceAsWritten(); if (const TypedefNameDecl *TND = dyn_cast(D)) { - add(TND->getUnderlyingType(), Flags | Rel::Underlying); + add(TND->getUnderlyingType(), Flags | Rel::AliasUnderlying); Flags |= Rel::Alias; // continue with the alias. } else if (const UsingDecl *UD = dyn_cast(D)) { for (const UsingShadowDecl *S : UD->shadows()) - add(S->getUnderlyingDecl(), Flags | Rel::Underlying); + add(S->getUnderlyingDecl(), Flags | Rel::NonAliasUnderlying); Flags |= Rel::Alias; // continue with the alias. } else if (const auto *NAD = dyn_cast(D)) { - add(NAD->getUnderlyingDecl(), Flags | Rel::Underlying); + add(NAD->getUnderlyingDecl(), Flags | Rel::AliasUnderlying); Flags |= Rel::Alias; // continue with the alias } else if (const UnresolvedUsingValueDecl *UUVD = dyn_cast(D)) { @@ -354,7 +354,7 @@ UUVD->getQualifier()->getAsType(), [UUVD](ASTContext &) { return UUVD->getNameInfo().getName(); }, ValueFilter)) { - add(Target, Flags | Rel::Underlying); + add(Target, Flags | Rel::NonAliasUnderlying); } Flags |= Rel::Alias; // continue with the alias } else if (const UsingShadowDecl *USD = dyn_cast(D)) { @@ -364,7 +364,7 @@ // Shadow decls are synthetic and not themselves interesting. // Record the underlying decl instead, if allowed. D = USD->getTargetDecl(); - Flags |= Rel::Underlying; // continue with the underlying decl. + Flags |= Rel::NonAliasUnderlying; // continue with the underlying decl. } else if (const auto *DG = dyn_cast(D)) { D = DG->getDeducedTemplate(); } else if (const ObjCImplementationDecl *IID = @@ -518,12 +518,12 @@ } void VisitDecltypeType(const DecltypeType *DTT) { - Outer.add(DTT->getUnderlyingType(), Flags | Rel::Underlying); + Outer.add(DTT->getUnderlyingType(), Flags | Rel::NonAliasUnderlying); } void VisitDeducedType(const DeducedType *DT) { // FIXME: In practice this doesn't work: the AutoType you find inside // TypeLoc never has a deduced type. https://llvm.org/PR42914 - Outer.add(DT->getDeducedType(), Flags | Rel::Underlying); + Outer.add(DT->getDeducedType(), Flags | Rel::NonAliasUnderlying); } void VisitDeducedTemplateSpecializationType( const DeducedTemplateSpecializationType *DTST) { @@ -548,7 +548,7 @@ // (after substitution), and failing that point to the (templated) using // decl. if (TST->isTypeAlias()) { - Outer.add(TST->getAliasedType(), Flags | Rel::Underlying); + Outer.add(TST->getAliasedType(), Flags | Rel::AliasUnderlying); // Don't *traverse* the alias, which would result in traversing the // template of the underlying type. Outer.report( @@ -721,10 +721,10 @@ void VisitUsingDecl(const UsingDecl *D) { // "using ns::identifier;" is a non-declaration reference. - Refs.push_back( - ReferenceLoc{D->getQualifierLoc(), D->getLocation(), /*IsDecl=*/false, - explicitReferenceTargets(DynTypedNode::create(*D), - DeclRelation::Underlying)}); + Refs.push_back(ReferenceLoc{ + D->getQualifierLoc(), D->getLocation(), /*IsDecl=*/false, + explicitReferenceTargets(DynTypedNode::create(*D), + DeclRelation::NonAliasUnderlying)}); } void VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) { @@ -1144,7 +1144,8 @@ case DeclRelation::X: \ return OS << #X; REL_CASE(Alias); - REL_CASE(Underlying); + REL_CASE(NonAliasUnderlying); + REL_CASE(AliasUnderlying); REL_CASE(TemplateInstantiation); REL_CASE(TemplatePattern); #undef REL_CASE 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 @@ -314,8 +314,9 @@ }; // Emit all symbol locations (declaration or definition) from AST. - DeclRelationSet Relations = - DeclRelation::TemplatePattern | DeclRelation::Alias; + DeclRelationSet Relations = DeclRelation::TemplatePattern | + DeclRelation::Alias | + DeclRelation::NonAliasUnderlying; for (const NamedDecl *D : getDeclAtPosition(AST, CurLoc, Relations, NodeKind)) { // Special case: void foo() ^override: jump to the overridden method. @@ -343,18 +344,6 @@ } } - // Give the underlying decl if navigation is triggered on a non-renaming - // alias. - if (llvm::isa(D) || llvm::isa(D)) { - // FIXME: address more complicated cases. TargetDecl(... Underlying) gives - // all overload candidates, we only want the targeted one if the cursor is - // on an using-alias usage, workround it with getDeclAtPosition. - llvm::for_each( - getDeclAtPosition(AST, CurLoc, DeclRelation::Underlying, NodeKind), - [&](const NamedDecl *UD) { AddResultDecl(UD); }); - continue; - } - // Special case: if the class name is selected, also map Objective-C // categories and category implementations back to their class interface. // @@ -1140,21 +1129,10 @@ } else { // Handle references to Decls. - DeclRelationSet Relations = - DeclRelation::TemplatePattern | DeclRelation::Alias; - std::vector Decls = - getDeclAtPosition(AST, *CurLoc, Relations); - std::vector NonrenamingAliasUnderlyingDecls; - // If the results include a *non-renaming* alias, get its - // underlying decls as well. (See similar logic in locateASTReferent()). - for (const NamedDecl *D : Decls) { - if (llvm::isa(D) || llvm::isa(D)) { - for (const NamedDecl *AD : - getDeclAtPosition(AST, *CurLoc, DeclRelation::Underlying)) - NonrenamingAliasUnderlyingDecls.push_back(AD); - } - } - llvm::copy(NonrenamingAliasUnderlyingDecls, std::back_inserter(Decls)); + DeclRelationSet Relations = DeclRelation::TemplatePattern | + DeclRelation::Alias | + DeclRelation::NonAliasUnderlying; + auto Decls = getDeclAtPosition(AST, *CurLoc, Relations); // We traverse the AST to find references in the main file. auto MainFileRefs = findRefs(Decls, AST); @@ -1221,8 +1199,9 @@ // We also want the targets of using-decls, so we include // DeclRelation::Underlying. - DeclRelationSet Relations = DeclRelation::TemplatePattern | - DeclRelation::Alias | DeclRelation::Underlying; + DeclRelationSet Relations = + DeclRelation::TemplatePattern | DeclRelation::Alias | + DeclRelation::NonAliasUnderlying | DeclRelation::AliasUnderlying; for (const NamedDecl *D : getDeclAtPosition(AST, *CurLoc, Relations)) { SymbolDetails NewSymbol; std::string QName = printQualifiedName(*D); @@ -1406,7 +1385,9 @@ // instantiations and template patterns, and prefer the former if available // (generally, one will be available for non-dependent specializations of a // class template). - auto Decls = explicitReferenceTargets(N->ASTNode, DeclRelation::Underlying); + auto Decls = + explicitReferenceTargets(N->ASTNode, DeclRelation::NonAliasUnderlying | + DeclRelation::AliasUnderlying); if (Decls.empty()) return nullptr; 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 @@ -182,7 +182,7 @@ )cpp"; // f(char) is not referenced! EXPECT_DECLS("DeclRefExpr", {"using foo::f", Rel::Alias}, - {"int f(int)", Rel::Underlying}); + {"int f(int)", Rel::NonAliasUnderlying}); Code = R"cpp( namespace foo { @@ -193,8 +193,8 @@ )cpp"; // All overloads are referenced. EXPECT_DECLS("UsingDecl", {"using foo::f", Rel::Alias}, - {"int f(int)", Rel::Underlying}, - {"int f(char)", Rel::Underlying}); + {"int f(int)", Rel::NonAliasUnderlying}, + {"int f(char)", Rel::NonAliasUnderlying}); Code = R"cpp( struct X { @@ -206,7 +206,7 @@ int x = Y().[[foo]](); )cpp"; EXPECT_DECLS("MemberExpr", {"using X::foo", Rel::Alias}, - {"int foo()", Rel::Underlying}); + {"int foo()", Rel::NonAliasUnderlying}); Code = R"cpp( template @@ -219,7 +219,7 @@ }; )cpp"; EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base::waldo", Rel::Alias}, - {"void waldo()", Rel::Underlying}); + {"void waldo()", Rel::NonAliasUnderlying}); } TEST_F(TargetDeclTest, ConstructorInitList) { @@ -275,7 +275,7 @@ int y = [[b]]::x; )cpp"; EXPECT_DECLS("NestedNameSpecifierLoc", {"namespace b = a", Rel::Alias}, - {"namespace a", Rel::Underlying}); + {"namespace a", Rel::AliasUnderlying}); } TEST_F(TargetDeclTest, Types) { @@ -291,14 +291,14 @@ [[X]] x; )cpp"; EXPECT_DECLS("TypedefTypeLoc", {"typedef S X", Rel::Alias}, - {"struct S", Rel::Underlying}); + {"struct S", Rel::AliasUnderlying}); Code = R"cpp( namespace ns { struct S{}; } typedef ns::S X; [[X]] x; )cpp"; EXPECT_DECLS("TypedefTypeLoc", {"typedef ns::S X", Rel::Alias}, - {"struct S", Rel::Underlying}); + {"struct S", Rel::AliasUnderlying}); // FIXME: Auto-completion in a template requires disabling delayed template // parsing. @@ -325,7 +325,7 @@ S X; [[decltype]](X) Y; )cpp"; - EXPECT_DECLS("DecltypeTypeLoc", {"struct S", Rel::Underlying}); + EXPECT_DECLS("DecltypeTypeLoc", {"struct S", Rel::NonAliasUnderlying}); Code = R"cpp( struct S{}; @@ -534,8 +534,9 @@ )cpp"; EXPECT_DECLS("TemplateSpecializationTypeLoc", {"template<> class SmallVector", - Rel::TemplateInstantiation | Rel::Underlying}, - {"class SmallVector", Rel::TemplatePattern | Rel::Underlying}, + Rel::TemplateInstantiation | DeclRelation::AliasUnderlying}, + {"class SmallVector", + Rel::TemplatePattern | DeclRelation::AliasUnderlying}, {"using TinyVector = SmallVector", Rel::Alias | Rel::TemplatePattern}); } 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 @@ -1090,7 +1090,6 @@ R"cpp( template struct function {}; template using [[callback]] = function; - c^allback foo; )cpp", @@ -1118,17 +1117,17 @@ // decls. R"cpp( namespace ns { class [[Foo]] {}; } - using ns::F^oo; + using ns::[[F^oo]]; )cpp", R"cpp( namespace ns { int [[x]](char); int [[x]](double); } - using ns::^x; + using ns::[[^x]]; )cpp", R"cpp( namespace ns { int [[x]](char); int x(double); } - using ns::x; + using ns::[[x]]; int y = ^x('a'); )cpp", @@ -1156,7 +1155,7 @@ }; template struct Derived : Base { - using Base::w^aldo; + using Base::[[w^aldo]]; }; )cpp", };