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
getParentStmt() const300b57cec5SDimitry Andric Stmt *getParentStmt() const {
310b57cec5SDimitry Andric return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric public:
BodyIndexer(IndexingContext & indexCtx,const NamedDecl * Parent,const DeclContext * DC)340b57cec5SDimitry Andric BodyIndexer(IndexingContext &indexCtx,
350b57cec5SDimitry Andric const NamedDecl *Parent, const DeclContext *DC)
360b57cec5SDimitry Andric : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
370b57cec5SDimitry Andric
shouldWalkTypesOfTypeLocs() const380b57cec5SDimitry Andric bool shouldWalkTypesOfTypeLocs() const { return false; }
390b57cec5SDimitry Andric
dataTraverseStmtPre(Stmt * S)400b57cec5SDimitry Andric bool dataTraverseStmtPre(Stmt *S) {
410b57cec5SDimitry Andric StmtStack.push_back(S);
420b57cec5SDimitry Andric return true;
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric
dataTraverseStmtPost(Stmt * S)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
TraverseTypeLoc(TypeLoc TL)510b57cec5SDimitry Andric bool TraverseTypeLoc(TypeLoc TL) {
520b57cec5SDimitry Andric IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
530b57cec5SDimitry Andric return true;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric
TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS)560b57cec5SDimitry Andric bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
570b57cec5SDimitry Andric IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
580b57cec5SDimitry Andric return true;
590b57cec5SDimitry Andric }
600b57cec5SDimitry Andric
getRolesForRef(const Expr * E,SmallVectorImpl<SymbolRelation> & Relations)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
addCallRole(SymbolRoleSet & Roles,SmallVectorImpl<SymbolRelation> & Relations)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
VisitDeclRefExpr(DeclRefExpr * E)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
VisitGotoStmt(GotoStmt * S)1475f757f3fSDimitry Andric bool VisitGotoStmt(GotoStmt *S) {
1485f757f3fSDimitry Andric return IndexCtx.handleReference(S->getLabel(), S->getLabelLoc(), Parent,
1495f757f3fSDimitry Andric ParentDC);
1505f757f3fSDimitry Andric }
1515f757f3fSDimitry Andric
VisitLabelStmt(LabelStmt * S)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
VisitMemberExpr(MemberExpr * E)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
indexDependentReference(const Expr * E,const Type * T,const DeclarationNameInfo & NameInfo,llvm::function_ref<bool (const NamedDecl * ND)> Filter)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
VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr * E)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
VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr * E)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
VisitDesignatedInitExpr(DesignatedInitExpr * E)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
VisitObjCIvarRefExpr(ObjCIvarRefExpr * E)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
VisitObjCMessageExpr(ObjCMessageExpr * E)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
VisitObjCPropertyRefExpr(ObjCPropertyRefExpr * E)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
VisitMSPropertyRefExpr(MSPropertyRefExpr * E)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
VisitObjCProtocolExpr(ObjCProtocolExpr * E)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
passObjCLiteralMethodCall(const ObjCMethodDecl * MD,const Expr * E)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
VisitObjCBoxedExpr(ObjCBoxedExpr * E)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
VisitObjCDictionaryLiteral(ObjCDictionaryLiteral * E)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
VisitObjCArrayLiteral(ObjCArrayLiteral * E)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
VisitCXXConstructExpr(CXXConstructExpr * E)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
TraverseCXXOperatorCallExpr(CXXOperatorCallExpr * E,DataRecursionQueue * Q=nullptr)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
VisitDeclStmt(DeclStmt * S)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
TraverseLambdaCapture(LambdaExpr * LE,const LambdaCapture * C,Expr * Init)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.
TraverseInitListExpr(InitListExpr * S,DataRecursionQueue * Q=nullptr)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
VisitOffsetOfExpr(OffsetOfExpr * S)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
VisitParmVarDecl(ParmVarDecl * D)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
VisitOverloadExpr(OverloadExpr * E)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
VisitConceptSpecializationExpr(ConceptSpecializationExpr * R)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
TraverseTypeConstraint(const TypeConstraint * C)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
indexBody(const Stmt * S,const NamedDecl * Parent,const DeclContext * DC)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