Home | History | Annotate | Download | only in Index
      1 //===- IndexBody.cpp - Indexing statements --------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "IndexingContext.h"
     11 #include "clang/AST/RecursiveASTVisitor.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 public:
     26   BodyIndexer(IndexingContext &indexCtx,
     27               const NamedDecl *Parent, const DeclContext *DC)
     28     : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
     29 
     30   bool shouldWalkTypesOfTypeLocs() const { return false; }
     31 
     32   bool dataTraverseStmtPre(Stmt *S) {
     33     StmtStack.push_back(S);
     34     return true;
     35   }
     36 
     37   bool dataTraverseStmtPost(Stmt *S) {
     38     assert(StmtStack.back() == S);
     39     StmtStack.pop_back();
     40     return true;
     41   }
     42 
     43   bool TraverseTypeLoc(TypeLoc TL) {
     44     IndexCtx.indexTypeLoc(TL, Parent, ParentDC);
     45     return true;
     46   }
     47 
     48   bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) {
     49     IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC);
     50     return true;
     51   }
     52 
     53   SymbolRoleSet getRolesForRef(const Expr *E,
     54                                SmallVectorImpl<SymbolRelation> &Relations) {
     55     SymbolRoleSet Roles{};
     56     assert(!StmtStack.empty() && E == StmtStack.back());
     57     if (StmtStack.size() == 1)
     58       return Roles;
     59     auto It = StmtStack.end()-2;
     60     while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) {
     61       if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) {
     62         if (ICE->getCastKind() == CK_LValueToRValue)
     63           Roles |= (unsigned)(unsigned)SymbolRole::Read;
     64       }
     65       if (It == StmtStack.begin())
     66         break;
     67       --It;
     68     }
     69     const Stmt *Parent = *It;
     70 
     71     if (auto BO = dyn_cast<BinaryOperator>(Parent)) {
     72       if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E)
     73         Roles |= (unsigned)SymbolRole::Write;
     74 
     75     } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) {
     76       if (UO->isIncrementDecrementOp()) {
     77         Roles |= (unsigned)SymbolRole::Read;
     78         Roles |= (unsigned)SymbolRole::Write;
     79       } else if (UO->getOpcode() == UO_AddrOf) {
     80         Roles |= (unsigned)SymbolRole::AddressOf;
     81       }
     82 
     83     } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) {
     84       if (CA->getLHS()->IgnoreParenCasts() == E) {
     85         Roles |= (unsigned)SymbolRole::Read;
     86         Roles |= (unsigned)SymbolRole::Write;
     87       }
     88 
     89     } else if (auto CE = dyn_cast<CallExpr>(Parent)) {
     90       if (CE->getCallee()->IgnoreParenCasts() == E) {
     91         addCallRole(Roles, Relations);
     92         if (auto *ME = dyn_cast<MemberExpr>(E)) {
     93           if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
     94             if (CXXMD->isVirtual() && !ME->hasQualifier()) {
     95               Roles |= (unsigned)SymbolRole::Dynamic;
     96               auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType();
     97               if (!BaseTy.isNull())
     98                 if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl())
     99                   Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy,
    100                                          CXXRD);
    101             }
    102         }
    103       } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) {
    104         if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) {
    105           OverloadedOperatorKind Op = CXXOp->getOperator();
    106           if (Op == OO_Equal) {
    107             Roles |= (unsigned)SymbolRole::Write;
    108           } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) ||
    109                      Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual ||
    110                      Op == OO_PlusPlus || Op == OO_MinusMinus) {
    111             Roles |= (unsigned)SymbolRole::Read;
    112             Roles |= (unsigned)SymbolRole::Write;
    113           } else if (Op == OO_Amp) {
    114             Roles |= (unsigned)SymbolRole::AddressOf;
    115           }
    116         }
    117       }
    118     }
    119 
    120     return Roles;
    121   }
    122 
    123   void addCallRole(SymbolRoleSet &Roles,
    124                    SmallVectorImpl<SymbolRelation> &Relations) {
    125     Roles |= (unsigned)SymbolRole::Call;
    126     if (auto *FD = dyn_cast<FunctionDecl>(ParentDC))
    127       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD);
    128     else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC))
    129       Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD);
    130   }
    131 
    132   bool VisitDeclRefExpr(DeclRefExpr *E) {
    133     SmallVector<SymbolRelation, 4> Relations;
    134     SymbolRoleSet Roles = getRolesForRef(E, Relations);
    135     return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
    136                                     Parent, ParentDC, Roles, Relations, E);
    137   }
    138 
    139   bool VisitMemberExpr(MemberExpr *E) {
    140     SourceLocation Loc = E->getMemberLoc();
    141     if (Loc.isInvalid())
    142       Loc = E->getLocStart();
    143     SmallVector<SymbolRelation, 4> Relations;
    144     SymbolRoleSet Roles = getRolesForRef(E, Relations);
    145     return IndexCtx.handleReference(E->getMemberDecl(), Loc,
    146                                     Parent, ParentDC, Roles, Relations, E);
    147   }
    148 
    149   bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
    150     for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
    151       if (D.isFieldDesignator())
    152         return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent,
    153                                         ParentDC, SymbolRoleSet(), {}, E);
    154     }
    155     return true;
    156   }
    157 
    158   bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) {
    159     SmallVector<SymbolRelation, 4> Relations;
    160     SymbolRoleSet Roles = getRolesForRef(E, Relations);
    161     return IndexCtx.handleReference(E->getDecl(), E->getLocation(),
    162                                     Parent, ParentDC, Roles, Relations, E);
    163   }
    164 
    165   bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
    166     auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool {
    167       if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance)
    168         return false;
    169       if (auto *RecE = dyn_cast<ObjCMessageExpr>(
    170               MsgE->getInstanceReceiver()->IgnoreParenCasts())) {
    171         if (RecE->getMethodFamily() == OMF_alloc)
    172           return false;
    173       }
    174       return true;
    175     };
    176 
    177     if (ObjCMethodDecl *MD = E->getMethodDecl()) {
    178       SymbolRoleSet Roles{};
    179       SmallVector<SymbolRelation, 2> Relations;
    180       addCallRole(Roles, Relations);
    181       if (E->isImplicit())
    182         Roles |= (unsigned)SymbolRole::Implicit;
    183 
    184       if (isDynamic(E)) {
    185         Roles |= (unsigned)SymbolRole::Dynamic;
    186         if (auto *RecD = E->getReceiverInterface())
    187           Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD);
    188       }
    189 
    190       return IndexCtx.handleReference(MD, E->getSelectorStartLoc(),
    191                                       Parent, ParentDC, Roles, Relations, E);
    192     }
    193     return true;
    194   }
    195 
    196   bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) {
    197     if (E->isExplicitProperty())
    198       return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(),
    199                                       Parent, ParentDC, SymbolRoleSet(), {}, E);
    200 
    201     // No need to do a handleReference for the objc method, because there will
    202     // be a message expr as part of PseudoObjectExpr.
    203     return true;
    204   }
    205 
    206   bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) {
    207     return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(),
    208                                     Parent, ParentDC, SymbolRoleSet(), {}, E);
    209   }
    210 
    211   bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
    212     return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
    213                                     Parent, ParentDC, SymbolRoleSet(), {}, E);
    214   }
    215 
    216   bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) {
    217     SymbolRoleSet Roles{};
    218     SmallVector<SymbolRelation, 2> Relations;
    219     addCallRole(Roles, Relations);
    220     Roles |= (unsigned)SymbolRole::Implicit;
    221     return IndexCtx.handleReference(MD, E->getLocStart(),
    222                                     Parent, ParentDC, Roles, Relations, E);
    223   }
    224 
    225   bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
    226     if (ObjCMethodDecl *MD = E->getBoxingMethod()) {
    227       return passObjCLiteralMethodCall(MD, E);
    228     }
    229     return true;
    230   }
    231 
    232   bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
    233     if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) {
    234       return passObjCLiteralMethodCall(MD, E);
    235     }
    236     return true;
    237   }
    238 
    239   bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) {
    240     if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) {
    241       return passObjCLiteralMethodCall(MD, E);
    242     }
    243     return true;
    244   }
    245 
    246   bool VisitCXXConstructExpr(CXXConstructExpr *E) {
    247     SymbolRoleSet Roles{};
    248     SmallVector<SymbolRelation, 2> Relations;
    249     addCallRole(Roles, Relations);
    250     return IndexCtx.handleReference(E->getConstructor(), E->getLocation(),
    251                                     Parent, ParentDC, Roles, Relations, E);
    252   }
    253 
    254   bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E,
    255                                    DataRecursionQueue *Q = nullptr) {
    256     if (E->getOperatorLoc().isInvalid())
    257       return true; // implicit.
    258     return base::TraverseCXXOperatorCallExpr(E, Q);
    259   }
    260 
    261   bool VisitDeclStmt(DeclStmt *S) {
    262     if (IndexCtx.shouldIndexFunctionLocalSymbols()) {
    263       IndexCtx.indexDeclGroupRef(S->getDeclGroup());
    264       return true;
    265     }
    266 
    267     DeclGroupRef DG = S->getDeclGroup();
    268     for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) {
    269       const Decl *D = *I;
    270       if (!D)
    271         continue;
    272       if (!IndexCtx.isFunctionLocalDecl(D))
    273         IndexCtx.indexTopLevelDecl(D);
    274     }
    275 
    276     return true;
    277   }
    278 
    279   bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) {
    280     if (C->capturesThis() || C->capturesVLAType())
    281       return true;
    282 
    283     if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols())
    284       return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(),
    285                                       Parent, ParentDC, SymbolRoleSet());
    286 
    287     // FIXME: Lambda init-captures.
    288     return true;
    289   }
    290 
    291   // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating
    292   // the things that we visit. Make sure to only visit the semantic form.
    293   // Also visit things that are in the syntactic form but not the semantic one,
    294   // for example the indices in DesignatedInitExprs.
    295   bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) {
    296 
    297     class SyntacticFormIndexer :
    298               public RecursiveASTVisitor<SyntacticFormIndexer> {
    299       IndexingContext &IndexCtx;
    300       const NamedDecl *Parent;
    301       const DeclContext *ParentDC;
    302 
    303     public:
    304       SyntacticFormIndexer(IndexingContext &indexCtx,
    305                             const NamedDecl *Parent, const DeclContext *DC)
    306         : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { }
    307 
    308       bool shouldWalkTypesOfTypeLocs() const { return false; }
    309 
    310       bool VisitDesignatedInitExpr(DesignatedInitExpr *E) {
    311         for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) {
    312           if (D.isFieldDesignator())
    313             return IndexCtx.handleReference(D.getField(), D.getFieldLoc(),
    314                                             Parent, ParentDC, SymbolRoleSet(),
    315                                             {}, E);
    316         }
    317         return true;
    318       }
    319     };
    320 
    321     auto visitForm = [&](InitListExpr *Form) {
    322       for (Stmt *SubStmt : Form->children()) {
    323         if (!TraverseStmt(SubStmt, Q))
    324           return false;
    325       }
    326       return true;
    327     };
    328 
    329     InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm();
    330     InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S;
    331 
    332     if (SemaForm) {
    333       // Visit things present in syntactic form but not the semantic form.
    334       if (SyntaxForm) {
    335         SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm);
    336       }
    337       return visitForm(SemaForm);
    338     }
    339 
    340     // No semantic, try the syntactic.
    341     if (SyntaxForm) {
    342       return visitForm(SyntaxForm);
    343     }
    344 
    345     return true;
    346   }
    347 };
    348 
    349 } // anonymous namespace
    350 
    351 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent,
    352                                 const DeclContext *DC) {
    353   if (!S)
    354     return;
    355 
    356   if (!DC)
    357     DC = Parent->getLexicalDeclContext();
    358   BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S));
    359 }
    360