xref: /freebsd-src/contrib/llvm-project/clang/lib/Index/IndexBody.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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