47 class AdditionalUSRFinder :
public RecursiveASTVisitor<AdditionalUSRFinder> {
50 : FoundDecl(FoundDecl), Context(Context) {}
52 std::vector<std::string> Find() {
54 TraverseDecl(
Context.getTranslationUnitDecl());
55 if (
const auto *MethodDecl = dyn_cast<CXXMethodDecl>(
FoundDecl)) {
56 addUSRsOfOverridenFunctions(MethodDecl);
58 if (checkIfOverriddenFunctionAscends(OverriddenMethod))
61 }
else if (
const auto *RecordDecl = dyn_cast<CXXRecordDecl>(
FoundDecl)) {
62 handleCXXRecordDecl(RecordDecl);
63 }
else if (
const auto *TemplateDecl =
65 handleClassTemplateDecl(TemplateDecl);
69 return std::vector<std::string>(
USRSet.begin(),
USRSet.end());
72 bool VisitCXXMethodDecl(
const CXXMethodDecl *MethodDecl) {
73 if (MethodDecl->isVirtual())
74 OverriddenMethods.push_back(MethodDecl);
78 bool VisitClassTemplatePartialSpecializationDecl(
79 const ClassTemplatePartialSpecializationDecl *PartialSpec) {
85 void handleCXXRecordDecl(
const CXXRecordDecl *RecordDecl) {
86 RecordDecl = RecordDecl->getDefinition();
87 if (
const auto *ClassTemplateSpecDecl =
88 dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl))
89 handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
90 addUSRsOfCtorDtors(RecordDecl);
93 void handleClassTemplateDecl(
const ClassTemplateDecl *TemplateDecl) {
94 for (
const auto *Specialization : TemplateDecl->specializations())
95 addUSRsOfCtorDtors(Specialization);
98 if (PartialSpec->getSpecializedTemplate() == TemplateDecl)
99 addUSRsOfCtorDtors(PartialSpec);
101 addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
104 void addUSRsOfCtorDtors(
const CXXRecordDecl *RecordDecl) {
105 RecordDecl = RecordDecl->getDefinition();
111 for (
const auto *CtorDecl : RecordDecl->ctors())
118 void addUSRsOfOverridenFunctions(
const CXXMethodDecl *MethodDecl) {
121 for (
const auto &OverriddenMethod : MethodDecl->overridden_methods())
122 addUSRsOfOverridenFunctions(OverriddenMethod);
125 bool checkIfOverriddenFunctionAscends(
const CXXMethodDecl *MethodDecl) {
126 for (
const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
129 return checkIfOverriddenFunctionAscends(OverriddenMethod);
138 std::vector<const ClassTemplatePartialSpecializationDecl *>
PartialSpecs;
146 std::vector<std::string> &SpellingNames,
147 std::vector<std::vector<std::string>> &USRList,
148 bool Force,
bool &ErrorOccurred)
149 : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
150 SpellingNames(SpellingNames), USRList(USRList), Force(Force),
151 ErrorOccurred(ErrorOccurred) {}
155 unsigned SymbolOffset,
const std::string &QualifiedName) {
160 ErrorOccurred =
true;
163 "SourceLocation in file %0 at offset %1 is invalid");
175 if (FoundDecl ==
nullptr) {
176 if (QualifiedName.empty()) {
180 "clang-rename could not find symbol (offset %0)");
181 Engine.
Report(Point, CouldNotFindSymbolAt) << SymbolOffset;
182 ErrorOccurred =
true;
191 Engine.
Report(CouldNotFindSymbolNamed) << QualifiedName;
192 ErrorOccurred =
true;
198 if (
const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
199 FoundDecl = CtorDecl->getParent();
200 else if (
const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
201 FoundDecl = DtorDecl->getParent();
204 AdditionalUSRFinder
Finder(FoundDecl, Context);
205 USRList.push_back(
Finder.Find());
209 void HandleTranslationUnit(ASTContext &Context)
override {
210 const SourceManager &SourceMgr = Context.getSourceManager();
211 for (
unsigned Offset : SymbolOffsets) {
212 if (!FindSymbol(Context, SourceMgr,
Offset,
""))
215 for (
const std::string &QualifiedName : QualifiedNames) {
216 if (!FindSymbol(Context, SourceMgr, 0, QualifiedName))
223 std::vector<std::string> &SpellingNames;
224 std::vector<std::vector<std::string>> &USRList;
229 std::unique_ptr<ASTConsumer> USRFindingAction::newASTConsumer() {
230 return llvm::make_unique<NamedDeclFindingConsumer>(
231 SymbolOffsets, QualifiedNames, SpellingNames, USRList, Force,
Defines the clang::ASTContext interface.
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Defines the clang::FileManager interface and associated types.
const SourceLocation Point
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
std::vector< const CXXMethodDecl * > OverriddenMethods
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
Concrete class used by the front-end to report problems and issues.
std::string getNameAsString() const
getNameAsString - Get a human-readable name for the declaration, even if it is one of the special kin...
StringRef getName() const
Provides an action to find all relevant USRs at a point.
Methods for determining the USR of a symbol at a location in source code.
DiagnosticsEngine & getDiagnostics() const
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
Defines the clang::Preprocessor interface.
ASTMatchFinder *const Finder
Encodes a location in the source.
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
FileID getMainFileID() const
Returns the FileID of the main source file.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
std::set< std::string > USRSet
A SourceLocation and its associated SourceManager.
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
NamedDecl - This represents a decl with a name.
This class handles loading and caching of source files into memory.
std::vector< const ClassTemplatePartialSpecializationDecl * > PartialSpecs