This revision was automatically updated to reflect the committed changes.
omtcyfz marked an inline comment as done.
Closed by commit rL277663: [clang-rename] improve USRFindingAction (authored by 
omtcyfz).

Changed prior to commit:
  https://reviews.llvm.org/D23058?vs=66670&id=66728#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D23058

Files:
  clang-tools-extra/trunk/clang-rename/USRFinder.cpp
  clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp
  clang-tools-extra/trunk/test/clang-rename/ComplexFunctionOverride.cpp
  clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiation.cpp
  
clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
  
clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp

Index: clang-tools-extra/trunk/clang-rename/USRFinder.cpp
===================================================================
--- clang-tools-extra/trunk/clang-rename/USRFinder.cpp
+++ clang-tools-extra/trunk/clang-rename/USRFinder.cpp
@@ -81,6 +81,11 @@
             dyn_cast<TemplateTypeParmType>(Loc.getType())) {
       return setResult(TemplateTypeParm->getDecl(), TypeBeginLoc, TypeEndLoc);
     }
+    if (const auto *TemplateSpecType =
+            dyn_cast<TemplateSpecializationType>(Loc.getType())) {
+      return setResult(TemplateSpecType->getTemplateName().getAsTemplateDecl(),
+                       TypeBeginLoc, TypeEndLoc);
+    }
     return setResult(Loc.getType()->getAsCXXRecordDecl(), TypeBeginLoc,
                      TypeEndLoc);
   }
Index: clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp
===================================================================
--- clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp
+++ clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp
@@ -20,7 +20,6 @@
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/RecursiveASTVisitor.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Frontend/CompilerInstance.h"
 #include "clang/Frontend/FrontendAction.h"
@@ -36,7 +35,6 @@
 
 
 using namespace llvm;
-using namespace clang::ast_matchers;
 
 namespace clang {
 namespace rename {
@@ -46,68 +44,101 @@
 // AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
 // Decl refers to class and adds USRs of all overridden methods if Decl refers
 // to virtual method.
-class AdditionalUSRFinder : public MatchFinder::MatchCallback {
+class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
 public:
   explicit AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context,
                              std::vector<std::string> *USRs)
-    : FoundDecl(FoundDecl), Context(Context), USRs(USRs), USRSet(), Finder() {}
+    : FoundDecl(FoundDecl), Context(Context), USRs(USRs) {}
 
   void Find() {
-    USRSet.insert(getUSRForDecl(FoundDecl));
+    // Fill OverriddenMethods and PartialSpecs storages.
+    TraverseDecl(Context.getTranslationUnitDecl());
     if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) {
-      addUSRsFromOverrideSets(MethodDecl);
-    }
-    if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
-      addUSRsOfCtorDtors(RecordDecl);
+      addUSRsOfOverridenFunctions(MethodDecl);
+      for (const auto &OverriddenMethod : OverriddenMethods) {
+        if (checkIfOverriddenFunctionAscends(OverriddenMethod)) {
+          USRSet.insert(getUSRForDecl(OverriddenMethod));
+        }
+      }
+    } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
+      handleCXXRecordDecl(RecordDecl);
+    } else if (const auto *TemplateDecl =
+               dyn_cast<ClassTemplateDecl>(FoundDecl)) {
+      handleClassTemplateDecl(TemplateDecl);
+    } else {
+      USRSet.insert(getUSRForDecl(FoundDecl));
     }
-    addMatchers();
-    Finder.matchAST(Context);
     USRs->insert(USRs->end(), USRSet.begin(), USRSet.end());
   }
 
+  bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
+    if (MethodDecl->isVirtual()) {
+      OverriddenMethods.push_back(MethodDecl);
+    }
+    return true;
+  }
+
+  bool VisitClassTemplatePartialSpecializationDecl(
+      const ClassTemplatePartialSpecializationDecl *PartialSpec) {
+    PartialSpecs.push_back(PartialSpec);
+    return true;
+  }
+
 private:
-  void addMatchers() {
-    const auto CXXMethodDeclMatcher =
-        cxxMethodDecl(forEachOverridden(cxxMethodDecl().bind("cxxMethodDecl")));
-    Finder.addMatcher(CXXMethodDeclMatcher, this);
+  void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
+    RecordDecl = RecordDecl->getDefinition();
+    if (const auto *ClassTemplateSpecDecl
+            = dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl)) {
+      handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
+    }
+    addUSRsOfCtorDtors(RecordDecl);
   }
 
-  // FIXME: Implement matchesUSR matchers to make lookups more efficient.
-  virtual void run(const MatchFinder::MatchResult &Result) {
-    const auto *VirtualMethod =
-        Result.Nodes.getNodeAs<CXXMethodDecl>("cxxMethodDecl");
-    bool Found = false;
-    for (const auto &OverriddenMethod : VirtualMethod->overridden_methods()) {
-      if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end()) {
-        Found = true;
-      }
+  void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
+    for (const auto *Specialization : TemplateDecl->specializations()) {
+      addUSRsOfCtorDtors(Specialization);
     }
-    if (Found) {
-      USRSet.insert(getUSRForDecl(VirtualMethod));
+    for (const auto *PartialSpec : PartialSpecs) {
+      if (PartialSpec->getSpecializedTemplate() == TemplateDecl) {
+        addUSRsOfCtorDtors(PartialSpec);
+      }
     }
+    addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
   void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {
     RecordDecl = RecordDecl->getDefinition();
     for (const auto *CtorDecl : RecordDecl->ctors()) {
       USRSet.insert(getUSRForDecl(CtorDecl));
     }
     USRSet.insert(getUSRForDecl(RecordDecl->getDestructor()));
+    USRSet.insert(getUSRForDecl(RecordDecl));
   }
 
-  void addUSRsFromOverrideSets(const CXXMethodDecl *MethodDecl) {
+  void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) {
     USRSet.insert(getUSRForDecl(MethodDecl));
     for (auto &OverriddenMethod : MethodDecl->overridden_methods()) {
       // Recursively visit each OverridenMethod.
-      addUSRsFromOverrideSets(OverriddenMethod);
+      addUSRsOfOverridenFunctions(OverriddenMethod);
+    }
+  }
+
+  bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
+    for (auto &OverriddenMethod : MethodDecl->overridden_methods()) {
+      if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end()) {
+        return true;
+      }
+      return checkIfOverriddenFunctionAscends(OverriddenMethod);
     }
+    return false;
   }
 
   const Decl *FoundDecl;
   ASTContext &Context;
   std::vector<std::string> *USRs;
   std::set<std::string> USRSet;
-  MatchFinder Finder;
+  std::vector<const CXXMethodDecl*> OverriddenMethods;
+  std::vector<const ClassTemplatePartialSpecializationDecl*> PartialSpecs;
 };
 } // namespace
 
Index: clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiation.cpp
===================================================================
--- clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiation.cpp
+++ clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiation.cpp
@@ -0,0 +1,44 @@
+template <typename T>
+class Foo {               // CHECK: class Bar {
+public:
+  T foo(T arg, T& ref, T* ptr) {
+    T value;
+    int number = 42;
+    value = (T)number;
+    value = static_cast<T>(number);
+    return value;
+  }
+  static void foo(T value) {}
+  T member;
+};
+
+template <typename T>
+void func() {
+  Foo<T> obj;             // CHECK: Bar<T> obj;
+  obj.member = T();
+  Foo<T>::foo();          // CHECK: Bar<T>::foo();
+}
+
+int main() {
+  Foo<int> i;             // CHECK: Bar<int> i;
+  i.member = 0;
+  Foo<int>::foo(0);       // CHECK: Bar<int>::foo(0);
+
+  Foo<bool> b;            // CHECK: Bar<bool> b;
+  b.member = false;
+  Foo<bool>::foo(false);  // CHECK: Bar<bool>::foo(false);
+
+  return 0;
+}
+
+// RUN: cat %s > %t-0.cpp
+// RUN: clang-rename -offset=29 -new-name=Bar %t-0.cpp -i -- -fno-delayed-template-parsing
+// RUN: sed 's,//.*,,' %t-0.cpp | FileCheck %s
+
+// RUN: cat %s > %t-1.cpp
+// RUN: clang-rename -offset=311 -new-name=Bar %t-1.cpp -i -- -fno-delayed-template-parsing
+// RUN: sed 's,//.*,,' %t-1.cpp | FileCheck %s
+
+// RUN: cat %s > %t-2.cpp
+// RUN: clang-rename -offset=445 -new-name=Bar %t-2.cpp -i -- -fno-delayed-template-parsing
+// RUN: sed 's,//.*,,' %t-2.cpp | FileCheck %s
Index: clang-tools-extra/trunk/test/clang-rename/ComplexFunctionOverride.cpp
===================================================================
--- clang-tools-extra/trunk/test/clang-rename/ComplexFunctionOverride.cpp
+++ clang-tools-extra/trunk/test/clang-rename/ComplexFunctionOverride.cpp
@@ -0,0 +1,23 @@
+// RUN: cat %s > %t.cpp
+// RUN: clang-rename -offset=307 -new-name=bar %t.cpp -i -- -std=c++11
+// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
+
+struct A {
+  virtual void foo();   // CHECK: virtual void bar();
+};
+
+struct B : A {
+  void foo() override;  // CHECK: void bar() override;
+};
+
+struct C : B {
+  void foo() override;  // CHECK: void bar() override;
+};
+
+struct D : B {
+  void foo() override;  // CHECK: void bar() override;
+};
+
+struct E : D {
+  void foo() override;  // CHECK: void bar() override;
+};
Index: clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp
===================================================================
--- clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp
+++ clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp
@@ -1,44 +0,0 @@
-// RUN: cat %s > %t.cpp
-// RUN: clang-rename -offset=703 -new-name=Bar %t.cpp -i --
-// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
-
-// Currently unsupported test.
-// FIXME: clang-rename should be able to rename classes with templates
-// correctly.
-// XFAIL: *
-
-template <typename T>
-class Foo {               // CHECK: class Bar;
-public:
-  T foo(T arg, T& ref, T* ptr) {
-    T value;
-    int number = 42;
-    value = (T)number;
-    value = static_cast<T>(number);
-    return value;
-  }
-  static void foo(T value) {}
-  T member;
-};
-
-template <typename T>
-void func() {
-  Foo<T> obj;             // CHECK: Bar<T> obj;
-  obj.member = T();
-  Foo<T>::foo();          // CHECK: Bar<T>::foo();
-}
-
-int main() {
-  Foo<int> i;             // CHECK: Bar<int> i;
-  i.member = 0;
-  Foo<int>::foo(0);       // CHECK: Bar<int>::foo(0);
-
-  Foo<bool> b;            // CHECK: Bar<bool> b;
-  b.member = false;
-  Foo<bool>::foo(false);  // CHECK: Bar<bool>::foo(false);
-
-  return 0;
-}
-
-// Use grep -FUbo 'Foo' <file> to get the correct offset of foo when changing
-// this file.
Index: clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
===================================================================
--- clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
+++ clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
@@ -1,44 +0,0 @@
-// RUN: cat %s > %t.cpp
-// RUN: clang-rename -offset=287 -new-name=Bar %t.cpp -i --
-// RUN: sed 's,//.*,,' %t.cpp | FileCheck %s
-
-// Currently unsupported test.
-// FIXME: clang-rename should be able to rename classes with templates
-// correctly.
-// XFAIL: *
-
-template <typename T>
-class Foo {               // CHECK: class Bar;
-public:
-  T foo(T arg, T& ref, T* ptr) {
-    T value;
-    int number = 42;
-    value = (T)number;
-    value = static_cast<T>(number);
-    return value;
-  }
-  static void foo(T value) {}
-  T member;
-};
-
-template <typename T>
-void func() {
-  Foo<T> obj;             // CHECK: Bar<T> obj;
-  obj.member = T();
-  Foo<T>::foo();          // CHECK: Bar<T>::foo();
-}
-
-int main() {
-  Foo<int> i;             // CHECK: Bar<int> i;
-  i.member = 0;
-  Foo<int>::foo(0);       // CHECK: Bar<int>::foo(0);
-
-  Foo<bool> b;            // CHECK: Bar<bool> b;
-  b.member = false;
-  Foo<bool>::foo(false);  // CHECK: Bar<bool>::foo(false);
-
-  return 0;
-}
-
-// Use grep -FUbo 'C' <file> to get the correct offset of foo when changing
-// this file.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to