Commit f651c402 authored by Haojian Wu's avatar Haojian Wu
Browse files

[clangd] Capture the missing injected class names in findExplicitReferences.

Summary: Fixes https://github.com/clangd/clangd/issues/237.

Reviewers: kadircet, kbobyrev

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D73088
parent 651fa669
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -695,6 +695,13 @@ llvm::SmallVector<ReferenceLoc, 2> refInTypeLoc(TypeLoc L) {
                                   DeclRelation::Alias)};
    }

    void VisitInjectedClassNameTypeLoc(InjectedClassNameTypeLoc TL) {
      Ref = ReferenceLoc{NestedNameSpecifierLoc(),
                         TL.getNameLoc(),
                         /*IsDecl=*/false,
                         {TL.getDecl()}};
    }

    void VisitDependentTemplateSpecializationTypeLoc(
        DependentTemplateSpecializationTypeLoc L) {
      Ref = ReferenceLoc{
+35 −7
Original line number Diff line number Diff line
//===-- FindSymbolsTests.cpp -------------------------*- C++ -*------------===//
//===-- FindTargetTests.cpp --------------------------*- C++ -*------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -553,8 +553,8 @@ protected:
    std::string DumpedReferences;
  };

  /// Parses \p Code, finds function '::foo' and annotates its body with results
  /// of findExplicitReferecnces.
  /// Parses \p Code, finds function or namespace '::foo' and annotates its body
  /// with results of findExplicitReferecnces.
  /// See actual tests for examples of annotation format.
  AllRefs annotateReferencesInFoo(llvm::StringRef Code) {
    TestTU TU;
@@ -574,12 +574,21 @@ protected:
    auto *TestDecl = &findDecl(AST, "foo");
    if (auto *T = llvm::dyn_cast<FunctionTemplateDecl>(TestDecl))
      TestDecl = T->getTemplatedDecl();
    auto &Func = llvm::cast<FunctionDecl>(*TestDecl);

    std::vector<ReferenceLoc> Refs;
    findExplicitReferences(Func.getBody(), [&Refs](ReferenceLoc R) {
    if (const auto *Func = llvm::dyn_cast<FunctionDecl>(TestDecl))
      findExplicitReferences(Func->getBody(), [&Refs](ReferenceLoc R) {
        Refs.push_back(std::move(R));
      });
    else if (const auto *NS = llvm::dyn_cast<NamespaceDecl>(TestDecl))
      findExplicitReferences(NS, [&Refs, &NS](ReferenceLoc R) {
        // Avoid adding the namespace foo decl to the results.
        if (R.Targets.size() == 1 && R.Targets.front() == NS)
          return;
        Refs.push_back(std::move(R));
      });
    else
      ADD_FAILURE() << "Failed to find ::foo decl for test";

    auto &SM = AST.getSourceManager();
    llvm::sort(Refs, [&](const ReferenceLoc &L, const ReferenceLoc &R) {
@@ -720,6 +729,25 @@ TEST_F(FindExplicitReferencesTest, All) {
        "1: targets = {vi}, decl\n"
        "2: targets = {valias}\n"
        "3: targets = {vb}, decl\n"},
       // Injected class name.
       {R"cpp(
            namespace foo {
              template <typename $0^T>
              class $1^$2^Bar {
                ~$3^Bar();
                void $4^f($5^Bar);
              };
            }
          )cpp",
        "0: targets = {foo::Bar::T}, decl\n"
        // FIXME: avoid the 2 duplicated foo::Bar references below, the first
        // one comes from ClassTemplateDecl; the second comes from the
        // underlying CXXRecordDecl.
        "1: targets = {foo::Bar}, decl\n"
        "2: targets = {foo::Bar}, decl\n"
        "3: targets = {foo::Bar}\n"
        "4: targets = {foo::Bar::f}, decl\n"
        "5: targets = {foo::Bar}\n"},
       // MemberExpr should know their using declaration.
       {R"cpp(
            struct X { void func(int); };
+10 −0
Original line number Diff line number Diff line
@@ -127,6 +127,16 @@ TEST(RenameTest, WithinFileRename) {
        void [[Foo]]::foo(int x) {}
      )cpp",

      // Rename template class, including constructor/destructor.
      R"cpp(
        template <typename T>
        class [[F^oo]] {
          [[F^oo]]();
          ~[[F^oo]]();
          void f([[Foo]] x);
        };
      )cpp",

      // Class in template argument.
      R"cpp(
        class [[F^oo]] {};
+1 −1
Original line number Diff line number Diff line
@@ -525,7 +525,7 @@ $InactiveCode[[]] #endif
        using $Typedef[[LVReference]] = $TemplateParameter[[T]] &;
        using $Typedef[[RVReference]] = $TemplateParameter[[T]]&&;
        using $Typedef[[Array]] = $TemplateParameter[[T]]*[3];
        using $Typedef[[MemberPointer]] = int (A::*)(int);
        using $Typedef[[MemberPointer]] = int ($Class[[A]]::*)(int);

        // Use various previously defined typedefs in a function type.
        void $Method[[func]](