summaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang14/lib/Index/IndexDecl.cpp
diff options
context:
space:
mode:
authorvitalyisaev <[email protected]>2023-06-29 10:00:50 +0300
committervitalyisaev <[email protected]>2023-06-29 10:00:50 +0300
commit6ffe9e53658409f212834330e13564e4952558f6 (patch)
tree85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang14/lib/Index/IndexDecl.cpp
parent726057070f9c5a91fc10fde0d5024913d10f1ab9 (diff)
YQ Connector: support managed ClickHouse
Со стороны dqrun можно обратиться к инстансу коннектора, который работает на streaming стенде, и извлечь данные из облачного CH.
Diffstat (limited to 'contrib/libs/clang14/lib/Index/IndexDecl.cpp')
-rw-r--r--contrib/libs/clang14/lib/Index/IndexDecl.cpp789
1 files changed, 789 insertions, 0 deletions
diff --git a/contrib/libs/clang14/lib/Index/IndexDecl.cpp b/contrib/libs/clang14/lib/Index/IndexDecl.cpp
new file mode 100644
index 00000000000..3139aedaf01
--- /dev/null
+++ b/contrib/libs/clang14/lib/Index/IndexDecl.cpp
@@ -0,0 +1,789 @@
+//===- 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/Attr.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/Index/IndexDataConsumer.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);
+ }
+ }
+ }
+ }
+ }
+
+ 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())
+ 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;
+ }
+
+ bool VisitTemplateDecl(const TemplateDecl *D) {
+
+ const NamedDecl *Parent = D->getTemplatedDecl();
+ if (!Parent)
+ return true;
+
+ // Index the default values for the template parameters.
+ if (D->getTemplateParameters() &&
+ shouldIndexTemplateParameterDefaultValue(Parent)) {
+ const TemplateParameterList *Params = D->getTemplateParameters();
+ 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);
+ } 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());
+ }
+ }
+ }
+
+ return Visit(Parent);
+ }
+
+ 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;
+}