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