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->isExplicitProperty()) { 290 SmallVector<SymbolRelation, 2> Relations; 291 SymbolRoleSet Roles = getRolesForRef(E, Relations); 292 return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 293 Parent, ParentDC, Roles, Relations, E); 294 } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) { 295 // Class properties that are explicitly defined using @property 296 // declarations are represented implicitly as there is no ivar for class 297 // properties. 298 if (Getter->isClassMethod()) { 299 if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) { 300 SmallVector<SymbolRelation, 2> Relations; 301 SymbolRoleSet Roles = getRolesForRef(E, Relations); 302 return IndexCtx.handleReference(PD, E->getLocation(), Parent, 303 ParentDC, Roles, Relations, E); 304 } 305 } 306 } 307 308 // No need to do a handleReference for the objc method, because there will 309 // be a message expr as part of PseudoObjectExpr. 310 return true; 311 } 312 313 bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { 314 return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), 315 Parent, ParentDC, SymbolRoleSet(), {}, E); 316 } 317 318 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { 319 return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), 320 Parent, ParentDC, SymbolRoleSet(), {}, E); 321 } 322 323 bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) { 324 SymbolRoleSet Roles{}; 325 SmallVector<SymbolRelation, 2> Relations; 326 addCallRole(Roles, Relations); 327 Roles |= (unsigned)SymbolRole::Implicit; 328 return IndexCtx.handleReference(MD, E->getBeginLoc(), Parent, ParentDC, 329 Roles, Relations, E); 330 } 331 332 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { 333 if (ObjCMethodDecl *MD = E->getBoxingMethod()) { 334 return passObjCLiteralMethodCall(MD, E); 335 } 336 return true; 337 } 338 339 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { 340 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { 341 return passObjCLiteralMethodCall(MD, E); 342 } 343 return true; 344 } 345 346 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { 347 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { 348 return passObjCLiteralMethodCall(MD, E); 349 } 350 return true; 351 } 352 353 bool VisitCXXConstructExpr(CXXConstructExpr *E) { 354 SymbolRoleSet Roles{}; 355 SmallVector<SymbolRelation, 2> Relations; 356 addCallRole(Roles, Relations); 357 return IndexCtx.handleReference(E->getConstructor(), E->getLocation(), 358 Parent, ParentDC, Roles, Relations, E); 359 } 360 361 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, 362 DataRecursionQueue *Q = nullptr) { 363 if (E->getOperatorLoc().isInvalid()) 364 return true; // implicit. 365 return base::TraverseCXXOperatorCallExpr(E, Q); 366 } 367 368 bool VisitDeclStmt(DeclStmt *S) { 369 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 370 IndexCtx.indexDeclGroupRef(S->getDeclGroup()); 371 return true; 372 } 373 374 DeclGroupRef DG = S->getDeclGroup(); 375 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 376 const Decl *D = *I; 377 if (!D) 378 continue; 379 if (!isFunctionLocalSymbol(D)) 380 IndexCtx.indexTopLevelDecl(D); 381 } 382 383 return true; 384 } 385 386 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, 387 Expr *Init) { 388 if (C->capturesThis() || C->capturesVLAType()) 389 return true; 390 391 if (!base::TraverseStmt(Init)) 392 return false; 393 394 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) 395 return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), 396 Parent, ParentDC, SymbolRoleSet()); 397 398 return true; 399 } 400 401 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating 402 // the things that we visit. Make sure to only visit the semantic form. 403 // Also visit things that are in the syntactic form but not the semantic one, 404 // for example the indices in DesignatedInitExprs. 405 bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { 406 auto visitForm = [&](InitListExpr *Form) { 407 for (Stmt *SubStmt : Form->children()) { 408 if (!TraverseStmt(SubStmt, Q)) 409 return false; 410 } 411 return true; 412 }; 413 414 auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool { 415 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 416 if (D.isFieldDesignator() && D.getField()) 417 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), 418 Parent, ParentDC, SymbolRoleSet(), 419 {}, E); 420 } 421 return true; 422 }; 423 424 InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); 425 InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; 426 427 if (SemaForm) { 428 // Visit things present in syntactic form but not the semantic form. 429 if (SyntaxForm) { 430 for (Expr *init : SyntaxForm->inits()) { 431 if (auto *DIE = dyn_cast<DesignatedInitExpr>(init)) 432 visitSyntacticDesignatedInitExpr(DIE); 433 } 434 } 435 return visitForm(SemaForm); 436 } 437 438 // No semantic, try the syntactic. 439 if (SyntaxForm) { 440 return visitForm(SyntaxForm); 441 } 442 443 return true; 444 } 445 446 bool VisitOffsetOfExpr(OffsetOfExpr *S) { 447 for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { 448 const OffsetOfNode &Component = S->getComponent(I); 449 if (Component.getKind() == OffsetOfNode::Field) 450 IndexCtx.handleReference(Component.getField(), Component.getEndLoc(), 451 Parent, ParentDC, SymbolRoleSet(), {}); 452 // FIXME: Try to resolve dependent field references. 453 } 454 return true; 455 } 456 457 bool VisitParmVarDecl(ParmVarDecl* D) { 458 // Index the parameters of lambda expression. 459 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 460 const auto *DC = D->getDeclContext(); 461 if (DC && isLambdaCallOperator(DC)) 462 IndexCtx.handleDecl(D); 463 } 464 return true; 465 } 466 467 bool VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { 468 SmallVector<SymbolRelation, 4> Relations; 469 SymbolRoleSet Roles = getRolesForRef(E, Relations); 470 for (auto *D : E->decls()) 471 IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles, 472 Relations, E); 473 return true; 474 } 475 }; 476 477 } // anonymous namespace 478 479 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 480 const DeclContext *DC) { 481 if (!S) 482 return; 483 484 if (!DC) 485 DC = Parent->getLexicalDeclContext(); 486 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 487 } 488