10b57cec5SDimitry Andric //===- IndexBody.cpp - Indexing statements --------------------------------===// 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 #include "IndexingContext.h" 1081ad6265SDimitry Andric #include "clang/AST/ASTConcept.h" 110b57cec5SDimitry Andric #include "clang/AST/ASTLambda.h" 1281ad6265SDimitry Andric #include "clang/AST/DeclCXX.h" 1381ad6265SDimitry Andric #include "clang/AST/ExprConcepts.h" 1481ad6265SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 1581ad6265SDimitry Andric #include "clang/AST/Type.h" 160b57cec5SDimitry Andric 170b57cec5SDimitry Andric using namespace clang; 180b57cec5SDimitry Andric using namespace clang::index; 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric namespace { 210b57cec5SDimitry Andric 220b57cec5SDimitry Andric class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> { 230b57cec5SDimitry Andric IndexingContext &IndexCtx; 240b57cec5SDimitry Andric const NamedDecl *Parent; 250b57cec5SDimitry Andric const DeclContext *ParentDC; 260b57cec5SDimitry Andric SmallVector<Stmt*, 16> StmtStack; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric typedef RecursiveASTVisitor<BodyIndexer> base; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric Stmt *getParentStmt() const { 310b57cec5SDimitry Andric return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2]; 320b57cec5SDimitry Andric } 330b57cec5SDimitry Andric public: 340b57cec5SDimitry Andric BodyIndexer(IndexingContext &indexCtx, 350b57cec5SDimitry Andric const NamedDecl *Parent, const DeclContext *DC) 360b57cec5SDimitry Andric : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric bool shouldWalkTypesOfTypeLocs() const { return false; } 390b57cec5SDimitry Andric 400b57cec5SDimitry Andric bool dataTraverseStmtPre(Stmt *S) { 410b57cec5SDimitry Andric StmtStack.push_back(S); 420b57cec5SDimitry Andric return true; 430b57cec5SDimitry Andric } 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric bool dataTraverseStmtPost(Stmt *S) { 460b57cec5SDimitry Andric assert(StmtStack.back() == S); 470b57cec5SDimitry Andric StmtStack.pop_back(); 480b57cec5SDimitry Andric return true; 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric bool TraverseTypeLoc(TypeLoc TL) { 520b57cec5SDimitry Andric IndexCtx.indexTypeLoc(TL, Parent, ParentDC); 530b57cec5SDimitry Andric return true; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { 570b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); 580b57cec5SDimitry Andric return true; 590b57cec5SDimitry Andric } 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric SymbolRoleSet getRolesForRef(const Expr *E, 620b57cec5SDimitry Andric SmallVectorImpl<SymbolRelation> &Relations) { 630b57cec5SDimitry Andric SymbolRoleSet Roles{}; 640b57cec5SDimitry Andric assert(!StmtStack.empty() && E == StmtStack.back()); 650b57cec5SDimitry Andric if (StmtStack.size() == 1) 660b57cec5SDimitry Andric return Roles; 670b57cec5SDimitry Andric auto It = StmtStack.end()-2; 680b57cec5SDimitry Andric while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) { 690b57cec5SDimitry Andric if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) { 700b57cec5SDimitry Andric if (ICE->getCastKind() == CK_LValueToRValue) 710b57cec5SDimitry Andric Roles |= (unsigned)(unsigned)SymbolRole::Read; 720b57cec5SDimitry Andric } 730b57cec5SDimitry Andric if (It == StmtStack.begin()) 740b57cec5SDimitry Andric break; 750b57cec5SDimitry Andric --It; 760b57cec5SDimitry Andric } 770b57cec5SDimitry Andric const Stmt *Parent = *It; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric if (auto BO = dyn_cast<BinaryOperator>(Parent)) { 805f757f3fSDimitry Andric if (BO->getOpcode() == BO_Assign) { 815f757f3fSDimitry Andric if (BO->getLHS()->IgnoreParenCasts() == E) 820b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Write; 835f757f3fSDimitry Andric } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) { 845f757f3fSDimitry Andric if (CA->getLHS()->IgnoreParenCasts() == E) { 855f757f3fSDimitry Andric Roles |= (unsigned)SymbolRole::Read; 865f757f3fSDimitry Andric Roles |= (unsigned)SymbolRole::Write; 875f757f3fSDimitry Andric } 885f757f3fSDimitry Andric } 890b57cec5SDimitry Andric } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) { 900b57cec5SDimitry Andric if (UO->isIncrementDecrementOp()) { 910b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Read; 920b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Write; 930b57cec5SDimitry Andric } else if (UO->getOpcode() == UO_AddrOf) { 940b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::AddressOf; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric } else if (auto CE = dyn_cast<CallExpr>(Parent)) { 980b57cec5SDimitry Andric if (CE->getCallee()->IgnoreParenCasts() == E) { 990b57cec5SDimitry Andric addCallRole(Roles, Relations); 1000b57cec5SDimitry Andric if (auto *ME = dyn_cast<MemberExpr>(E)) { 1010b57cec5SDimitry Andric if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl())) 1020b57cec5SDimitry Andric if (CXXMD->isVirtual() && !ME->hasQualifier()) { 1030b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Dynamic; 1040b57cec5SDimitry Andric auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType(); 1050b57cec5SDimitry Andric if (!BaseTy.isNull()) 1060b57cec5SDimitry Andric if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl()) 1070b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 1080b57cec5SDimitry Andric CXXRD); 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) { 1120b57cec5SDimitry Andric if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) { 1130b57cec5SDimitry Andric OverloadedOperatorKind Op = CXXOp->getOperator(); 1140b57cec5SDimitry Andric if (Op == OO_Equal) { 1150b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Write; 1160b57cec5SDimitry Andric } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) || 1170b57cec5SDimitry Andric Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual || 1180b57cec5SDimitry Andric Op == OO_PlusPlus || Op == OO_MinusMinus) { 1190b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Read; 1200b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Write; 1210b57cec5SDimitry Andric } else if (Op == OO_Amp) { 1220b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::AddressOf; 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric return Roles; 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric void addCallRole(SymbolRoleSet &Roles, 1320b57cec5SDimitry Andric SmallVectorImpl<SymbolRelation> &Relations) { 1330b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Call; 1340b57cec5SDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(ParentDC)) 1350b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD); 1360b57cec5SDimitry Andric else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC)) 1370b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric bool VisitDeclRefExpr(DeclRefExpr *E) { 1410b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 1420b57cec5SDimitry Andric SymbolRoleSet Roles = getRolesForRef(E, Relations); 1430b57cec5SDimitry Andric return IndexCtx.handleReference(E->getDecl(), E->getLocation(), 1440b57cec5SDimitry Andric Parent, ParentDC, Roles, Relations, E); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1475f757f3fSDimitry Andric bool VisitGotoStmt(GotoStmt *S) { 1485f757f3fSDimitry Andric return IndexCtx.handleReference(S->getLabel(), S->getLabelLoc(), Parent, 1495f757f3fSDimitry Andric ParentDC); 1505f757f3fSDimitry Andric } 1515f757f3fSDimitry Andric 1525f757f3fSDimitry Andric bool VisitLabelStmt(LabelStmt *S) { 1535f757f3fSDimitry Andric if (IndexCtx.shouldIndexFunctionLocalSymbols()) 1545f757f3fSDimitry Andric return IndexCtx.handleDecl(S->getDecl()); 1555f757f3fSDimitry Andric return true; 1565f757f3fSDimitry Andric } 1575f757f3fSDimitry Andric 1580b57cec5SDimitry Andric bool VisitMemberExpr(MemberExpr *E) { 1590b57cec5SDimitry Andric SourceLocation Loc = E->getMemberLoc(); 1600b57cec5SDimitry Andric if (Loc.isInvalid()) 1610b57cec5SDimitry Andric Loc = E->getBeginLoc(); 1620b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 1630b57cec5SDimitry Andric SymbolRoleSet Roles = getRolesForRef(E, Relations); 1640b57cec5SDimitry Andric return IndexCtx.handleReference(E->getMemberDecl(), Loc, 1650b57cec5SDimitry Andric Parent, ParentDC, Roles, Relations, E); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric 1680b57cec5SDimitry Andric bool indexDependentReference( 1690b57cec5SDimitry Andric const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo, 1700b57cec5SDimitry Andric llvm::function_ref<bool(const NamedDecl *ND)> Filter) { 1710b57cec5SDimitry Andric if (!T) 1720b57cec5SDimitry Andric return true; 1730b57cec5SDimitry Andric const TemplateSpecializationType *TST = 1740b57cec5SDimitry Andric T->getAs<TemplateSpecializationType>(); 1750b57cec5SDimitry Andric if (!TST) 1760b57cec5SDimitry Andric return true; 1770b57cec5SDimitry Andric TemplateName TN = TST->getTemplateName(); 1780b57cec5SDimitry Andric const ClassTemplateDecl *TD = 1790b57cec5SDimitry Andric dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); 1800b57cec5SDimitry Andric if (!TD) 1810b57cec5SDimitry Andric return true; 1820b57cec5SDimitry Andric CXXRecordDecl *RD = TD->getTemplatedDecl(); 1830b57cec5SDimitry Andric if (!RD->hasDefinition()) 1840b57cec5SDimitry Andric return true; 1850b57cec5SDimitry Andric RD = RD->getDefinition(); 1860b57cec5SDimitry Andric std::vector<const NamedDecl *> Symbols = 1870b57cec5SDimitry Andric RD->lookupDependentName(NameInfo.getName(), Filter); 1880b57cec5SDimitry Andric // FIXME: Improve overload handling. 1890b57cec5SDimitry Andric if (Symbols.size() != 1) 1900b57cec5SDimitry Andric return true; 1910b57cec5SDimitry Andric SourceLocation Loc = NameInfo.getLoc(); 1920b57cec5SDimitry Andric if (Loc.isInvalid()) 1930b57cec5SDimitry Andric Loc = E->getBeginLoc(); 1940b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 1950b57cec5SDimitry Andric SymbolRoleSet Roles = getRolesForRef(E, Relations); 1960b57cec5SDimitry Andric return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles, 1970b57cec5SDimitry Andric Relations, E); 1980b57cec5SDimitry Andric } 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { 2010b57cec5SDimitry Andric const DeclarationNameInfo &Info = E->getMemberNameInfo(); 2020b57cec5SDimitry Andric return indexDependentReference( 2030b57cec5SDimitry Andric E, E->getBaseType().getTypePtrOrNull(), Info, 2040b57cec5SDimitry Andric [](const NamedDecl *D) { return D->isCXXInstanceMember(); }); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { 2080b57cec5SDimitry Andric const DeclarationNameInfo &Info = E->getNameInfo(); 2090b57cec5SDimitry Andric const NestedNameSpecifier *NNS = E->getQualifier(); 2100b57cec5SDimitry Andric return indexDependentReference( 2110b57cec5SDimitry Andric E, NNS->getAsType(), Info, 2120b57cec5SDimitry Andric [](const NamedDecl *D) { return !D->isCXXInstanceMember(); }); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { 2160b57cec5SDimitry Andric for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 21706c3fb27SDimitry Andric if (D.isFieldDesignator()) { 21806c3fb27SDimitry Andric if (const FieldDecl *FD = D.getFieldDecl()) { 21906c3fb27SDimitry Andric return IndexCtx.handleReference(FD, D.getFieldLoc(), Parent, 2200b57cec5SDimitry Andric ParentDC, SymbolRoleSet(), {}, E); 2210b57cec5SDimitry Andric } 22206c3fb27SDimitry Andric } 22306c3fb27SDimitry Andric } 2240b57cec5SDimitry Andric return true; 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 2280b57cec5SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 2290b57cec5SDimitry Andric SymbolRoleSet Roles = getRolesForRef(E, Relations); 2300b57cec5SDimitry Andric return IndexCtx.handleReference(E->getDecl(), E->getLocation(), 2310b57cec5SDimitry Andric Parent, ParentDC, Roles, Relations, E); 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 2350b57cec5SDimitry Andric auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool { 2360b57cec5SDimitry Andric if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) 2370b57cec5SDimitry Andric return false; 2380b57cec5SDimitry Andric if (auto *RecE = dyn_cast<ObjCMessageExpr>( 2390b57cec5SDimitry Andric MsgE->getInstanceReceiver()->IgnoreParenCasts())) { 2400b57cec5SDimitry Andric if (RecE->getMethodFamily() == OMF_alloc) 2410b57cec5SDimitry Andric return false; 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric return true; 2440b57cec5SDimitry Andric }; 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric if (ObjCMethodDecl *MD = E->getMethodDecl()) { 2470b57cec5SDimitry Andric SymbolRoleSet Roles{}; 2480b57cec5SDimitry Andric SmallVector<SymbolRelation, 2> Relations; 2490b57cec5SDimitry Andric addCallRole(Roles, Relations); 2500b57cec5SDimitry Andric Stmt *Containing = getParentStmt(); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool { 2530b57cec5SDimitry Andric const auto *E = POE->getSyntacticForm(); 2540b57cec5SDimitry Andric if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) 2550b57cec5SDimitry Andric E = BinOp->getLHS(); 2560b57cec5SDimitry Andric const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E); 2570b57cec5SDimitry Andric if (!PRE) 2580b57cec5SDimitry Andric return false; 2590b57cec5SDimitry Andric if (PRE->isExplicitProperty()) 2600b57cec5SDimitry Andric return false; 2610b57cec5SDimitry Andric if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) { 2620b57cec5SDimitry Andric // Class properties that are explicitly defined using @property 2630b57cec5SDimitry Andric // declarations are represented implicitly as there is no ivar for 2640b57cec5SDimitry Andric // class properties. 2650b57cec5SDimitry Andric if (Getter->isClassMethod() && 2660b57cec5SDimitry Andric Getter->getCanonicalDecl()->findPropertyDecl()) 2670b57cec5SDimitry Andric return false; 2680b57cec5SDimitry Andric } 2690b57cec5SDimitry Andric return true; 2700b57cec5SDimitry Andric }; 271*0fca6ea1SDimitry Andric bool IsPropCall = isa_and_nonnull<PseudoObjectExpr>(Containing); 2720b57cec5SDimitry Andric // Implicit property message sends are not 'implicit'. 2730b57cec5SDimitry Andric if ((E->isImplicit() || IsPropCall) && 2740b57cec5SDimitry Andric !(IsPropCall && 2750b57cec5SDimitry Andric IsImplicitProperty(cast<PseudoObjectExpr>(Containing)))) 2760b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Implicit; 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric if (isDynamic(E)) { 2790b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Dynamic; 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric auto addReceivers = [&](const ObjCObjectType *Ty) { 2820b57cec5SDimitry Andric if (!Ty) 2830b57cec5SDimitry Andric return; 2840b57cec5SDimitry Andric if (const auto *clsD = Ty->getInterface()) { 2850b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 2860b57cec5SDimitry Andric clsD); 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric for (const auto *protD : Ty->quals()) { 2890b57cec5SDimitry Andric Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 2900b57cec5SDimitry Andric protD); 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric }; 2930b57cec5SDimitry Andric QualType recT = E->getReceiverType(); 2940b57cec5SDimitry Andric if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>()) 2950b57cec5SDimitry Andric addReceivers(Ptr->getObjectType()); 2960b57cec5SDimitry Andric else 2970b57cec5SDimitry Andric addReceivers(recT->getAs<ObjCObjectType>()); 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric return IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 3010b57cec5SDimitry Andric Parent, ParentDC, Roles, Relations, E); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric return true; 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { 3070b57cec5SDimitry Andric if (E->isExplicitProperty()) { 3080b57cec5SDimitry Andric SmallVector<SymbolRelation, 2> Relations; 3090b57cec5SDimitry Andric SymbolRoleSet Roles = getRolesForRef(E, Relations); 3100b57cec5SDimitry Andric return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 3110b57cec5SDimitry Andric Parent, ParentDC, Roles, Relations, E); 3120b57cec5SDimitry Andric } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) { 3130b57cec5SDimitry Andric // Class properties that are explicitly defined using @property 3140b57cec5SDimitry Andric // declarations are represented implicitly as there is no ivar for class 3150b57cec5SDimitry Andric // properties. 3160b57cec5SDimitry Andric if (Getter->isClassMethod()) { 3170b57cec5SDimitry Andric if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) { 3180b57cec5SDimitry Andric SmallVector<SymbolRelation, 2> Relations; 3190b57cec5SDimitry Andric SymbolRoleSet Roles = getRolesForRef(E, Relations); 3200b57cec5SDimitry Andric return IndexCtx.handleReference(PD, E->getLocation(), Parent, 3210b57cec5SDimitry Andric ParentDC, Roles, Relations, E); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric } 3250b57cec5SDimitry Andric 3260b57cec5SDimitry Andric // No need to do a handleReference for the objc method, because there will 3270b57cec5SDimitry Andric // be a message expr as part of PseudoObjectExpr. 3280b57cec5SDimitry Andric return true; 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { 3320b57cec5SDimitry Andric return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), 3330b57cec5SDimitry Andric Parent, ParentDC, SymbolRoleSet(), {}, E); 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { 3370b57cec5SDimitry Andric return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), 3380b57cec5SDimitry Andric Parent, ParentDC, SymbolRoleSet(), {}, E); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric 3410b57cec5SDimitry Andric bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) { 3420b57cec5SDimitry Andric SymbolRoleSet Roles{}; 3430b57cec5SDimitry Andric SmallVector<SymbolRelation, 2> Relations; 3440b57cec5SDimitry Andric addCallRole(Roles, Relations); 3450b57cec5SDimitry Andric Roles |= (unsigned)SymbolRole::Implicit; 3460b57cec5SDimitry Andric return IndexCtx.handleReference(MD, E->getBeginLoc(), Parent, ParentDC, 3470b57cec5SDimitry Andric Roles, Relations, E); 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric 3500b57cec5SDimitry Andric bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { 3510b57cec5SDimitry Andric if (ObjCMethodDecl *MD = E->getBoxingMethod()) { 3520b57cec5SDimitry Andric return passObjCLiteralMethodCall(MD, E); 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric return true; 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { 3580b57cec5SDimitry Andric if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { 3590b57cec5SDimitry Andric return passObjCLiteralMethodCall(MD, E); 3600b57cec5SDimitry Andric } 3610b57cec5SDimitry Andric return true; 3620b57cec5SDimitry Andric } 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { 3650b57cec5SDimitry Andric if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { 3660b57cec5SDimitry Andric return passObjCLiteralMethodCall(MD, E); 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric return true; 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric bool VisitCXXConstructExpr(CXXConstructExpr *E) { 3720b57cec5SDimitry Andric SymbolRoleSet Roles{}; 3730b57cec5SDimitry Andric SmallVector<SymbolRelation, 2> Relations; 3740b57cec5SDimitry Andric addCallRole(Roles, Relations); 3750b57cec5SDimitry Andric return IndexCtx.handleReference(E->getConstructor(), E->getLocation(), 3760b57cec5SDimitry Andric Parent, ParentDC, Roles, Relations, E); 3770b57cec5SDimitry Andric } 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, 3800b57cec5SDimitry Andric DataRecursionQueue *Q = nullptr) { 3810b57cec5SDimitry Andric if (E->getOperatorLoc().isInvalid()) 3820b57cec5SDimitry Andric return true; // implicit. 3830b57cec5SDimitry Andric return base::TraverseCXXOperatorCallExpr(E, Q); 3840b57cec5SDimitry Andric } 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric bool VisitDeclStmt(DeclStmt *S) { 3870b57cec5SDimitry Andric if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 3880b57cec5SDimitry Andric IndexCtx.indexDeclGroupRef(S->getDeclGroup()); 3890b57cec5SDimitry Andric return true; 3900b57cec5SDimitry Andric } 3910b57cec5SDimitry Andric 3920b57cec5SDimitry Andric DeclGroupRef DG = S->getDeclGroup(); 3930b57cec5SDimitry Andric for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 3940b57cec5SDimitry Andric const Decl *D = *I; 3950b57cec5SDimitry Andric if (!D) 3960b57cec5SDimitry Andric continue; 3970b57cec5SDimitry Andric if (!isFunctionLocalSymbol(D)) 3980b57cec5SDimitry Andric IndexCtx.indexTopLevelDecl(D); 3990b57cec5SDimitry Andric } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric return true; 4020b57cec5SDimitry Andric } 4030b57cec5SDimitry Andric 4040b57cec5SDimitry Andric bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, 4050b57cec5SDimitry Andric Expr *Init) { 4060b57cec5SDimitry Andric if (C->capturesThis() || C->capturesVLAType()) 4070b57cec5SDimitry Andric return true; 4080b57cec5SDimitry Andric 409e8d8bef9SDimitry Andric if (!base::TraverseStmt(Init)) 410e8d8bef9SDimitry Andric return false; 411e8d8bef9SDimitry Andric 4120b57cec5SDimitry Andric if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) 4130b57cec5SDimitry Andric return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), 4140b57cec5SDimitry Andric Parent, ParentDC, SymbolRoleSet()); 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric return true; 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating 4200b57cec5SDimitry Andric // the things that we visit. Make sure to only visit the semantic form. 4210b57cec5SDimitry Andric // Also visit things that are in the syntactic form but not the semantic one, 4220b57cec5SDimitry Andric // for example the indices in DesignatedInitExprs. 4230b57cec5SDimitry Andric bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { 4240b57cec5SDimitry Andric auto visitForm = [&](InitListExpr *Form) { 4250b57cec5SDimitry Andric for (Stmt *SubStmt : Form->children()) { 4260b57cec5SDimitry Andric if (!TraverseStmt(SubStmt, Q)) 4270b57cec5SDimitry Andric return false; 4280b57cec5SDimitry Andric } 4290b57cec5SDimitry Andric return true; 4300b57cec5SDimitry Andric }; 4310b57cec5SDimitry Andric 4320b57cec5SDimitry Andric auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool { 4330b57cec5SDimitry Andric for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 43406c3fb27SDimitry Andric if (D.isFieldDesignator()) { 43506c3fb27SDimitry Andric if (const FieldDecl *FD = D.getFieldDecl()) { 43606c3fb27SDimitry Andric return IndexCtx.handleReference(FD, D.getFieldLoc(), Parent, 43706c3fb27SDimitry Andric ParentDC, SymbolRoleSet(), 43806c3fb27SDimitry Andric /*Relations=*/{}, E); 43906c3fb27SDimitry Andric } 44006c3fb27SDimitry Andric } 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric return true; 4430b57cec5SDimitry Andric }; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); 4460b57cec5SDimitry Andric InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric if (SemaForm) { 4490b57cec5SDimitry Andric // Visit things present in syntactic form but not the semantic form. 4500b57cec5SDimitry Andric if (SyntaxForm) { 4510b57cec5SDimitry Andric for (Expr *init : SyntaxForm->inits()) { 4520b57cec5SDimitry Andric if (auto *DIE = dyn_cast<DesignatedInitExpr>(init)) 4530b57cec5SDimitry Andric visitSyntacticDesignatedInitExpr(DIE); 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric return visitForm(SemaForm); 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric // No semantic, try the syntactic. 4600b57cec5SDimitry Andric if (SyntaxForm) { 4610b57cec5SDimitry Andric return visitForm(SyntaxForm); 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric return true; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric bool VisitOffsetOfExpr(OffsetOfExpr *S) { 4680b57cec5SDimitry Andric for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { 4690b57cec5SDimitry Andric const OffsetOfNode &Component = S->getComponent(I); 4700b57cec5SDimitry Andric if (Component.getKind() == OffsetOfNode::Field) 4710b57cec5SDimitry Andric IndexCtx.handleReference(Component.getField(), Component.getEndLoc(), 4720b57cec5SDimitry Andric Parent, ParentDC, SymbolRoleSet(), {}); 4730b57cec5SDimitry Andric // FIXME: Try to resolve dependent field references. 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric return true; 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric 4780b57cec5SDimitry Andric bool VisitParmVarDecl(ParmVarDecl* D) { 47981ad6265SDimitry Andric // Index the parameters of lambda expression and requires expression. 4800b57cec5SDimitry Andric if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 4810b57cec5SDimitry Andric const auto *DC = D->getDeclContext(); 48281ad6265SDimitry Andric if (DC && (isLambdaCallOperator(DC) || isa<RequiresExprBodyDecl>(DC))) 4830b57cec5SDimitry Andric IndexCtx.handleDecl(D); 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric return true; 4860b57cec5SDimitry Andric } 487fe6060f1SDimitry Andric 488bdd1243dSDimitry Andric bool VisitOverloadExpr(OverloadExpr *E) { 489fe6060f1SDimitry Andric SmallVector<SymbolRelation, 4> Relations; 490fe6060f1SDimitry Andric SymbolRoleSet Roles = getRolesForRef(E, Relations); 491fe6060f1SDimitry Andric for (auto *D : E->decls()) 492fe6060f1SDimitry Andric IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles, 493fe6060f1SDimitry Andric Relations, E); 494fe6060f1SDimitry Andric return true; 495fe6060f1SDimitry Andric } 49681ad6265SDimitry Andric 49781ad6265SDimitry Andric bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) { 49881ad6265SDimitry Andric IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(), 49981ad6265SDimitry Andric Parent, ParentDC); 50081ad6265SDimitry Andric return true; 50181ad6265SDimitry Andric } 50281ad6265SDimitry Andric 50381ad6265SDimitry Andric bool TraverseTypeConstraint(const TypeConstraint *C) { 50481ad6265SDimitry Andric IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(), 50581ad6265SDimitry Andric Parent, ParentDC); 50681ad6265SDimitry Andric return RecursiveASTVisitor::TraverseTypeConstraint(C); 50781ad6265SDimitry Andric } 5080b57cec5SDimitry Andric }; 5090b57cec5SDimitry Andric 5100b57cec5SDimitry Andric } // anonymous namespace 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 5130b57cec5SDimitry Andric const DeclContext *DC) { 5140b57cec5SDimitry Andric if (!S) 5150b57cec5SDimitry Andric return; 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric if (!DC) 5180b57cec5SDimitry Andric DC = Parent->getLexicalDeclContext(); 5190b57cec5SDimitry Andric BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 5200b57cec5SDimitry Andric } 521