hokein created this revision.
Herald added subscribers: cfe-commits, usaxena95, kadircet, arphaman.
Herald added a project: clang.
hokein requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

Extend the TargetDecl API to fix the workaround in 
https://reviews.llvm.org/D87225 and
https://reviews.llvm.org/D74054.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D88472

Files:
  clang-tools-extra/clangd/FindTarget.cpp
  clang-tools-extra/clangd/FindTarget.h
  clang-tools-extra/clangd/XRefs.cpp
  clang-tools-extra/clangd/unittests/FindTargetTests.cpp
  clang-tools-extra/clangd/unittests/XRefsTests.cpp

Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -1090,7 +1090,6 @@
       R"cpp(
       template <class T> struct function {};
       template <class T> using [[callback]] = function<T()>;
-
       c^allback<int> 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 <typename T>
       struct Derived : Base<T> {
-        using Base<T>::w^aldo;
+        using Base<T>::[[w^aldo]];
       };
     )cpp",
   };
Index: clang-tools-extra/clangd/unittests/FindTargetTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ 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 <typename T>
@@ -219,7 +219,7 @@
       };
     )cpp";
   EXPECT_DECLS("UnresolvedUsingValueDecl", {"using Base<T>::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<int, 1>",
-                Rel::TemplateInstantiation | Rel::Underlying},
-               {"class SmallVector", Rel::TemplatePattern | Rel::Underlying},
+                Rel::TemplateInstantiation | DeclRelation::AliasUnderlying},
+               {"class SmallVector",
+                Rel::TemplatePattern | DeclRelation::AliasUnderlying},
                {"using TinyVector = SmallVector<U, 1>",
                 Rel::Alias | Rel::TemplatePattern});
 }
Index: clang-tools-extra/clangd/XRefs.cpp
===================================================================
--- clang-tools-extra/clangd/XRefs.cpp
+++ 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<UsingDecl>(D) || llvm::isa<UnresolvedUsingValueDecl>(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<const NamedDecl *> Decls =
-        getDeclAtPosition(AST, *CurLoc, Relations);
-    std::vector<const NamedDecl *> 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<UsingDecl>(D) || llvm::isa<UnresolvedUsingValueDecl>(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;
 
Index: clang-tools-extra/clangd/FindTarget.h
===================================================================
--- clang-tools-extra/clangd/FindTarget.h
+++ 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<static_cast<unsigned>(DeclRelation::Underlying) + 1>;
+  using Set = std::bitset<static_cast<unsigned>(DeclRelation::LastKind) + 1>;
   Set S;
   DeclRelationSet(Set S) : S(S) {}
 
Index: clang-tools-extra/clangd/FindTarget.cpp
===================================================================
--- clang-tools-extra/clangd/FindTarget.cpp
+++ clang-tools-extra/clangd/FindTarget.cpp
@@ -339,14 +339,14 @@
       D = UDD->getNominatedNamespaceAsWritten();
 
     if (const TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(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<UsingDecl>(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<NamespaceAliasDecl>(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<UnresolvedUsingValueDecl>(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<UsingShadowDecl>(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<CXXDeductionGuideDecl>(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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to