123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817 |
- //===- IndexDecl.cpp - Indexing declarations ------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "IndexingContext.h"
- #include "clang/AST/ASTConcept.h"
- #include "clang/AST/Attr.h"
- #include "clang/AST/Decl.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/AST/DeclVisitor.h"
- #include "clang/Index/IndexDataConsumer.h"
- #include "clang/Index/IndexSymbol.h"
- using namespace clang;
- using namespace index;
- #define TRY_DECL(D,CALL_EXPR) \
- do { \
- if (!IndexCtx.shouldIndex(D)) return true; \
- if (!CALL_EXPR) \
- return false; \
- } while (0)
- #define TRY_TO(CALL_EXPR) \
- do { \
- if (!CALL_EXPR) \
- return false; \
- } while (0)
- namespace {
- class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> {
- IndexingContext &IndexCtx;
- public:
- explicit IndexingDeclVisitor(IndexingContext &indexCtx)
- : IndexCtx(indexCtx) { }
- bool Handled = true;
- bool VisitDecl(const Decl *D) {
- Handled = false;
- return true;
- }
- void handleTemplateArgumentLoc(const TemplateArgumentLoc &TALoc,
- const NamedDecl *Parent,
- const DeclContext *DC) {
- const TemplateArgumentLocInfo &LocInfo = TALoc.getLocInfo();
- switch (TALoc.getArgument().getKind()) {
- case TemplateArgument::Expression:
- IndexCtx.indexBody(LocInfo.getAsExpr(), Parent, DC);
- break;
- case TemplateArgument::Type:
- IndexCtx.indexTypeSourceInfo(LocInfo.getAsTypeSourceInfo(), Parent, DC);
- break;
- case TemplateArgument::Template:
- case TemplateArgument::TemplateExpansion:
- IndexCtx.indexNestedNameSpecifierLoc(TALoc.getTemplateQualifierLoc(),
- Parent, DC);
- if (const TemplateDecl *TD = TALoc.getArgument()
- .getAsTemplateOrTemplatePattern()
- .getAsTemplateDecl()) {
- if (const NamedDecl *TTD = TD->getTemplatedDecl())
- IndexCtx.handleReference(TTD, TALoc.getTemplateNameLoc(), Parent, DC);
- }
- break;
- default:
- break;
- }
- }
- /// Returns true if the given method has been defined explicitly by the
- /// user.
- static bool hasUserDefined(const ObjCMethodDecl *D,
- const ObjCImplDecl *Container) {
- const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(),
- D->isInstanceMethod());
- return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition() &&
- !MD->isSynthesizedAccessorStub();
- }
- void handleDeclarator(const DeclaratorDecl *D,
- const NamedDecl *Parent = nullptr,
- bool isIBType = false) {
- if (!Parent) Parent = D;
- IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent,
- Parent->getLexicalDeclContext(),
- /*isBase=*/false, isIBType);
- IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent);
- auto IndexDefaultParmeterArgument = [&](const ParmVarDecl *Parm,
- const NamedDecl *Parent) {
- if (Parm->hasDefaultArg() && !Parm->hasUninstantiatedDefaultArg() &&
- !Parm->hasUnparsedDefaultArg())
- IndexCtx.indexBody(Parm->getDefaultArg(), Parent);
- };
- if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
- if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) {
- auto *DC = Parm->getDeclContext();
- if (auto *FD = dyn_cast<FunctionDecl>(DC)) {
- if (IndexCtx.shouldIndexParametersInDeclarations() ||
- FD->isThisDeclarationADefinition())
- IndexCtx.handleDecl(Parm);
- } else if (auto *MD = dyn_cast<ObjCMethodDecl>(DC)) {
- if (MD->isThisDeclarationADefinition())
- IndexCtx.handleDecl(Parm);
- } else {
- IndexCtx.handleDecl(Parm);
- }
- } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- if (IndexCtx.shouldIndexParametersInDeclarations() ||
- FD->isThisDeclarationADefinition()) {
- for (const auto *PI : FD->parameters()) {
- IndexDefaultParmeterArgument(PI, D);
- IndexCtx.handleDecl(PI);
- }
- }
- }
- } else {
- // Index the default parameter value for function definitions.
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (FD->isThisDeclarationADefinition()) {
- for (const auto *PV : FD->parameters()) {
- IndexDefaultParmeterArgument(PV, D);
- }
- }
- }
- }
- if (auto *C = D->getTrailingRequiresClause())
- IndexCtx.indexBody(C, Parent);
- }
- bool handleObjCMethod(const ObjCMethodDecl *D,
- const ObjCPropertyDecl *AssociatedProp = nullptr) {
- SmallVector<SymbolRelation, 4> Relations;
- SmallVector<const ObjCMethodDecl*, 4> Overriden;
- D->getOverriddenMethods(Overriden);
- for(auto overridden: Overriden) {
- Relations.emplace_back((unsigned) SymbolRole::RelationOverrideOf,
- overridden);
- }
- if (AssociatedProp)
- Relations.emplace_back((unsigned)SymbolRole::RelationAccessorOf,
- AssociatedProp);
- // getLocation() returns beginning token of a method declaration, but for
- // indexing purposes we want to point to the base name.
- SourceLocation MethodLoc = D->getSelectorStartLoc();
- if (MethodLoc.isInvalid())
- MethodLoc = D->getLocation();
- SourceLocation AttrLoc;
- // check for (getter=/setter=)
- if (AssociatedProp) {
- bool isGetter = !D->param_size();
- AttrLoc = isGetter ?
- AssociatedProp->getGetterNameLoc():
- AssociatedProp->getSetterNameLoc();
- }
- SymbolRoleSet Roles = (SymbolRoleSet)SymbolRole::Dynamic;
- if (D->isImplicit()) {
- if (AttrLoc.isValid()) {
- MethodLoc = AttrLoc;
- } else {
- Roles |= (SymbolRoleSet)SymbolRole::Implicit;
- }
- } else if (AttrLoc.isValid()) {
- IndexCtx.handleReference(D, AttrLoc, cast<NamedDecl>(D->getDeclContext()),
- D->getDeclContext(), 0);
- }
- TRY_DECL(D, IndexCtx.handleDecl(D, MethodLoc, Roles, Relations));
- IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D);
- bool hasIBActionAndFirst = D->hasAttr<IBActionAttr>();
- for (const auto *I : D->parameters()) {
- handleDeclarator(I, D, /*isIBType=*/hasIBActionAndFirst);
- hasIBActionAndFirst = false;
- }
- if (D->isThisDeclarationADefinition()) {
- const Stmt *Body = D->getBody();
- if (Body) {
- IndexCtx.indexBody(Body, D, D);
- }
- }
- return true;
- }
- /// Gather the declarations which the given declaration \D overrides in a
- /// pseudo-override manner.
- ///
- /// Pseudo-overrides occur when a class template specialization declares
- /// a declaration that has the same name as a similar declaration in the
- /// non-specialized template.
- void
- gatherTemplatePseudoOverrides(const NamedDecl *D,
- SmallVectorImpl<SymbolRelation> &Relations) {
- if (!IndexCtx.getLangOpts().CPlusPlus)
- return;
- const auto *CTSD =
- dyn_cast<ClassTemplateSpecializationDecl>(D->getLexicalDeclContext());
- if (!CTSD)
- return;
- llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *>
- Template = CTSD->getSpecializedTemplateOrPartial();
- if (const auto *CTD = Template.dyn_cast<ClassTemplateDecl *>()) {
- const CXXRecordDecl *Pattern = CTD->getTemplatedDecl();
- bool TypeOverride = isa<TypeDecl>(D);
- for (const NamedDecl *ND : Pattern->lookup(D->getDeclName())) {
- if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND))
- ND = CTD->getTemplatedDecl();
- if (ND->isImplicit())
- continue;
- // Types can override other types.
- if (!TypeOverride) {
- if (ND->getKind() != D->getKind())
- continue;
- } else if (!isa<TypeDecl>(ND))
- continue;
- if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
- const auto *DFD = cast<FunctionDecl>(D);
- // Function overrides are approximated using the number of parameters.
- if (FD->getStorageClass() != DFD->getStorageClass() ||
- FD->getNumParams() != DFD->getNumParams())
- continue;
- }
- Relations.emplace_back(
- SymbolRoleSet(SymbolRole::RelationSpecializationOf), ND);
- }
- }
- }
- bool VisitFunctionDecl(const FunctionDecl *D) {
- SymbolRoleSet Roles{};
- SmallVector<SymbolRelation, 4> Relations;
- if (auto *CXXMD = dyn_cast<CXXMethodDecl>(D)) {
- if (CXXMD->isVirtual())
- Roles |= (unsigned)SymbolRole::Dynamic;
- for (const CXXMethodDecl *O : CXXMD->overridden_methods()) {
- Relations.emplace_back((unsigned)SymbolRole::RelationOverrideOf, O);
- }
- }
- gatherTemplatePseudoOverrides(D, Relations);
- if (const auto *Base = D->getPrimaryTemplate())
- Relations.push_back(
- SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
- Base->getTemplatedDecl()));
- TRY_DECL(D, IndexCtx.handleDecl(D, Roles, Relations));
- handleDeclarator(D);
- if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
- IndexCtx.handleReference(Ctor->getParent(), Ctor->getLocation(),
- Ctor->getParent(), Ctor->getDeclContext(),
- (unsigned)SymbolRole::NameReference);
- // Constructor initializers.
- for (const auto *Init : Ctor->inits()) {
- if (Init->isWritten()) {
- IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D);
- if (const FieldDecl *Member = Init->getAnyMember())
- IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D,
- (unsigned)SymbolRole::Write);
- IndexCtx.indexBody(Init->getInit(), D, D);
- }
- }
- } else if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(D)) {
- if (auto TypeNameInfo = Dtor->getNameInfo().getNamedTypeInfo()) {
- IndexCtx.handleReference(Dtor->getParent(),
- TypeNameInfo->getTypeLoc().getBeginLoc(),
- Dtor->getParent(), Dtor->getDeclContext(),
- (unsigned)SymbolRole::NameReference);
- }
- } else if (const auto *Guide = dyn_cast<CXXDeductionGuideDecl>(D)) {
- IndexCtx.handleReference(Guide->getDeducedTemplate()->getTemplatedDecl(),
- Guide->getLocation(), Guide,
- Guide->getDeclContext());
- }
- // Template specialization arguments.
- if (const ASTTemplateArgumentListInfo *TemplateArgInfo =
- D->getTemplateSpecializationArgsAsWritten()) {
- for (const auto &Arg : TemplateArgInfo->arguments())
- handleTemplateArgumentLoc(Arg, D, D->getLexicalDeclContext());
- }
- if (D->isThisDeclarationADefinition()) {
- const Stmt *Body = D->getBody();
- if (Body) {
- IndexCtx.indexBody(Body, D, D);
- }
- }
- return true;
- }
- bool VisitVarDecl(const VarDecl *D) {
- SmallVector<SymbolRelation, 4> Relations;
- gatherTemplatePseudoOverrides(D, Relations);
- TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
- handleDeclarator(D);
- IndexCtx.indexBody(D->getInit(), D);
- return true;
- }
- bool VisitDecompositionDecl(const DecompositionDecl *D) {
- for (const auto *Binding : D->bindings())
- TRY_DECL(Binding, IndexCtx.handleDecl(Binding));
- return Base::VisitDecompositionDecl(D);
- }
- bool VisitFieldDecl(const FieldDecl *D) {
- SmallVector<SymbolRelation, 4> Relations;
- gatherTemplatePseudoOverrides(D, Relations);
- TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
- handleDeclarator(D);
- if (D->isBitField())
- IndexCtx.indexBody(D->getBitWidth(), D);
- else if (D->hasInClassInitializer())
- IndexCtx.indexBody(D->getInClassInitializer(), D);
- return true;
- }
- bool VisitObjCIvarDecl(const ObjCIvarDecl *D) {
- if (D->getSynthesize()) {
- // handled in VisitObjCPropertyImplDecl
- return true;
- }
- TRY_DECL(D, IndexCtx.handleDecl(D));
- handleDeclarator(D);
- return true;
- }
- bool VisitMSPropertyDecl(const MSPropertyDecl *D) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
- handleDeclarator(D);
- return true;
- }
- bool VisitEnumConstantDecl(const EnumConstantDecl *D) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
- IndexCtx.indexBody(D->getInitExpr(), D);
- return true;
- }
- bool VisitTypedefNameDecl(const TypedefNameDecl *D) {
- if (!D->isTransparentTag()) {
- SmallVector<SymbolRelation, 4> Relations;
- gatherTemplatePseudoOverrides(D, Relations);
- TRY_DECL(D, IndexCtx.handleDecl(D, SymbolRoleSet(), Relations));
- IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
- }
- return true;
- }
- bool VisitTagDecl(const TagDecl *D) {
- // Non-free standing tags are handled in indexTypeSourceInfo.
- if (D->isFreeStanding()) {
- if (D->isThisDeclarationADefinition()) {
- SmallVector<SymbolRelation, 4> Relations;
- gatherTemplatePseudoOverrides(D, Relations);
- IndexCtx.indexTagDecl(D, Relations);
- } else {
- SmallVector<SymbolRelation, 1> Relations;
- gatherTemplatePseudoOverrides(D, Relations);
- return IndexCtx.handleDecl(D, D->getLocation(), SymbolRoleSet(),
- Relations, D->getLexicalDeclContext());
- }
- }
- return true;
- }
- bool VisitEnumDecl(const EnumDecl *ED) {
- TRY_TO(VisitTagDecl(ED));
- // Indexing for enumdecl itself is handled inside TagDecl, we just want to
- // visit integer-base here, which is different than other TagDecl bases.
- if (auto *TSI = ED->getIntegerTypeSourceInfo())
- IndexCtx.indexTypeSourceInfo(TSI, ED, ED, /*isBase=*/true);
- return true;
- }
- bool handleReferencedProtocols(const ObjCProtocolList &ProtList,
- const ObjCContainerDecl *ContD,
- SourceLocation SuperLoc) {
- ObjCInterfaceDecl::protocol_loc_iterator LI = ProtList.loc_begin();
- for (ObjCInterfaceDecl::protocol_iterator
- I = ProtList.begin(), E = ProtList.end(); I != E; ++I, ++LI) {
- SourceLocation Loc = *LI;
- ObjCProtocolDecl *PD = *I;
- SymbolRoleSet roles{};
- if (Loc == SuperLoc)
- roles |= (SymbolRoleSet)SymbolRole::Implicit;
- TRY_TO(IndexCtx.handleReference(PD, Loc, ContD, ContD, roles,
- SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, ContD}));
- }
- return true;
- }
- bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
- if (D->isThisDeclarationADefinition()) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
- SourceLocation SuperLoc = D->getSuperClassLoc();
- if (auto *SuperD = D->getSuperClass()) {
- bool hasSuperTypedef = false;
- if (auto *TInfo = D->getSuperClassTInfo()) {
- if (auto *TT = TInfo->getType()->getAs<TypedefType>()) {
- if (auto *TD = TT->getDecl()) {
- hasSuperTypedef = true;
- TRY_TO(IndexCtx.handleReference(TD, SuperLoc, D, D,
- SymbolRoleSet()));
- }
- }
- }
- SymbolRoleSet superRoles{};
- if (hasSuperTypedef)
- superRoles |= (SymbolRoleSet)SymbolRole::Implicit;
- TRY_TO(IndexCtx.handleReference(SuperD, SuperLoc, D, D, superRoles,
- SymbolRelation{(unsigned)SymbolRole::RelationBaseOf, D}));
- }
- TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
- SuperLoc));
- TRY_TO(IndexCtx.indexDeclContext(D));
- } else {
- return IndexCtx.handleReference(D, D->getLocation(), nullptr,
- D->getDeclContext(), SymbolRoleSet());
- }
- return true;
- }
- bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
- if (D->isThisDeclarationADefinition()) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
- TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
- /*SuperLoc=*/SourceLocation()));
- TRY_TO(IndexCtx.indexDeclContext(D));
- } else {
- return IndexCtx.handleReference(D, D->getLocation(), nullptr,
- D->getDeclContext(), SymbolRoleSet());
- }
- return true;
- }
- bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) {
- const ObjCInterfaceDecl *Class = D->getClassInterface();
- if (!Class)
- return true;
- if (Class->isImplicitInterfaceDecl())
- IndexCtx.handleDecl(Class);
- TRY_DECL(D, IndexCtx.handleDecl(D));
- // Visit implicit @synthesize property implementations first as their
- // location is reported at the name of the @implementation block. This
- // serves no purpose other than to simplify the FileCheck-based tests.
- for (const auto *I : D->property_impls()) {
- if (I->getLocation().isInvalid())
- IndexCtx.indexDecl(I);
- }
- for (const auto *I : D->decls()) {
- if (!isa<ObjCPropertyImplDecl>(I) ||
- cast<ObjCPropertyImplDecl>(I)->getLocation().isValid())
- IndexCtx.indexDecl(I);
- }
- return true;
- }
- bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
- if (!IndexCtx.shouldIndex(D))
- return true;
- const ObjCInterfaceDecl *C = D->getClassInterface();
- if (!C)
- return true;
- TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D, SymbolRoleSet(),
- SymbolRelation{
- (unsigned)SymbolRole::RelationExtendedBy, D
- }));
- SourceLocation CategoryLoc = D->getCategoryNameLoc();
- if (!CategoryLoc.isValid())
- CategoryLoc = D->getLocation();
- TRY_TO(IndexCtx.handleDecl(D, CategoryLoc));
- TRY_TO(handleReferencedProtocols(D->getReferencedProtocols(), D,
- /*SuperLoc=*/SourceLocation()));
- TRY_TO(IndexCtx.indexDeclContext(D));
- return true;
- }
- bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
- const ObjCCategoryDecl *Cat = D->getCategoryDecl();
- if (!Cat)
- return true;
- const ObjCInterfaceDecl *C = D->getClassInterface();
- if (C)
- TRY_TO(IndexCtx.handleReference(C, D->getLocation(), D, D,
- SymbolRoleSet()));
- SourceLocation CategoryLoc = D->getCategoryNameLoc();
- if (!CategoryLoc.isValid())
- CategoryLoc = D->getLocation();
- TRY_DECL(D, IndexCtx.handleDecl(D, CategoryLoc));
- IndexCtx.indexDeclContext(D);
- return true;
- }
- bool VisitObjCMethodDecl(const ObjCMethodDecl *D) {
- // Methods associated with a property, even user-declared ones, are
- // handled when we handle the property.
- if (D->isPropertyAccessor())
- return true;
- handleObjCMethod(D);
- return true;
- }
- bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
- if (ObjCMethodDecl *MD = D->getGetterMethodDecl())
- if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
- handleObjCMethod(MD, D);
- if (ObjCMethodDecl *MD = D->getSetterMethodDecl())
- if (MD->getLexicalDeclContext() == D->getLexicalDeclContext())
- handleObjCMethod(MD, D);
- TRY_DECL(D, IndexCtx.handleDecl(D));
- if (IBOutletCollectionAttr *attr = D->getAttr<IBOutletCollectionAttr>())
- IndexCtx.indexTypeSourceInfo(attr->getInterfaceLoc(), D,
- D->getLexicalDeclContext(), false, true);
- IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D);
- return true;
- }
- bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
- ObjCPropertyDecl *PD = D->getPropertyDecl();
- auto *Container = cast<ObjCImplDecl>(D->getDeclContext());
- SourceLocation Loc = D->getLocation();
- SymbolRoleSet Roles = 0;
- SmallVector<SymbolRelation, 1> Relations;
- if (ObjCIvarDecl *ID = D->getPropertyIvarDecl())
- Relations.push_back({(SymbolRoleSet)SymbolRole::RelationAccessorOf, ID});
- if (Loc.isInvalid()) {
- Loc = Container->getLocation();
- Roles |= (SymbolRoleSet)SymbolRole::Implicit;
- }
- TRY_DECL(D, IndexCtx.handleDecl(D, Loc, Roles, Relations));
- if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
- return true;
- assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize);
- SymbolRoleSet AccessorMethodRoles =
- SymbolRoleSet(SymbolRole::Dynamic) | SymbolRoleSet(SymbolRole::Implicit);
- if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) {
- if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
- IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
- }
- if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) {
- if (MD->isPropertyAccessor() && !hasUserDefined(MD, Container))
- IndexCtx.handleDecl(MD, Loc, AccessorMethodRoles, {}, Container);
- }
- if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) {
- if (IvarD->getSynthesize()) {
- // For synthesized ivars, use the location of its name in the
- // corresponding @synthesize. If there isn't one, use the containing
- // @implementation's location, rather than the property's location,
- // otherwise the header file containing the @interface will have different
- // indexing contents based on whether the @implementation was present or
- // not in the translation unit.
- SymbolRoleSet IvarRoles = 0;
- SourceLocation IvarLoc = D->getPropertyIvarDeclLoc();
- if (D->getLocation().isInvalid()) {
- IvarLoc = Container->getLocation();
- IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
- } else if (D->getLocation() == IvarLoc) {
- IvarRoles = (SymbolRoleSet)SymbolRole::Implicit;
- }
- TRY_DECL(IvarD, IndexCtx.handleDecl(IvarD, IvarLoc, IvarRoles));
- } else {
- IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr,
- D->getDeclContext(), SymbolRoleSet());
- }
- }
- return true;
- }
- bool VisitNamespaceDecl(const NamespaceDecl *D) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
- IndexCtx.indexDeclContext(D);
- return true;
- }
- bool VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
- IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
- IndexCtx.handleReference(D->getAliasedNamespace(), D->getTargetNameLoc(), D,
- D->getLexicalDeclContext());
- return true;
- }
- bool VisitUsingDecl(const UsingDecl *D) {
- IndexCtx.handleDecl(D);
- const DeclContext *DC = D->getDeclContext()->getRedeclContext();
- const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
- IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
- D->getLexicalDeclContext());
- for (const auto *I : D->shadows()) {
- // Skip unresolved using decls - we already have a decl for the using
- // itself, so there's not much point adding another decl or reference to
- // refer to the same location.
- if (isa<UnresolvedUsingIfExistsDecl>(I->getUnderlyingDecl()))
- continue;
- IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), Parent,
- D->getLexicalDeclContext(), SymbolRoleSet());
- }
- return true;
- }
- bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
- const DeclContext *DC = D->getDeclContext()->getRedeclContext();
- const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
- // NNS for the local 'using namespace' directives is visited by the body
- // visitor.
- if (!D->getParentFunctionOrMethod())
- IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
- D->getLexicalDeclContext());
- return IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(),
- D->getLocation(), Parent,
- D->getLexicalDeclContext(),
- SymbolRoleSet());
- }
- bool VisitUnresolvedUsingValueDecl(const UnresolvedUsingValueDecl *D) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
- const DeclContext *DC = D->getDeclContext()->getRedeclContext();
- const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
- IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
- D->getLexicalDeclContext());
- return true;
- }
- bool VisitUnresolvedUsingTypenameDecl(const UnresolvedUsingTypenameDecl *D) {
- TRY_DECL(D, IndexCtx.handleDecl(D));
- const DeclContext *DC = D->getDeclContext()->getRedeclContext();
- const NamedDecl *Parent = dyn_cast<NamedDecl>(DC);
- IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent,
- D->getLexicalDeclContext());
- return true;
- }
- bool VisitClassTemplateSpecializationDecl(const
- ClassTemplateSpecializationDecl *D) {
- // FIXME: Notify subsequent callbacks if info comes from implicit
- // instantiation.
- llvm::PointerUnion<ClassTemplateDecl *,
- ClassTemplatePartialSpecializationDecl *>
- Template = D->getSpecializedTemplateOrPartial();
- const Decl *SpecializationOf =
- Template.is<ClassTemplateDecl *>()
- ? (Decl *)Template.get<ClassTemplateDecl *>()
- : Template.get<ClassTemplatePartialSpecializationDecl *>();
- if (!D->isThisDeclarationADefinition())
- IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D);
- IndexCtx.indexTagDecl(
- D, SymbolRelation(SymbolRoleSet(SymbolRole::RelationSpecializationOf),
- SpecializationOf));
- if (TypeSourceInfo *TSI = D->getTypeAsWritten())
- IndexCtx.indexTypeSourceInfo(TSI, /*Parent=*/nullptr,
- D->getLexicalDeclContext());
- return true;
- }
- static bool shouldIndexTemplateParameterDefaultValue(const NamedDecl *D) {
- // We want to index the template parameters only once when indexing the
- // canonical declaration.
- if (!D)
- return false;
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- return FD->getCanonicalDecl() == FD;
- else if (const auto *TD = dyn_cast<TagDecl>(D))
- return TD->getCanonicalDecl() == TD;
- else if (const auto *VD = dyn_cast<VarDecl>(D))
- return VD->getCanonicalDecl() == VD;
- return true;
- }
- void indexTemplateParameters(TemplateParameterList *Params,
- const NamedDecl *Parent) {
- for (const NamedDecl *TP : *Params) {
- if (IndexCtx.shouldIndexTemplateParameters())
- IndexCtx.handleDecl(TP);
- if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(TP)) {
- if (TTP->hasDefaultArgument())
- IndexCtx.indexTypeSourceInfo(TTP->getDefaultArgumentInfo(), Parent);
- if (auto *C = TTP->getTypeConstraint())
- IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(),
- Parent, TTP->getLexicalDeclContext());
- } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) {
- if (NTTP->hasDefaultArgument())
- IndexCtx.indexBody(NTTP->getDefaultArgument(), Parent);
- } else if (const auto *TTPD = dyn_cast<TemplateTemplateParmDecl>(TP)) {
- if (TTPD->hasDefaultArgument())
- handleTemplateArgumentLoc(TTPD->getDefaultArgument(), Parent,
- TP->getLexicalDeclContext());
- }
- }
- if (auto *R = Params->getRequiresClause())
- IndexCtx.indexBody(R, Parent);
- }
- bool VisitTemplateDecl(const TemplateDecl *D) {
- const NamedDecl *Parent = D->getTemplatedDecl();
- if (!Parent)
- return true;
- // Index the default values for the template parameters.
- auto *Params = D->getTemplateParameters();
- if (Params && shouldIndexTemplateParameterDefaultValue(Parent)) {
- indexTemplateParameters(Params, Parent);
- }
- return Visit(Parent);
- }
- bool VisitConceptDecl(const ConceptDecl *D) {
- if (auto *Params = D->getTemplateParameters())
- indexTemplateParameters(Params, D);
- if (auto *E = D->getConstraintExpr())
- IndexCtx.indexBody(E, D);
- return IndexCtx.handleDecl(D);
- }
- bool VisitFriendDecl(const FriendDecl *D) {
- if (auto ND = D->getFriendDecl()) {
- // FIXME: Ignore a class template in a dependent context, these are not
- // linked properly with their redeclarations, ending up with duplicate
- // USRs.
- // See comment "Friend templates are visible in fairly strange ways." in
- // SemaTemplate.cpp which precedes code that prevents the friend template
- // from becoming visible from the enclosing context.
- if (isa<ClassTemplateDecl>(ND) && D->getDeclContext()->isDependentContext())
- return true;
- return Visit(ND);
- }
- if (auto Ty = D->getFriendType()) {
- IndexCtx.indexTypeSourceInfo(Ty, cast<NamedDecl>(D->getDeclContext()));
- }
- return true;
- }
- bool VisitImportDecl(const ImportDecl *D) {
- return IndexCtx.importedModule(D);
- }
- bool VisitStaticAssertDecl(const StaticAssertDecl *D) {
- IndexCtx.indexBody(D->getAssertExpr(),
- dyn_cast<NamedDecl>(D->getDeclContext()),
- D->getLexicalDeclContext());
- return true;
- }
- };
- } // anonymous namespace
- bool IndexingContext::indexDecl(const Decl *D) {
- if (D->isImplicit() && shouldIgnoreIfImplicit(D))
- return true;
- if (isTemplateImplicitInstantiation(D) && !shouldIndexImplicitInstantiation())
- return true;
- IndexingDeclVisitor Visitor(*this);
- bool ShouldContinue = Visitor.Visit(D);
- if (!ShouldContinue)
- return false;
- if (!Visitor.Handled && isa<DeclContext>(D))
- return indexDeclContext(cast<DeclContext>(D));
- return true;
- }
- bool IndexingContext::indexDeclContext(const DeclContext *DC) {
- for (const auto *I : DC->decls())
- if (!indexDecl(I))
- return false;
- return true;
- }
- bool IndexingContext::indexTopLevelDecl(const Decl *D) {
- if (!D || D->getLocation().isInvalid())
- return true;
- if (isa<ObjCMethodDecl>(D))
- return true; // Wait for the objc container.
- if (IndexOpts.ShouldTraverseDecl && !IndexOpts.ShouldTraverseDecl(D))
- return true; // skip
- return indexDecl(D);
- }
- bool IndexingContext::indexDeclGroupRef(DeclGroupRef DG) {
- for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
- if (!indexTopLevelDecl(*I))
- return false;
- return true;
- }
|