diff options
| author | vitalyisaev <[email protected]> | 2023-06-29 10:00:50 +0300 | 
|---|---|---|
| committer | vitalyisaev <[email protected]> | 2023-06-29 10:00:50 +0300 | 
| commit | 6ffe9e53658409f212834330e13564e4952558f6 (patch) | |
| tree | 85b1e00183517648b228aafa7c8fb07f5276f419 /contrib/libs/clang14/lib/Index/IndexDecl.cpp | |
| parent | 726057070f9c5a91fc10fde0d5024913d10f1ab9 (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.cpp | 789 | 
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; +}  | 
