[clang-tools-extra] r277663 - [clang-rename] improve USRFindingAction

Kirill Bobyrev via cfe-commits cfe-commits at lists.llvm.org
Wed Aug 3 16:00:32 PDT 2016


Author: omtcyfz
Date: Wed Aug  3 18:00:32 2016
New Revision: 277663

URL: http://llvm.org/viewvc/llvm-project?rev=277663&view=rev
Log:
[clang-rename] improve USRFindingAction

1. Improve templated class renaming, namely add capabilities of finding partial
and full specializations. Every class partial specialization has reference to
the specialized class. Thus, storing all partial specializations and
comparing specialized class decls to the FoundDecl solves this. All full class
specializations can be found by calling ClassTemplateDecl::specializations().

2. Fix virtual function and its overriding functions renaming. Renaming a
virtual function requires renaming every other function in its "overriding
graph".

3. Merge TemplateClassInstantiationFindBy{Declaration|TypeUse}.cpp tests into
one test by adding multiple invocations of clang-rename to one test, because
the only different thing across these tests is -offset passed to clang-rename.

Reviewers: alexfh

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

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

Modified: clang-tools-extra/trunk/clang-rename/USRFinder.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFinder.cpp?rev=277663&r1=277662&r2=277663&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-rename/USRFinder.cpp (original)
+++ clang-tools-extra/trunk/clang-rename/USRFinder.cpp Wed Aug  3 18:00:32 2016
@@ -81,6 +81,11 @@ public:
             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);
   }

Modified: clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp?rev=277663&r1=277662&r2=277663&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp (original)
+++ clang-tools-extra/trunk/clang-rename/USRFindingAction.cpp Wed Aug  3 18:00:32 2016
@@ -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,45 +44,66 @@ namespace {
 // 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);
+    }
+    for (const auto *PartialSpec : PartialSpecs) {
+      if (PartialSpec->getSpecializedTemplate() == TemplateDecl) {
+        addUSRsOfCtorDtors(PartialSpec);
       }
     }
-    if (Found) {
-      USRSet.insert(getUSRForDecl(VirtualMethod));
-    }
+    addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
   }
 
   void addUSRsOfCtorDtors(const CXXRecordDecl *RecordDecl) {
@@ -93,21 +112,33 @@ private:
       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
 

Added: clang-tools-extra/trunk/test/clang-rename/ComplexFunctionOverride.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-rename/ComplexFunctionOverride.cpp?rev=277663&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-rename/ComplexFunctionOverride.cpp (added)
+++ clang-tools-extra/trunk/test/clang-rename/ComplexFunctionOverride.cpp Wed Aug  3 18:00:32 2016
@@ -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;
+};

Added: clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiation.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiation.cpp?rev=277663&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiation.cpp (added)
+++ clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiation.cpp Wed Aug  3 18:00:32 2016
@@ -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

Removed: clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp?rev=277662&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp (original)
+++ clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByDeclaration.cpp (removed)
@@ -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.

Removed: clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp?rev=277662&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp (original)
+++ clang-tools-extra/trunk/test/clang-rename/TemplateClassInstantiationFindByTypeUse.cpp (removed)
@@ -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.




More information about the cfe-commits mailing list