xref: /freebsd/contrib/llvm-project/clang/lib/Tooling/Refactoring/Rename/USRFindingAction.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===--- USRFindingAction.cpp - Clang refactoring library -----------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Provides an action to find USR for the symbol at <offset>, as well as
110b57cec5SDimitry Andric /// all additional USRs.
120b57cec5SDimitry Andric ///
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "clang/Tooling/Refactoring/Rename/USRFindingAction.h"
160b57cec5SDimitry Andric #include "clang/AST/AST.h"
170b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h"
180b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
190b57cec5SDimitry Andric #include "clang/AST/Decl.h"
200b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
210b57cec5SDimitry Andric #include "clang/Basic/FileManager.h"
220b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h"
230b57cec5SDimitry Andric #include "clang/Frontend/FrontendAction.h"
240b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
250b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
260b57cec5SDimitry Andric #include "clang/Tooling/CommonOptionsParser.h"
270b57cec5SDimitry Andric #include "clang/Tooling/Refactoring.h"
280b57cec5SDimitry Andric #include "clang/Tooling/Refactoring/Rename/USRFinder.h"
290b57cec5SDimitry Andric #include "clang/Tooling/Tooling.h"
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #include <algorithm>
320b57cec5SDimitry Andric #include <set>
330b57cec5SDimitry Andric #include <string>
340b57cec5SDimitry Andric #include <vector>
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric namespace clang {
390b57cec5SDimitry Andric namespace tooling {
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric const NamedDecl *getCanonicalSymbolDeclaration(const NamedDecl *FoundDecl) {
42480093f4SDimitry Andric   if (!FoundDecl)
43480093f4SDimitry Andric     return nullptr;
440b57cec5SDimitry Andric   // If FoundDecl is a constructor or destructor, we want to instead take
450b57cec5SDimitry Andric   // the Decl of the corresponding class.
460b57cec5SDimitry Andric   if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(FoundDecl))
470b57cec5SDimitry Andric     FoundDecl = CtorDecl->getParent();
480b57cec5SDimitry Andric   else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(FoundDecl))
490b57cec5SDimitry Andric     FoundDecl = DtorDecl->getParent();
500b57cec5SDimitry Andric   // FIXME: (Alex L): Canonicalize implicit template instantions, just like
510b57cec5SDimitry Andric   // the indexer does it.
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   // Note: please update the declaration's doc comment every time the
540b57cec5SDimitry Andric   // canonicalization rules are changed.
550b57cec5SDimitry Andric   return FoundDecl;
560b57cec5SDimitry Andric }
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric namespace {
590b57cec5SDimitry Andric // NamedDeclFindingConsumer should delegate finding USRs of given Decl to
600b57cec5SDimitry Andric // AdditionalUSRFinder. AdditionalUSRFinder adds USRs of ctor and dtor if given
610b57cec5SDimitry Andric // Decl refers to class and adds USRs of all overridden methods if Decl refers
620b57cec5SDimitry Andric // to virtual method.
630b57cec5SDimitry Andric class AdditionalUSRFinder : public RecursiveASTVisitor<AdditionalUSRFinder> {
640b57cec5SDimitry Andric public:
650b57cec5SDimitry Andric   AdditionalUSRFinder(const Decl *FoundDecl, ASTContext &Context)
660b57cec5SDimitry Andric       : FoundDecl(FoundDecl), Context(Context) {}
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   std::vector<std::string> Find() {
690b57cec5SDimitry Andric     // Fill OverriddenMethods and PartialSpecs storages.
70480093f4SDimitry Andric     TraverseAST(Context);
710b57cec5SDimitry Andric     if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FoundDecl)) {
720b57cec5SDimitry Andric       addUSRsOfOverridenFunctions(MethodDecl);
730b57cec5SDimitry Andric       for (const auto &OverriddenMethod : OverriddenMethods) {
740b57cec5SDimitry Andric         if (checkIfOverriddenFunctionAscends(OverriddenMethod))
750b57cec5SDimitry Andric           USRSet.insert(getUSRForDecl(OverriddenMethod));
760b57cec5SDimitry Andric       }
770b57cec5SDimitry Andric       addUSRsOfInstantiatedMethods(MethodDecl);
780b57cec5SDimitry Andric     } else if (const auto *RecordDecl = dyn_cast<CXXRecordDecl>(FoundDecl)) {
790b57cec5SDimitry Andric       handleCXXRecordDecl(RecordDecl);
800b57cec5SDimitry Andric     } else if (const auto *TemplateDecl =
810b57cec5SDimitry Andric                    dyn_cast<ClassTemplateDecl>(FoundDecl)) {
820b57cec5SDimitry Andric       handleClassTemplateDecl(TemplateDecl);
83e8d8bef9SDimitry Andric     } else if (const auto *FD = dyn_cast<FunctionDecl>(FoundDecl)) {
84e8d8bef9SDimitry Andric       USRSet.insert(getUSRForDecl(FD));
85e8d8bef9SDimitry Andric       if (const auto *FTD = FD->getPrimaryTemplate())
86e8d8bef9SDimitry Andric         handleFunctionTemplateDecl(FTD);
87e8d8bef9SDimitry Andric     } else if (const auto *FD = dyn_cast<FunctionTemplateDecl>(FoundDecl)) {
88e8d8bef9SDimitry Andric       handleFunctionTemplateDecl(FD);
89e8d8bef9SDimitry Andric     } else if (const auto *VTD = dyn_cast<VarTemplateDecl>(FoundDecl)) {
90e8d8bef9SDimitry Andric       handleVarTemplateDecl(VTD);
91e8d8bef9SDimitry Andric     } else if (const auto *VD =
92e8d8bef9SDimitry Andric                    dyn_cast<VarTemplateSpecializationDecl>(FoundDecl)) {
93e8d8bef9SDimitry Andric       // FIXME: figure out why FoundDecl can be a VarTemplateSpecializationDecl.
94e8d8bef9SDimitry Andric       handleVarTemplateDecl(VD->getSpecializedTemplate());
95e8d8bef9SDimitry Andric     } else if (const auto *VD = dyn_cast<VarDecl>(FoundDecl)) {
96e8d8bef9SDimitry Andric       USRSet.insert(getUSRForDecl(VD));
97e8d8bef9SDimitry Andric       if (const auto *VTD = VD->getDescribedVarTemplate())
98e8d8bef9SDimitry Andric         handleVarTemplateDecl(VTD);
990b57cec5SDimitry Andric     } else {
1000b57cec5SDimitry Andric       USRSet.insert(getUSRForDecl(FoundDecl));
1010b57cec5SDimitry Andric     }
1020b57cec5SDimitry Andric     return std::vector<std::string>(USRSet.begin(), USRSet.end());
1030b57cec5SDimitry Andric   }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   bool shouldVisitTemplateInstantiations() const { return true; }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   bool VisitCXXMethodDecl(const CXXMethodDecl *MethodDecl) {
1080b57cec5SDimitry Andric     if (MethodDecl->isVirtual())
1090b57cec5SDimitry Andric       OverriddenMethods.push_back(MethodDecl);
1100b57cec5SDimitry Andric     if (MethodDecl->getInstantiatedFromMemberFunction())
1110b57cec5SDimitry Andric       InstantiatedMethods.push_back(MethodDecl);
1120b57cec5SDimitry Andric     return true;
1130b57cec5SDimitry Andric   }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric private:
1160b57cec5SDimitry Andric   void handleCXXRecordDecl(const CXXRecordDecl *RecordDecl) {
117a7dea167SDimitry Andric     if (!RecordDecl->getDefinition()) {
118a7dea167SDimitry Andric       USRSet.insert(getUSRForDecl(RecordDecl));
119a7dea167SDimitry Andric       return;
120a7dea167SDimitry Andric     }
1210b57cec5SDimitry Andric     RecordDecl = RecordDecl->getDefinition();
1220b57cec5SDimitry Andric     if (const auto *ClassTemplateSpecDecl =
1230b57cec5SDimitry Andric             dyn_cast<ClassTemplateSpecializationDecl>(RecordDecl))
1240b57cec5SDimitry Andric       handleClassTemplateDecl(ClassTemplateSpecDecl->getSpecializedTemplate());
1250b57cec5SDimitry Andric     addUSRsOfCtorDtors(RecordDecl);
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric   void handleClassTemplateDecl(const ClassTemplateDecl *TemplateDecl) {
1290b57cec5SDimitry Andric     for (const auto *Specialization : TemplateDecl->specializations())
1300b57cec5SDimitry Andric       addUSRsOfCtorDtors(Specialization);
131e8d8bef9SDimitry Andric     SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
132e8d8bef9SDimitry Andric     TemplateDecl->getPartialSpecializations(PartialSpecs);
133e8d8bef9SDimitry Andric     for (const auto *Spec : PartialSpecs)
134e8d8bef9SDimitry Andric       addUSRsOfCtorDtors(Spec);
1350b57cec5SDimitry Andric     addUSRsOfCtorDtors(TemplateDecl->getTemplatedDecl());
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric 
138e8d8bef9SDimitry Andric   void handleFunctionTemplateDecl(const FunctionTemplateDecl *FTD) {
139e8d8bef9SDimitry Andric     USRSet.insert(getUSRForDecl(FTD));
140e8d8bef9SDimitry Andric     USRSet.insert(getUSRForDecl(FTD->getTemplatedDecl()));
141e8d8bef9SDimitry Andric     for (const auto *S : FTD->specializations())
142e8d8bef9SDimitry Andric       USRSet.insert(getUSRForDecl(S));
143e8d8bef9SDimitry Andric   }
144e8d8bef9SDimitry Andric 
145e8d8bef9SDimitry Andric   void handleVarTemplateDecl(const VarTemplateDecl *VTD) {
146e8d8bef9SDimitry Andric     USRSet.insert(getUSRForDecl(VTD));
147e8d8bef9SDimitry Andric     USRSet.insert(getUSRForDecl(VTD->getTemplatedDecl()));
14881ad6265SDimitry Andric     for (const auto *Spec : VTD->specializations())
149e8d8bef9SDimitry Andric       USRSet.insert(getUSRForDecl(Spec));
150e8d8bef9SDimitry Andric     SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
151e8d8bef9SDimitry Andric     VTD->getPartialSpecializations(PartialSpecs);
15281ad6265SDimitry Andric     for (const auto *Spec : PartialSpecs)
153e8d8bef9SDimitry Andric       USRSet.insert(getUSRForDecl(Spec));
154e8d8bef9SDimitry Andric   }
155e8d8bef9SDimitry Andric 
1565ffd83dbSDimitry Andric   void addUSRsOfCtorDtors(const CXXRecordDecl *RD) {
1575ffd83dbSDimitry Andric     const auto* RecordDecl = RD->getDefinition();
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric     // Skip if the CXXRecordDecl doesn't have definition.
1605ffd83dbSDimitry Andric     if (!RecordDecl) {
1615ffd83dbSDimitry Andric       USRSet.insert(getUSRForDecl(RD));
1620b57cec5SDimitry Andric       return;
1635ffd83dbSDimitry Andric     }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric     for (const auto *CtorDecl : RecordDecl->ctors())
1660b57cec5SDimitry Andric       USRSet.insert(getUSRForDecl(CtorDecl));
1675ffd83dbSDimitry Andric     // Add template constructor decls, they are not in ctors() unfortunately.
1685ffd83dbSDimitry Andric     if (RecordDecl->hasUserDeclaredConstructor())
1695ffd83dbSDimitry Andric       for (const auto *D : RecordDecl->decls())
1705ffd83dbSDimitry Andric         if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
1715ffd83dbSDimitry Andric           if (const auto *Ctor =
1725ffd83dbSDimitry Andric                   dyn_cast<CXXConstructorDecl>(FTD->getTemplatedDecl()))
1735ffd83dbSDimitry Andric             USRSet.insert(getUSRForDecl(Ctor));
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric     USRSet.insert(getUSRForDecl(RecordDecl->getDestructor()));
1760b57cec5SDimitry Andric     USRSet.insert(getUSRForDecl(RecordDecl));
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   void addUSRsOfOverridenFunctions(const CXXMethodDecl *MethodDecl) {
1800b57cec5SDimitry Andric     USRSet.insert(getUSRForDecl(MethodDecl));
1810b57cec5SDimitry Andric     // Recursively visit each OverridenMethod.
1820b57cec5SDimitry Andric     for (const auto &OverriddenMethod : MethodDecl->overridden_methods())
1830b57cec5SDimitry Andric       addUSRsOfOverridenFunctions(OverriddenMethod);
1840b57cec5SDimitry Andric   }
1850b57cec5SDimitry Andric 
1860b57cec5SDimitry Andric   void addUSRsOfInstantiatedMethods(const CXXMethodDecl *MethodDecl) {
1870b57cec5SDimitry Andric     // For renaming a class template method, all references of the instantiated
1880b57cec5SDimitry Andric     // member methods should be renamed too, so add USRs of the instantiated
1890b57cec5SDimitry Andric     // methods to the USR set.
1900b57cec5SDimitry Andric     USRSet.insert(getUSRForDecl(MethodDecl));
1910b57cec5SDimitry Andric     if (const auto *FT = MethodDecl->getInstantiatedFromMemberFunction())
1920b57cec5SDimitry Andric       USRSet.insert(getUSRForDecl(FT));
1930b57cec5SDimitry Andric     for (const auto *Method : InstantiatedMethods) {
1940b57cec5SDimitry Andric       if (USRSet.find(getUSRForDecl(
1950b57cec5SDimitry Andric               Method->getInstantiatedFromMemberFunction())) != USRSet.end())
1960b57cec5SDimitry Andric         USRSet.insert(getUSRForDecl(Method));
1970b57cec5SDimitry Andric     }
1980b57cec5SDimitry Andric   }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   bool checkIfOverriddenFunctionAscends(const CXXMethodDecl *MethodDecl) {
2010b57cec5SDimitry Andric     for (const auto &OverriddenMethod : MethodDecl->overridden_methods()) {
2020b57cec5SDimitry Andric       if (USRSet.find(getUSRForDecl(OverriddenMethod)) != USRSet.end())
2030b57cec5SDimitry Andric         return true;
2040b57cec5SDimitry Andric       return checkIfOverriddenFunctionAscends(OverriddenMethod);
2050b57cec5SDimitry Andric     }
2060b57cec5SDimitry Andric     return false;
2070b57cec5SDimitry Andric   }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric   const Decl *FoundDecl;
2100b57cec5SDimitry Andric   ASTContext &Context;
2110b57cec5SDimitry Andric   std::set<std::string> USRSet;
2120b57cec5SDimitry Andric   std::vector<const CXXMethodDecl *> OverriddenMethods;
2130b57cec5SDimitry Andric   std::vector<const CXXMethodDecl *> InstantiatedMethods;
2140b57cec5SDimitry Andric };
2150b57cec5SDimitry Andric } // namespace
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric std::vector<std::string> getUSRsForDeclaration(const NamedDecl *ND,
2180b57cec5SDimitry Andric                                                ASTContext &Context) {
2190b57cec5SDimitry Andric   AdditionalUSRFinder Finder(ND, Context);
2200b57cec5SDimitry Andric   return Finder.Find();
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric class NamedDeclFindingConsumer : public ASTConsumer {
2240b57cec5SDimitry Andric public:
2250b57cec5SDimitry Andric   NamedDeclFindingConsumer(ArrayRef<unsigned> SymbolOffsets,
2260b57cec5SDimitry Andric                            ArrayRef<std::string> QualifiedNames,
2270b57cec5SDimitry Andric                            std::vector<std::string> &SpellingNames,
2280b57cec5SDimitry Andric                            std::vector<std::vector<std::string>> &USRList,
2290b57cec5SDimitry Andric                            bool Force, bool &ErrorOccurred)
2300b57cec5SDimitry Andric       : SymbolOffsets(SymbolOffsets), QualifiedNames(QualifiedNames),
2310b57cec5SDimitry Andric         SpellingNames(SpellingNames), USRList(USRList), Force(Force),
2320b57cec5SDimitry Andric         ErrorOccurred(ErrorOccurred) {}
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric private:
2350b57cec5SDimitry Andric   bool FindSymbol(ASTContext &Context, const SourceManager &SourceMgr,
2360b57cec5SDimitry Andric                   unsigned SymbolOffset, const std::string &QualifiedName) {
2370b57cec5SDimitry Andric     DiagnosticsEngine &Engine = Context.getDiagnostics();
2380b57cec5SDimitry Andric     const FileID MainFileID = SourceMgr.getMainFileID();
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric     if (SymbolOffset >= SourceMgr.getFileIDSize(MainFileID)) {
2410b57cec5SDimitry Andric       ErrorOccurred = true;
2420b57cec5SDimitry Andric       unsigned InvalidOffset = Engine.getCustomDiagID(
2430b57cec5SDimitry Andric           DiagnosticsEngine::Error,
2440b57cec5SDimitry Andric           "SourceLocation in file %0 at offset %1 is invalid");
2450b57cec5SDimitry Andric       Engine.Report(SourceLocation(), InvalidOffset)
246*5f757f3fSDimitry Andric           << SourceMgr.getFileEntryRefForID(MainFileID)->getName()
247*5f757f3fSDimitry Andric           << SymbolOffset;
2480b57cec5SDimitry Andric       return false;
2490b57cec5SDimitry Andric     }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric     const SourceLocation Point = SourceMgr.getLocForStartOfFile(MainFileID)
2520b57cec5SDimitry Andric                                      .getLocWithOffset(SymbolOffset);
2530b57cec5SDimitry Andric     const NamedDecl *FoundDecl = QualifiedName.empty()
2540b57cec5SDimitry Andric                                      ? getNamedDeclAt(Context, Point)
2550b57cec5SDimitry Andric                                      : getNamedDeclFor(Context, QualifiedName);
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric     if (FoundDecl == nullptr) {
2580b57cec5SDimitry Andric       if (QualifiedName.empty()) {
2590b57cec5SDimitry Andric         FullSourceLoc FullLoc(Point, SourceMgr);
2600b57cec5SDimitry Andric         unsigned CouldNotFindSymbolAt = Engine.getCustomDiagID(
2610b57cec5SDimitry Andric             DiagnosticsEngine::Error,
2620b57cec5SDimitry Andric             "clang-rename could not find symbol (offset %0)");
2630b57cec5SDimitry Andric         Engine.Report(Point, CouldNotFindSymbolAt) << SymbolOffset;
2640b57cec5SDimitry Andric         ErrorOccurred = true;
2650b57cec5SDimitry Andric         return false;
2660b57cec5SDimitry Andric       }
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric       if (Force) {
2690b57cec5SDimitry Andric         SpellingNames.push_back(std::string());
2700b57cec5SDimitry Andric         USRList.push_back(std::vector<std::string>());
2710b57cec5SDimitry Andric         return true;
2720b57cec5SDimitry Andric       }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric       unsigned CouldNotFindSymbolNamed = Engine.getCustomDiagID(
2750b57cec5SDimitry Andric           DiagnosticsEngine::Error, "clang-rename could not find symbol %0");
2760b57cec5SDimitry Andric       Engine.Report(CouldNotFindSymbolNamed) << QualifiedName;
2770b57cec5SDimitry Andric       ErrorOccurred = true;
2780b57cec5SDimitry Andric       return false;
2790b57cec5SDimitry Andric     }
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric     FoundDecl = getCanonicalSymbolDeclaration(FoundDecl);
2820b57cec5SDimitry Andric     SpellingNames.push_back(FoundDecl->getNameAsString());
2830b57cec5SDimitry Andric     AdditionalUSRFinder Finder(FoundDecl, Context);
2840b57cec5SDimitry Andric     USRList.push_back(Finder.Find());
2850b57cec5SDimitry Andric     return true;
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   void HandleTranslationUnit(ASTContext &Context) override {
2890b57cec5SDimitry Andric     const SourceManager &SourceMgr = Context.getSourceManager();
2900b57cec5SDimitry Andric     for (unsigned Offset : SymbolOffsets) {
2910b57cec5SDimitry Andric       if (!FindSymbol(Context, SourceMgr, Offset, ""))
2920b57cec5SDimitry Andric         return;
2930b57cec5SDimitry Andric     }
2940b57cec5SDimitry Andric     for (const std::string &QualifiedName : QualifiedNames) {
2950b57cec5SDimitry Andric       if (!FindSymbol(Context, SourceMgr, 0, QualifiedName))
2960b57cec5SDimitry Andric         return;
2970b57cec5SDimitry Andric     }
2980b57cec5SDimitry Andric   }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   ArrayRef<unsigned> SymbolOffsets;
3010b57cec5SDimitry Andric   ArrayRef<std::string> QualifiedNames;
3020b57cec5SDimitry Andric   std::vector<std::string> &SpellingNames;
3030b57cec5SDimitry Andric   std::vector<std::vector<std::string>> &USRList;
3040b57cec5SDimitry Andric   bool Force;
3050b57cec5SDimitry Andric   bool &ErrorOccurred;
3060b57cec5SDimitry Andric };
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric std::unique_ptr<ASTConsumer> USRFindingAction::newASTConsumer() {
309a7dea167SDimitry Andric   return std::make_unique<NamedDeclFindingConsumer>(
3100b57cec5SDimitry Andric       SymbolOffsets, QualifiedNames, SpellingNames, USRList, Force,
3110b57cec5SDimitry Andric       ErrorOccurred);
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
3140b57cec5SDimitry Andric } // end namespace tooling
3150b57cec5SDimitry Andric } // end namespace clang
316