summaryrefslogtreecommitdiff
path: root/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Tooling/Refactoring/Rename/USRFindingAction.cpp')
-rw-r--r--lib/Tooling/Refactoring/Rename/USRFindingAction.cpp54
1 files changed, 46 insertions, 8 deletions
diff --git a/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
index 2769802ad2bc..40b70d8a0590 100644
--- a/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
+++ b/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp
@@ -39,6 +39,21 @@ using namespace llvm;
namespace clang {
namespace tooling {
+const NamedDecl *getCanonicalSymbolDeclaration(const NamedDecl *FoundDecl) {
+ // If FoundDecl is a constructor or destructor, we want to instead take
+ // the Decl of the corresponding class.
+ if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
+ FoundDecl = CtorDecl->getParent();
+ else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
+ FoundDecl = DtorDecl->getParent();
+ // FIXME: (Alex L): Canonicalize implicit template instantions, just like
+ // the indexer does it.
+
+ // Note: please update the declaration's doc comment every time the
+ // canonicalization rules are changed.
+ return FoundDecl;
+}
+
namespace {
// \brief NamedDeclFindingConsumer should delegate finding USRs of given Decl to
// AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
@@ -58,6 +73,7 @@ public:
if (checkIfOverriddenFunctionAscends(OverriddenMethod))
USRSet.insert(getUSRForDecl(OverriddenMethod));
}
+ addUSRsOfInstantiatedMethods(MethodDecl);
} else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
handleCXXRecordDecl(RecordDecl);
} else if (const auto *TemplateDecl =
@@ -69,9 +85,13 @@ public:
return std::vector<std::string>(USRSet.begin(), USRSet.end());
}
+ bool shouldVisitTemplateInstantiations() const { return true; }
+
bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
if (MethodDecl->isVirtual())
OverriddenMethods.push_back(MethodDecl);
+ if (MethodDecl->getInstantiatedFromMemberFunction())
+ InstantiatedMethods.push_back(MethodDecl);
return true;
}
@@ -122,6 +142,20 @@ private:
addUSRsOfOverridenFunctions(OverriddenMethod);
}
+ void addUSRsOfInstantiatedMethods(const CXXMethodDecl *MethodDecl) {
+ // For renaming a class template method, all references of the instantiated
+ // member methods should be renamed too, so add USRs of the instantiated
+ // methods to the USR set.
+ USRSet.insert(getUSRForDecl(MethodDecl));
+ if (const auto *FT = MethodDecl->getInstantiatedFromMemberFunction())
+ USRSet.insert(getUSRForDecl(FT));
+ for (const auto *Method : InstantiatedMethods) {
+ if (USRSet.find(getUSRForDecl(
+ Method->getInstantiatedFromMemberFunction())) != USRSet.end())
+ USRSet.insert(getUSRForDecl(Method));
+ }
+ }
+
bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end())
@@ -135,10 +169,17 @@ private:
ASTContext &Context;
std::set<std::string> USRSet;
std::vector<const CXXMethodDecl *> OverriddenMethods;
+ std::vector<const CXXMethodDecl *> InstantiatedMethods;
std::vector<const ClassTemplatePartialSpecializationDecl *> PartialSpecs;
};
} // namespace
+std::vector<std::string> getUSRsForDeclaration(const NamedDecl *ND,
+ ASTContext &Context) {
+ AdditionalUSRFinder Finder(ND, Context);
+ return Finder.Find();
+}
+
class NamedDeclFindingConsumer : public ASTConsumer {
public:
NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets,
@@ -183,8 +224,11 @@ private:
return false;
}
- if (Force)
+ if (Force) {
+ SpellingNames.push_back(std::string());
+ USRList.push_back(std::vector<std::string>());
return true;
+ }
unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
@@ -193,13 +237,7 @@ private:
return false;
}
- // If FoundDecl is a constructor or destructor, we want to instead take
- // the Decl of the corresponding class.
- if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
- FoundDecl = CtorDecl->getParent();
- else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
- FoundDecl = DtorDecl->getParent();
-
+ FoundDecl = getCanonicalSymbolDeclaration(FoundDecl);
SpellingNames.push_back(FoundDecl->getNameAsString());
AdditionalUSRFinder Finder(FoundDecl, Context);
USRList.push_back(Finder.Find());