Home | History | Annotate | Line # | Download | only in Index
      1 //===- IndexBody.cpp - Indexing statements --------------------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 
      9 #include "IndexingContext.h"
     10 #include "clang/AST/RecursiveASTVisitor.h"
     11 #include "clang/AST/ASTLambda.h"
     12 
     13 using namespace clang;
     14 using namespace clang::index;
     15 
     16 namespace {
     17 
     18 class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
     19   IndexingContext &IndexCtx;
     20   const NamedDecl *Parent;
     21   const DeclContext *ParentDC;
     22   SmallVector<Stmt*, 16> StmtStack;
     23 
     24   typedef RecursiveASTVisitor<BodyIndexer> base;
     25 
     26   Stmt *getParentStmt() const {
     27     return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2];
     28   }
     29 public:
     30   BodyIndexer(IndexingContext &indexCtx,
     31               const NamedDecl *Parent, const DeclContext *DC)
     32     : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
     33 
     34   bool shouldWalkTypesOfTypeLocs() const { return false; }
     35 
     36   bool dataTraverseStmtPre(Stmt *S) {
     37     StmtStack.push_back(S);
     38     return true;
     39   }
     40 
     41   bool dataTraverseStmtPost(Stmt *S) {
     42     assert(StmtStack.back() == S);
     43     StmtStack.pop_back();
     44     return true;
     45   }
     46 
     47   bool TraverseTypeLoc(TypeLoc TL) {
     48     IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
     49     return true;
     50   }
     51 
     52   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
     53     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
     54     return true;
     55   }
     56 
     57   SymbolRoleSet getRolesForRef(const Expr *E,
     58                                SmallVectorImpl<SymbolRelation> &Relations) {
     59     SymbolRoleSet Roles{};
     60     assert(!StmtStack.empty() && E == StmtStack.back());
     61     if (StmtStack.size() == 1)
     62       return Roles;
     63     auto It = StmtStack.end()-2;
     64     while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
     65       if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
     66         if (ICE->getCastKind() == CK_LValueToRValue)
     67           Roles |= (unsigned)(unsigned)SymbolRole::Read;
     68       }
     69       if (It == StmtStack.begin())
     70         break;
     71       --It;
     72     }
     73     const Stmt *Parent = *It;
     74 
     75     if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
     76       if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
     77         Roles |= (unsigned)SymbolRole::Write;
     78 
     79     } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
     80       if (UO->isIncrementDecrementOp()) {
     81         Roles |= (unsigned)SymbolRole::Read;
     82         Roles |= (unsigned)SymbolRole::Write;
     83       } else if (UO->getOpcode() == UO_AddrOf) {
     84         Roles |= (unsigned)SymbolRole::AddressOf;
     85       }
     86 
     87     } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
     88       if (CA->getLHS()->IgnoreParenCasts() == E) {
     89         Roles |= (unsigned)SymbolRole::Read;
     90         Roles |= (unsigned)SymbolRole::Write;
     91       }
     92 
     93     } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
     94       if (CE->getCallee()->IgnoreParenCasts() == E) {
     95         addCallRole(Roles, Relations);
     96         if (auto *ME = dyn_cast<MemberExpr>(E)) {
     97           if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
     98             if (CXXMD->isVirtual() && !ME->hasQualifier()) {
     99               Roles |= (unsigned)SymbolRole::Dynamic;
    100               auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
    101               if (!BaseTy.isNull())
    102                 if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
    103                   Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
    104                                          CXXRD);
    105             }
    106         }
    107       } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
    108         if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
    109           OverloadedOperatorKind Op = CXXOp->getOperator();
    110           if (Op == OO_Equal) {
    111             Roles |= (unsigned)SymbolRole::Write;
    112           } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
    113                      Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
    114                      Op == OO_PlusPlus || Op == OO_MinusMinus) {
    115             Roles |= (unsigned)SymbolRole::Read;
    116             Roles |= (unsigned)SymbolRole::Write;
    117           } else if (Op == OO_Amp) {
    118             Roles |= (unsigned)SymbolRole::AddressOf;
    119           }
    120         }
    121       }
    122     }
    123 
    124     return Roles;
    125   }
    126 
    127   void addCallRole(SymbolRoleSet &Roles,
    128                    SmallVectorImpl<SymbolRelation> &Relations) {
    129     Roles |= (unsigned)SymbolRole::Call;
    130     if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
    131       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
    132     else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
    133       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
    134   }
    135 
    136   bool VisitDeclRefExpr(DeclRefExpr *E) {
    137     SmallVector<SymbolRelation, 4> Relations;
    138     SymbolRoleSet Roles = getRolesForRef(E, Relations);
    139     return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
    140                                     Parent, ParentDC, Roles, Relations, E);
    141   }
    142 
    143   bool VisitMemberExpr(MemberExpr *E) {
    144     SourceLocation Loc = E->getMemberLoc();
    145     if (Loc.isInvalid())
    146       Loc = E->getBeginLoc();
    147     SmallVector<SymbolRelation, 4> Relations;
    148     SymbolRoleSet Roles = getRolesForRef(E, Relations);
    149     return IndexCtx.handleReference(E->getMemberDecl(), Loc,
    150                                     Parent, ParentDC, Roles, Relations, E);
    151   }
    152 
    153   bool indexDependentReference(
    154       const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo,
    155       llvm::function_ref<bool(const NamedDecl *ND)> Filter) {
    156     if (!T)
    157       return true;
    158     const TemplateSpecializationType *TST =
    159         T->getAs<TemplateSpecializationType>();
    160     if (!TST)
    161       return true;
    162     TemplateName TN = TST->getTemplateName();
    163     const ClassTemplateDecl *TD =
    164         dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl());
    165     if (!TD)
    166       return true;
    167     CXXRecordDecl *RD = TD->getTemplatedDecl();
    168     if (!RD->hasDefinition())
    169       return true;
    170     RD = RD->getDefinition();
    171     std::vector<const NamedDecl *> Symbols =
    172         RD->lookupDependentName(NameInfo.getName(), Filter);
    173     // FIXME: Improve overload handling.
    174     if (Symbols.size() != 1)
    175       return true;
    176     SourceLocation Loc = NameInfo.getLoc();
    177     if (Loc.isInvalid())
    178       Loc = E->getBeginLoc();
    179     SmallVector<SymbolRelation, 4> Relations;
    180     SymbolRoleSet Roles = getRolesForRef(E, Relations);
    181     return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles,
    182                                     Relations, E);
    183   }
    184 
    185   bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) {
    186     const DeclarationNameInfo &Info = E->getMemberNameInfo();
    187     return indexDependentReference(
    188         E, E->getBaseType().getTypePtrOrNull(), Info,
    189         [](const NamedDecl *D) { return D->isCXXInstanceMember(); });
    190   }
    191 
    192   bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) {
    193     const DeclarationNameInfo &Info = E->getNameInfo();
    194     const NestedNameSpecifier *NNS = E->getQualifier();
    195     return indexDependentReference(
    196         E, NNS->getAsType(), Info,
    197         [](const NamedDecl *D) { return !D->isCXXInstanceMember(); });
    198   }
    199 
    200   bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
    201     for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
    202       if (D.isFieldDesignator() && D.getField())
    203         return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
    204                                         ParentDC, SymbolRoleSet(), {}, E);
    205     }
    206     return true;
    207   }
    208 
    209   bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
    210     SmallVector<SymbolRelation, 4> Relations;
    211     SymbolRoleSet Roles = getRolesForRef(E, Relations);
    212     return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
    213                                     Parent, ParentDC, Roles, Relations, E);
    214   }
    215 
    216   bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
    217     auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
    218       if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
    219         return false;
    220       if (auto *RecE = dyn_cast<ObjCMessageExpr>(
    221               MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
    222         if (RecE->getMethodFamily() == OMF_alloc)
    223           return false;
    224       }
    225       return true;
    226     };
    227 
    228     if (ObjCMethodDecl *MD = E->getMethodDecl()) {
    229       SymbolRoleSet Roles{};
    230       SmallVector<SymbolRelation, 2> Relations;
    231       addCallRole(Roles, Relations);
    232       Stmt *Containing = getParentStmt();
    233 
    234       auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool {
    235         const auto *E = POE->getSyntacticForm();
    236         if (const auto *BinOp = dyn_cast<BinaryOperator>(E))
    237           E = BinOp->getLHS();
    238         const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E);
    239         if (!PRE)
    240           return false;
    241         if (PRE->isExplicitProperty())
    242           return false;
    243         if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) {
    244           // Class properties that are explicitly defined using @property
    245           // declarations are represented implicitly as there is no ivar for
    246           // class properties.
    247           if (Getter->isClassMethod() &&
    248               Getter->getCanonicalDecl()->findPropertyDecl())
    249             return false;
    250         }
    251         return true;
    252       };
    253       bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing);
    254       // Implicit property message sends are not 'implicit'.
    255       if ((E->isImplicit() || IsPropCall) &&
    256           !(IsPropCall &&
    257             IsImplicitProperty(cast<PseudoObjectExpr>(Containing))))
    258         Roles |= (unsigned)SymbolRole::Implicit;
    259 
    260       if (isDynamic(E)) {
    261         Roles |= (unsigned)SymbolRole::Dynamic;
    262 
    263         auto addReceivers = [&](const ObjCObjectType *Ty) {
    264           if (!Ty)
    265             return;
    266           if (const auto *clsD = Ty->getInterface()) {
    267             Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
    268                                    clsD);
    269           }
    270           for (const auto *protD : Ty->quals()) {
    271             Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
    272                                    protD);
    273           }
    274         };
    275         QualType recT = E->getReceiverType();
    276         if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>())
    277           addReceivers(Ptr->getObjectType());
    278         else
    279           addReceivers(recT->getAs<ObjCObjectType>());
    280       }
    281 
    282       return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
    283                                       Parent, ParentDC, Roles, Relations, E);
    284     }
    285     return true;
    286   }
    287 
    288   bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
    289     if (E->isClassReceiver())
    290       IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(),
    291                                Parent, ParentDC);
    292     if (E->isExplicitProperty()) {
    293       SmallVector<SymbolRelation, 2> Relations;
    294       SymbolRoleSet Roles = getRolesForRef(E, Relations);
    295       return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
    296                                       Parent, ParentDC, Roles, Relations, E);
    297     } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) {
    298       // Class properties that are explicitly defined using @property
    299       // declarations are represented implicitly as there is no ivar for class
    300       // properties.
    301       if (Getter->isClassMethod()) {
    302         if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) {
    303           SmallVector<SymbolRelation, 2> Relations;
    304           SymbolRoleSet Roles = getRolesForRef(E, Relations);
    305           return IndexCtx.handleReference(PD, E->getLocation(), Parent,
    306                                           ParentDC, Roles, Relations, E);
    307         }
    308       }
    309     }
    310 
    311     // No need to do a handleReference for the objc method, because there will
    312     // be a message expr as part of PseudoObjectExpr.
    313     return true;
    314   }
    315 
    316   bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
    317     return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
    318                                     Parent, ParentDC, SymbolRoleSet(), {}, E);
    319   }
    320 
    321   bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
    322     return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
    323                                     Parent, ParentDC, SymbolRoleSet(), {}, E);
    324   }
    325 
    326   bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
    327     SymbolRoleSet Roles{};
    328     SmallVector<SymbolRelation, 2> Relations;
    329     addCallRole(Roles, Relations);
    330     Roles |= (unsigned)SymbolRole::Implicit;
    331     return IndexCtx.handleReference(MD, E->getBeginLoc(), Parent, ParentDC,
    332                                     Roles, Relations, E);
    333   }
    334 
    335   bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
    336     if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
    337       return passObjCLiteralMethodCall(MD, E);
    338     }
    339     return true;
    340   }
    341 
    342   bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
    343     if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
    344       return passObjCLiteralMethodCall(MD, E);
    345     }
    346     return true;
    347   }
    348 
    349   bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
    350     if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
    351       return passObjCLiteralMethodCall(MD, E);
    352     }
    353     return true;
    354   }
    355 
    356   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    357     SymbolRoleSet Roles{};
    358     SmallVector<SymbolRelation, 2> Relations;
    359     addCallRole(Roles, Relations);
    360     return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
    361                                     Parent, ParentDC, Roles, Relations, E);
    362   }
    363 
    364   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
    365                                    DataRecursionQueue *Q = nullptr) {
    366     if (E->getOperatorLoc().isInvalid())
    367       return true; // implicit.
    368     return base::TraverseCXXOperatorCallExpr(E, Q);
    369   }
    370 
    371   bool VisitDeclStmt(DeclStmt *S) {
    372     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
    373       IndexCtx.indexDeclGroupRef(S->getDeclGroup());
    374       return true;
    375     }
    376 
    377     DeclGroupRef DG = S->getDeclGroup();
    378     for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
    379       const Decl *D = *I;
    380       if (!D)
    381         continue;
    382       if (!isFunctionLocalSymbol(D))
    383         IndexCtx.indexTopLevelDecl(D);
    384     }
    385 
    386     return true;
    387   }
    388 
    389   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C,
    390                              Expr *Init) {
    391     if (C->capturesThis() || C->capturesVLAType())
    392       return true;
    393 
    394     if (!base::TraverseStmt(Init))
    395       return false;
    396 
    397     if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
    398       return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
    399                                       Parent, ParentDC, SymbolRoleSet());
    400 
    401     return true;
    402   }
    403 
    404   // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
    405   // the things that we visit. Make sure to only visit the semantic form.
    406   // Also visit things that are in the syntactic form but not the semantic one,
    407   // for example the indices in DesignatedInitExprs.
    408   bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
    409     auto visitForm = [&](InitListExpr *Form) {
    410       for (Stmt *SubStmt : Form->children()) {
    411         if (!TraverseStmt(SubStmt, Q))
    412           return false;
    413       }
    414       return true;
    415     };
    416 
    417     auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool {
    418       for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
    419         if (D.isFieldDesignator() && D.getField())
    420           return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
    421                                           Parent, ParentDC, SymbolRoleSet(),
    422                                           {}, E);
    423       }
    424       return true;
    425     };
    426 
    427     InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
    428     InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
    429 
    430     if (SemaForm) {
    431       // Visit things present in syntactic form but not the semantic form.
    432       if (SyntaxForm) {
    433         for (Expr *init : SyntaxForm->inits()) {
    434           if (auto *DIE = dyn_cast<DesignatedInitExpr>(init))
    435             visitSyntacticDesignatedInitExpr(DIE);
    436         }
    437       }
    438       return visitForm(SemaForm);
    439     }
    440 
    441     // No semantic, try the syntactic.
    442     if (SyntaxForm) {
    443       return visitForm(SyntaxForm);
    444     }
    445 
    446     return true;
    447   }
    448 
    449   bool VisitOffsetOfExpr(OffsetOfExpr *S) {
    450     for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) {
    451       const OffsetOfNode &Component = S->getComponent(I);
    452       if (Component.getKind() == OffsetOfNode::Field)
    453         IndexCtx.handleReference(Component.getField(), Component.getEndLoc(),
    454                                  Parent, ParentDC, SymbolRoleSet(), {});
    455       // FIXME: Try to resolve dependent field references.
    456     }
    457     return true;
    458   }
    459 
    460   bool VisitParmVarDecl(ParmVarDecl* D) {
    461     // Index the parameters of lambda expression.
    462     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
    463       const auto *DC = D->getDeclContext();
    464       if (DC && isLambdaCallOperator(DC))
    465         IndexCtx.handleDecl(D);
    466     }
    467     return true;
    468   }
    469 
    470   bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) {
    471     SmallVector<SymbolRelation, 4> Relations;
    472     SymbolRoleSet Roles = getRolesForRef(E, Relations);
    473     for (auto *D : E->decls())
    474       IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles,
    475                                Relations, E);
    476     return true;
    477   }
    478 };
    479 
    480 } // anonymous namespace
    481 
    482 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
    483                                 const DeclContext *DC) {
    484   if (!S)
    485     return;
    486 
    487   if (!DC)
    488     DC = Parent->getLexicalDeclContext();
    489   BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
    490 }
    491