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 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->getLocStart(); 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 VisitDesignatedInitExpr(DesignatedInitExpr *E) { 154 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 155 if (D.isFieldDesignator() && D.getField()) 156 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent, 157 ParentDC, SymbolRoleSet(), {}, E); 158 } 159 return true; 160 } 161 162 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 163 SmallVector<SymbolRelation, 4> Relations; 164 SymbolRoleSet Roles = getRolesForRef(E, Relations); 165 return IndexCtx.handleReference(E->getDecl(), E->getLocation(), 166 Parent, ParentDC, Roles, Relations, E); 167 } 168 169 bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 170 auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool { 171 if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) 172 return false; 173 if (auto *RecE = dyn_cast<ObjCMessageExpr>( 174 MsgE->getInstanceReceiver()->IgnoreParenCasts())) { 175 if (RecE->getMethodFamily() == OMF_alloc) 176 return false; 177 } 178 return true; 179 }; 180 181 if (ObjCMethodDecl *MD = E->getMethodDecl()) { 182 SymbolRoleSet Roles{}; 183 SmallVector<SymbolRelation, 2> Relations; 184 addCallRole(Roles, Relations); 185 Stmt *Containing = getParentStmt(); 186 if (E->isImplicit() || (Containing && isa<PseudoObjectExpr>(Containing))) 187 Roles |= (unsigned)SymbolRole::Implicit; 188 189 if (isDynamic(E)) { 190 Roles |= (unsigned)SymbolRole::Dynamic; 191 if (auto *RecD = E->getReceiverInterface()) 192 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD); 193 } 194 195 return IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 196 Parent, ParentDC, Roles, Relations, E); 197 } 198 return true; 199 } 200 201 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { 202 if (E->isExplicitProperty()) { 203 SmallVector<SymbolRelation, 2> Relations; 204 SymbolRoleSet Roles = getRolesForRef(E, Relations); 205 return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 206 Parent, ParentDC, Roles, Relations, E); 207 } 208 209 // No need to do a handleReference for the objc method, because there will 210 // be a message expr as part of PseudoObjectExpr. 211 return true; 212 } 213 214 bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { 215 return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), 216 Parent, ParentDC, SymbolRoleSet(), {}, E); 217 } 218 219 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { 220 return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), 221 Parent, ParentDC, SymbolRoleSet(), {}, E); 222 } 223 224 bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) { 225 SymbolRoleSet Roles{}; 226 SmallVector<SymbolRelation, 2> Relations; 227 addCallRole(Roles, Relations); 228 Roles |= (unsigned)SymbolRole::Implicit; 229 return IndexCtx.handleReference(MD, E->getLocStart(), 230 Parent, ParentDC, Roles, Relations, E); 231 } 232 233 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { 234 if (ObjCMethodDecl *MD = E->getBoxingMethod()) { 235 return passObjCLiteralMethodCall(MD, E); 236 } 237 return true; 238 } 239 240 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { 241 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { 242 return passObjCLiteralMethodCall(MD, E); 243 } 244 return true; 245 } 246 247 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { 248 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { 249 return passObjCLiteralMethodCall(MD, E); 250 } 251 return true; 252 } 253 254 bool VisitCXXConstructExpr(CXXConstructExpr *E) { 255 SymbolRoleSet Roles{}; 256 SmallVector<SymbolRelation, 2> Relations; 257 addCallRole(Roles, Relations); 258 return IndexCtx.handleReference(E->getConstructor(), E->getLocation(), 259 Parent, ParentDC, Roles, Relations, E); 260 } 261 262 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, 263 DataRecursionQueue *Q = nullptr) { 264 if (E->getOperatorLoc().isInvalid()) 265 return true; // implicit. 266 return base::TraverseCXXOperatorCallExpr(E, Q); 267 } 268 269 bool VisitDeclStmt(DeclStmt *S) { 270 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 271 IndexCtx.indexDeclGroupRef(S->getDeclGroup()); 272 return true; 273 } 274 275 DeclGroupRef DG = S->getDeclGroup(); 276 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 277 const Decl *D = *I; 278 if (!D) 279 continue; 280 if (!isFunctionLocalSymbol(D)) 281 IndexCtx.indexTopLevelDecl(D); 282 } 283 284 return true; 285 } 286 287 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, 288 Expr *Init) { 289 if (C->capturesThis() || C->capturesVLAType()) 290 return true; 291 292 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) 293 return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), 294 Parent, ParentDC, SymbolRoleSet()); 295 296 // FIXME: Lambda init-captures. 297 return true; 298 } 299 300 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating 301 // the things that we visit. Make sure to only visit the semantic form. 302 // Also visit things that are in the syntactic form but not the semantic one, 303 // for example the indices in DesignatedInitExprs. 304 bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { 305 auto visitForm = [&](InitListExpr *Form) { 306 for (Stmt *SubStmt : Form->children()) { 307 if (!TraverseStmt(SubStmt, Q)) 308 return false; 309 } 310 return true; 311 }; 312 313 auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool { 314 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 315 if (D.isFieldDesignator()) 316 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), 317 Parent, ParentDC, SymbolRoleSet(), 318 {}, E); 319 } 320 return true; 321 }; 322 323 InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); 324 InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; 325 326 if (SemaForm) { 327 // Visit things present in syntactic form but not the semantic form. 328 if (SyntaxForm) { 329 for (Expr *init : SyntaxForm->inits()) { 330 if (auto *DIE = dyn_cast<DesignatedInitExpr>(init)) 331 visitSyntacticDesignatedInitExpr(DIE); 332 } 333 } 334 return visitForm(SemaForm); 335 } 336 337 // No semantic, try the syntactic. 338 if (SyntaxForm) { 339 return visitForm(SyntaxForm); 340 } 341 342 return true; 343 } 344 }; 345 346 } // anonymous namespace 347 348 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 349 const DeclContext *DC) { 350 if (!S) 351 return; 352 353 if (!DC) 354 DC = Parent->getLexicalDeclContext(); 355 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 356 } 357