[clang-tools-extra] 1a4ee4c - [clangd] Find reference to template parameter in 'sizeof...' expression

Nathan Ridge via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 5 11:31:10 PST 2019


Author: Nathan Ridge
Date: 2019-12-05T14:30:53-05:00
New Revision: 1a4ee4c88f21c0e6860983a80bfa51a25b4af700

URL: https://github.com/llvm/llvm-project/commit/1a4ee4c88f21c0e6860983a80bfa51a25b4af700
DIFF: https://github.com/llvm/llvm-project/commit/1a4ee4c88f21c0e6860983a80bfa51a25b4af700.diff

LOG: [clangd] Find reference to template parameter in 'sizeof...' expression

Fixes https://github.com/clangd/clangd/issues/213.

Reviewers: ilya-biryukov

Reviewed By: ilya-biryukov

Subscribers: MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D70740

Added: 
    

Modified: 
    clang-tools-extra/clangd/FindTarget.cpp
    clang-tools-extra/clangd/unittests/FindTargetTests.cpp
    clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp
index 3e55a6a9cdc6..69c298b6887c 100644
--- a/clang-tools-extra/clangd/FindTarget.cpp
+++ b/clang-tools-extra/clangd/FindTarget.cpp
@@ -197,6 +197,9 @@ struct TargetFinder {
         for (auto *D : OE->decls())
           Outer.add(D, Flags);
       }
+      void VisitSizeOfPackExpr(const SizeOfPackExpr *SE) {
+        Outer.add(SE->getPack(), Flags);
+      }
       void VisitCXXConstructExpr(const CXXConstructExpr *CCE) {
         Outer.add(CCE->getConstructor(), Flags);
       }
@@ -494,6 +497,13 @@ llvm::SmallVector<ReferenceLoc, 2> refInExpr(const Expr *E) {
                                   llvm::SmallVector<const NamedDecl *, 1>(
                                       E->decls().begin(), E->decls().end())});
     }
+
+    void VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
+      Refs.push_back(ReferenceLoc{NestedNameSpecifierLoc(),
+                                  E->getPackLoc(),
+                                  /*IsDecl=*/false,
+                                  {E->getPack()}});
+    }
   };
 
   Visitor V;

diff  --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index 620eb3d6d3d6..a81569485e89 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -277,6 +277,15 @@ TEST_F(TargetDeclTest, Types) {
   )cpp";
   // FIXME: deduced type missing in AST. https://llvm.org/PR42914
   EXPECT_DECLS("AutoTypeLoc");
+
+  Code = R"cpp(
+    template <typename... E>
+    struct S {
+      static const int size = sizeof...([[E]]);
+    };
+  )cpp";
+  // FIXME: We don't do a good job printing TemplateTypeParmDecls, apparently!
+  EXPECT_DECLS("SizeOfPackExpr", "");
 }
 
 TEST_F(TargetDeclTest, ClassTemplate) {
@@ -593,28 +602,27 @@ class FindExplicitReferencesTest : public ::testing::Test {
 
 TEST_F(FindExplicitReferencesTest, All) {
   std::pair</*Code*/ llvm::StringRef, /*References*/ llvm::StringRef> Cases[] =
-      {
-          // Simple expressions.
-          {R"cpp(
+      {// Simple expressions.
+       {R"cpp(
         int global;
         int func();
         void foo(int param) {
           $0^global = $1^param + $2^func();
         }
         )cpp",
-           "0: targets = {global}\n"
-           "1: targets = {param}\n"
-           "2: targets = {func}\n"},
-          {R"cpp(
+        "0: targets = {global}\n"
+        "1: targets = {param}\n"
+        "2: targets = {func}\n"},
+       {R"cpp(
         struct X { int a; };
         void foo(X x) {
           $0^x.$1^a = 10;
         }
         )cpp",
-           "0: targets = {x}\n"
-           "1: targets = {X::a}\n"},
-          // Namespaces and aliases.
-          {R"cpp(
+        "0: targets = {x}\n"
+        "1: targets = {X::a}\n"},
+       // Namespaces and aliases.
+       {R"cpp(
           namespace ns {}
           namespace alias = ns;
           void foo() {
@@ -622,19 +630,19 @@ TEST_F(FindExplicitReferencesTest, All) {
             using namespace $1^alias;
           }
         )cpp",
-           "0: targets = {ns}\n"
-           "1: targets = {alias}\n"},
-          // Using declarations.
-          {R"cpp(
+        "0: targets = {ns}\n"
+        "1: targets = {alias}\n"},
+       // Using declarations.
+       {R"cpp(
           namespace ns { int global; }
           void foo() {
             using $0^ns::$1^global;
           }
         )cpp",
-           "0: targets = {ns}\n"
-           "1: targets = {ns::global}, qualifier = 'ns::'\n"},
-          // Simple types.
-          {R"cpp(
+        "0: targets = {ns}\n"
+        "1: targets = {ns::global}, qualifier = 'ns::'\n"},
+       // Simple types.
+       {R"cpp(
          struct Struct { int a; };
          using Typedef = int;
          void foo() {
@@ -643,13 +651,13 @@ TEST_F(FindExplicitReferencesTest, All) {
            static_cast<$4^Struct*>(0);
          }
        )cpp",
-           "0: targets = {Struct}\n"
-           "1: targets = {x}, decl\n"
-           "2: targets = {Typedef}\n"
-           "3: targets = {y}, decl\n"
-           "4: targets = {Struct}\n"},
-          // Name qualifiers.
-          {R"cpp(
+        "0: targets = {Struct}\n"
+        "1: targets = {x}, decl\n"
+        "2: targets = {Typedef}\n"
+        "3: targets = {y}, decl\n"
+        "4: targets = {Struct}\n"},
+       // Name qualifiers.
+       {R"cpp(
          namespace a { namespace b { struct S { typedef int type; }; } }
          void foo() {
            $0^a::$1^b::$2^S $3^x;
@@ -657,17 +665,17 @@ TEST_F(FindExplicitReferencesTest, All) {
            $6^S::$7^type $8^y;
          }
         )cpp",
-           "0: targets = {a}\n"
-           "1: targets = {a::b}, qualifier = 'a::'\n"
-           "2: targets = {a::b::S}, qualifier = 'a::b::'\n"
-           "3: targets = {x}, decl\n"
-           "4: targets = {a}\n"
-           "5: targets = {a::b}, qualifier = 'a::'\n"
-           "6: targets = {a::b::S}\n"
-           "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
-           "8: targets = {y}, decl\n"},
-          // Simple templates.
-          {R"cpp(
+        "0: targets = {a}\n"
+        "1: targets = {a::b}, qualifier = 'a::'\n"
+        "2: targets = {a::b::S}, qualifier = 'a::b::'\n"
+        "3: targets = {x}, decl\n"
+        "4: targets = {a}\n"
+        "5: targets = {a::b}, qualifier = 'a::'\n"
+        "6: targets = {a::b::S}\n"
+        "7: targets = {a::b::S::type}, qualifier = 'struct S::'\n"
+        "8: targets = {y}, decl\n"},
+       // Simple templates.
+       {R"cpp(
           template <class T> struct vector { using value_type = T; };
           template <> struct vector<bool> { using value_type = bool; };
           void foo() {
@@ -675,12 +683,12 @@ TEST_F(FindExplicitReferencesTest, All) {
             $2^vector<bool> $3^vb;
           }
         )cpp",
-           "0: targets = {vector<int>}\n"
-           "1: targets = {vi}, decl\n"
-           "2: targets = {vector<bool>}\n"
-           "3: targets = {vb}, decl\n"},
-          // Template type aliases.
-          {R"cpp(
+        "0: targets = {vector<int>}\n"
+        "1: targets = {vi}, decl\n"
+        "2: targets = {vector<bool>}\n"
+        "3: targets = {vb}, decl\n"},
+       // Template type aliases.
+       {R"cpp(
             template <class T> struct vector { using value_type = T; };
             template <> struct vector<bool> { using value_type = bool; };
             template <class T> using valias = vector<T>;
@@ -689,12 +697,12 @@ TEST_F(FindExplicitReferencesTest, All) {
               $2^valias<bool> $3^vb;
             }
           )cpp",
-           "0: targets = {valias}\n"
-           "1: targets = {vi}, decl\n"
-           "2: targets = {valias}\n"
-           "3: targets = {vb}, decl\n"},
-          // MemberExpr should know their using declaration.
-          {R"cpp(
+        "0: targets = {valias}\n"
+        "1: targets = {vi}, decl\n"
+        "2: targets = {valias}\n"
+        "3: targets = {vb}, decl\n"},
+       // MemberExpr should know their using declaration.
+       {R"cpp(
             struct X { void func(int); }
             struct Y : X {
               using X::func;
@@ -703,10 +711,10 @@ TEST_F(FindExplicitReferencesTest, All) {
               $0^y.$1^func(1);
             }
         )cpp",
-           "0: targets = {y}\n"
-           "1: targets = {Y::func}\n"},
-          // DeclRefExpr should know their using declaration.
-          {R"cpp(
+        "0: targets = {y}\n"
+        "1: targets = {Y::func}\n"},
+       // DeclRefExpr should know their using declaration.
+       {R"cpp(
             namespace ns { void bar(int); }
             using ns::bar;
 
@@ -714,9 +722,9 @@ TEST_F(FindExplicitReferencesTest, All) {
               $0^bar(10);
             }
         )cpp",
-           "0: targets = {bar}\n"},
-          // References from a macro.
-          {R"cpp(
+        "0: targets = {bar}\n"},
+       // References from a macro.
+       {R"cpp(
             #define FOO a
             #define BAR b
 
@@ -724,10 +732,10 @@ TEST_F(FindExplicitReferencesTest, All) {
               $0^FOO+$1^BAR;
             }
         )cpp",
-           "0: targets = {a}\n"
-           "1: targets = {b}\n"},
-          // No references from implicit nodes.
-          {R"cpp(
+        "0: targets = {a}\n"
+        "1: targets = {b}\n"},
+       // No references from implicit nodes.
+       {R"cpp(
             struct vector {
               int *begin();
               int *end();
@@ -739,11 +747,11 @@ TEST_F(FindExplicitReferencesTest, All) {
               }
             }
         )cpp",
-           "0: targets = {x}, decl\n"
-           "1: targets = {vector}\n"
-           "2: targets = {x}\n"},
-          // Handle UnresolvedLookupExpr.
-          {R"cpp(
+        "0: targets = {x}, decl\n"
+        "1: targets = {vector}\n"
+        "2: targets = {x}\n"},
+       // Handle UnresolvedLookupExpr.
+       {R"cpp(
             namespace ns1 { void func(char*); }
             namespace ns2 { void func(int*); }
             using namespace ns1;
@@ -754,10 +762,10 @@ TEST_F(FindExplicitReferencesTest, All) {
               $0^func($1^t);
             }
         )cpp",
-           "0: targets = {ns1::func, ns2::func}\n"
-           "1: targets = {t}\n"},
-          // Handle UnresolvedMemberExpr.
-          {R"cpp(
+        "0: targets = {ns1::func, ns2::func}\n"
+        "1: targets = {t}\n"},
+       // Handle UnresolvedMemberExpr.
+       {R"cpp(
             struct X {
               void func(char*);
               void func(int*);
@@ -768,11 +776,11 @@ TEST_F(FindExplicitReferencesTest, All) {
               $0^x.$1^func($2^t);
             }
         )cpp",
-           "0: targets = {x}\n"
-           "1: targets = {X::func, X::func}\n"
-           "2: targets = {t}\n"},
-          // Type template parameters.
-          {R"cpp(
+        "0: targets = {x}\n"
+        "1: targets = {X::func, X::func}\n"
+        "2: targets = {t}\n"},
+       // Type template parameters.
+       {R"cpp(
             template <class T>
             void foo() {
               static_cast<$0^T>(0);
@@ -780,21 +788,21 @@ TEST_F(FindExplicitReferencesTest, All) {
               $2^T $3^t;
             }
         )cpp",
-           "0: targets = {T}\n"
-           "1: targets = {T}\n"
-           "2: targets = {T}\n"
-           "3: targets = {t}, decl\n"},
-          // Non-type template parameters.
-          {R"cpp(
+        "0: targets = {T}\n"
+        "1: targets = {T}\n"
+        "2: targets = {T}\n"
+        "3: targets = {t}, decl\n"},
+       // Non-type template parameters.
+       {R"cpp(
             template <int I>
             void foo() {
               int $0^x = $1^I;
             }
         )cpp",
-           "0: targets = {x}, decl\n"
-           "1: targets = {I}\n"},
-          // Template template parameters.
-          {R"cpp(
+        "0: targets = {x}, decl\n"
+        "1: targets = {I}\n"},
+       // Template template parameters.
+       {R"cpp(
             template <class T> struct vector {};
 
             template <template<class> class TT, template<class> class ...TP>
@@ -805,16 +813,16 @@ TEST_F(FindExplicitReferencesTest, All) {
               $6^foo<$7^TP...>();
             }
         )cpp",
-           "0: targets = {TT}\n"
-           "1: targets = {x}, decl\n"
-           "2: targets = {foo}\n"
-           "3: targets = {TT}\n"
-           "4: targets = {foo}\n"
-           "5: targets = {vector}\n"
-           "6: targets = {foo}\n"
-           "7: targets = {TP}\n"},
-          // Non-type template parameters with declarations.
-          {R"cpp(
+        "0: targets = {TT}\n"
+        "1: targets = {x}, decl\n"
+        "2: targets = {foo}\n"
+        "3: targets = {TT}\n"
+        "4: targets = {foo}\n"
+        "5: targets = {vector}\n"
+        "6: targets = {foo}\n"
+        "7: targets = {TP}\n"},
+       // Non-type template parameters with declarations.
+       {R"cpp(
             int func();
             template <int(*)()> struct wrapper {};
 
@@ -824,12 +832,12 @@ TEST_F(FindExplicitReferencesTest, All) {
               $3^FuncParam();
             }
         )cpp",
-           "0: targets = {wrapper<&func>}\n"
-           "1: targets = {func}\n"
-           "2: targets = {w}, decl\n"
-           "3: targets = {FuncParam}\n"},
-          // declaration references.
-          {R"cpp(
+        "0: targets = {wrapper<&func>}\n"
+        "1: targets = {func}\n"
+        "2: targets = {w}, decl\n"
+        "3: targets = {FuncParam}\n"},
+       // declaration references.
+       {R"cpp(
              namespace ns {}
              class S {};
              void foo() {
@@ -841,19 +849,19 @@ TEST_F(FindExplicitReferencesTest, All) {
                namespace $9^NS = $10^ns;
              }
            )cpp",
-           "0: targets = {Foo}, decl\n"
-           "1: targets = {foo()::Foo::Foo}, decl\n"
-           "2: targets = {Foo}\n"
-           "3: targets = {foo()::Foo::field}, decl\n"
-           "4: targets = {Var}, decl\n"
-           "5: targets = {E}, decl\n"
-           "6: targets = {foo()::ABC}, decl\n"
-           "7: targets = {INT}, decl\n"
-           "8: targets = {INT2}, decl\n"
-           "9: targets = {NS}, decl\n"
-           "10: targets = {ns}\n"},
-          // cxx constructor initializer.
-          {R"cpp(
+        "0: targets = {Foo}, decl\n"
+        "1: targets = {foo()::Foo::Foo}, decl\n"
+        "2: targets = {Foo}\n"
+        "3: targets = {foo()::Foo::field}, decl\n"
+        "4: targets = {Var}, decl\n"
+        "5: targets = {E}, decl\n"
+        "6: targets = {foo()::ABC}, decl\n"
+        "7: targets = {INT}, decl\n"
+        "8: targets = {INT2}, decl\n"
+        "9: targets = {NS}, decl\n"
+        "10: targets = {ns}\n"},
+       // cxx constructor initializer.
+       {R"cpp(
              class Base {};
              void foo() {
                // member initializer
@@ -873,34 +881,34 @@ TEST_F(FindExplicitReferencesTest, All) {
                };
              }
            )cpp",
-           "0: targets = {X}, decl\n"
-           "1: targets = {foo()::X::abc}, decl\n"
-           "2: targets = {foo()::X::X}, decl\n"
-           "3: targets = {foo()::X::abc}\n"
-           "4: targets = {Derived}, decl\n"
-           "5: targets = {Base}\n"
-           "6: targets = {Base}\n"
-           "7: targets = {foo()::Derived::B}, decl\n"
-           "8: targets = {foo()::Derived::Derived}, decl\n"
-           "9: targets = {Base}\n"
-           "10: targets = {Foo}, decl\n"
-           "11: targets = {foo()::Foo::Foo}, decl\n"
-           "12: targets = {foo()::Foo::Foo}, decl\n"
-           "13: targets = {Foo}\n"},
-          // Anonymous entities should not be reported.
-          {
-              R"cpp(
+        "0: targets = {X}, decl\n"
+        "1: targets = {foo()::X::abc}, decl\n"
+        "2: targets = {foo()::X::X}, decl\n"
+        "3: targets = {foo()::X::abc}\n"
+        "4: targets = {Derived}, decl\n"
+        "5: targets = {Base}\n"
+        "6: targets = {Base}\n"
+        "7: targets = {foo()::Derived::B}, decl\n"
+        "8: targets = {foo()::Derived::Derived}, decl\n"
+        "9: targets = {Base}\n"
+        "10: targets = {Foo}, decl\n"
+        "11: targets = {foo()::Foo::Foo}, decl\n"
+        "12: targets = {foo()::Foo::Foo}, decl\n"
+        "13: targets = {Foo}\n"},
+       // Anonymous entities should not be reported.
+       {
+           R"cpp(
              void foo() {
               class {} $0^x;
               int (*$1^fptr)(int $2^a, int) = nullptr;
              }
            )cpp",
-              "0: targets = {x}, decl\n"
-              "1: targets = {fptr}, decl\n"
-              "2: targets = {a}, decl\n"},
-          // Namespace aliases should be handled properly.
-          {
-              R"cpp(
+           "0: targets = {x}, decl\n"
+           "1: targets = {fptr}, decl\n"
+           "2: targets = {a}, decl\n"},
+       // Namespace aliases should be handled properly.
+       {
+           R"cpp(
                 namespace ns { struct Type {} }
                 namespace alias = ns;
                 namespace rec_alias = alias;
@@ -911,16 +919,25 @@ TEST_F(FindExplicitReferencesTest, All) {
                   $6^rec_alias::$7^Type $8^c;
                 }
            )cpp",
-              "0: targets = {ns}\n"
-              "1: targets = {ns::Type}, qualifier = 'ns::'\n"
-              "2: targets = {a}, decl\n"
-              "3: targets = {alias}\n"
-              "4: targets = {ns::Type}, qualifier = 'alias::'\n"
-              "5: targets = {b}, decl\n"
-              "6: targets = {rec_alias}\n"
-              "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"
-              "8: targets = {c}, decl\n"},
-      };
+           "0: targets = {ns}\n"
+           "1: targets = {ns::Type}, qualifier = 'ns::'\n"
+           "2: targets = {a}, decl\n"
+           "3: targets = {alias}\n"
+           "4: targets = {ns::Type}, qualifier = 'alias::'\n"
+           "5: targets = {b}, decl\n"
+           "6: targets = {rec_alias}\n"
+           "7: targets = {ns::Type}, qualifier = 'rec_alias::'\n"
+           "8: targets = {c}, decl\n"},
+       // Handle SizeOfPackExpr.
+       {
+           R"cpp(
+                template <typename... E>
+                void foo() {
+                  constexpr int $0^size = sizeof...($1^E);
+                };
+            )cpp",
+           "0: targets = {size}, decl\n"
+           "1: targets = {E}\n"}};
 
   for (const auto &C : Cases) {
     llvm::StringRef ExpectedCode = C.first;

diff  --git a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
index 0f688656b767..2df0f1c9a579 100644
--- a/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SemanticHighlightingTests.cpp
@@ -625,6 +625,13 @@ TEST(SemanticHighlighting, GetsCorrectTokens) {
 $InactiveCode[[]]      #else
       int $Variable[[Active2]];
       #endif
+    )cpp",
+      // Argument to 'sizeof...'
+      R"cpp(
+      template <typename... $TemplateParameter[[Elements]]>
+      struct $Class[[TupleSize]] {
+        static const int $StaticField[[size]] = sizeof...($TemplateParameter[[Elements]]);
+      };
     )cpp"};
   for (const auto &TestCase : TestCases) {
     checkHighlightings(TestCase);


        


More information about the cfe-commits mailing list