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