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 && BO->getLHS()->IgnoreParenCasts() == E) 81 Roles |= (unsigned)SymbolRole::Write; 82 83 } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) { 84 if (UO->isIncrementDecrementOp()) { 85 Roles |= (unsigned)SymbolRole::Read; 86 Roles |= (unsigned)SymbolRole::Write; 87 } else if (UO->getOpcode() == UO_AddrOf) { 88 Roles |= (unsigned)SymbolRole::AddressOf; 89 } 90 91 } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) { 92 if (CA->getLHS()->IgnoreParenCasts() == E) { 93 Roles |= (unsigned)SymbolRole::Read; 94 Roles |= (unsigned)SymbolRole::Write; 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 VisitMemberExpr(MemberExpr *E) { 148 SourceLocation Loc = E->getMemberLoc(); 149 if (Loc.isInvalid()) 150 Loc = E->getBeginLoc(); 151 SmallVector<SymbolRelation, 4> Relations; 152 SymbolRoleSet Roles = getRolesForRef(E, Relations); 153 return IndexCtx.handleReference(E->getMemberDecl(), Loc, 154 Parent, ParentDC, Roles, Relations, E); 155 } 156 157 bool indexDependentReference( 158 const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo, 159 llvm::function_ref<bool(const NamedDecl *ND)> Filter) { 160 if (!T) 161 return true; 162 const TemplateSpecializationType *TST = 163 T->getAs<TemplateSpecializationType>(); 164 if (!TST) 165 return true; 166 TemplateName TN = TST->getTemplateName(); 167 const ClassTemplateDecl *TD = 168 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); 169 if (!TD) 170 return true; 171 CXXRecordDecl *RD = TD->getTemplatedDecl(); 172 if (!RD->hasDefinition()) 173 return true; 174 RD = RD->getDefinition(); 175 std::vector<const NamedDecl *> Symbols = 176 RD->lookupDependentName(NameInfo.getName(), Filter); 177 // FIXME: Improve overload handling. 178 if (Symbols.size() != 1) 179 return true; 180 SourceLocation Loc = NameInfo.getLoc(); 181 if (Loc.isInvalid()) 182 Loc = E->getBeginLoc(); 183 SmallVector<SymbolRelation, 4> Relations; 184 SymbolRoleSet Roles = getRolesForRef(E, Relations); 185 return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles, 186 Relations, E); 187 } 188 189 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { 190 const DeclarationNameInfo &Info = E->getMemberNameInfo(); 191 return indexDependentReference( 192 E, E->getBaseType().getTypePtrOrNull(), Info, 193 [](const NamedDecl *D) { return D->isCXXInstanceMember(); }); 194 } 195 196 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { 197 const DeclarationNameInfo &Info = E->getNameInfo(); 198 const NestedNameSpecifier *NNS = E->getQualifier(); 199 return indexDependentReference( 200 E, NNS->getAsType(), Info, 201 [](const NamedDecl *D) { return !D->isCXXInstanceMember(); }); 202 } 203 204 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { 205 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 206 if (D.isFieldDesignator()) { 207 if (const FieldDecl *FD = D.getFieldDecl()) { 208 return IndexCtx.handleReference(FD, D.getFieldLoc(), Parent, 209 ParentDC, SymbolRoleSet(), {}, E); 210 } 211 } 212 } 213 return true; 214 } 215 216 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 217 SmallVector<SymbolRelation, 4> Relations; 218 SymbolRoleSet Roles = getRolesForRef(E, Relations); 219 return IndexCtx.handleReference(E->getDecl(), E->getLocation(), 220 Parent, ParentDC, Roles, Relations, E); 221 } 222 223 bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 224 auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool { 225 if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) 226 return false; 227 if (auto *RecE = dyn_cast<ObjCMessageExpr>( 228 MsgE->getInstanceReceiver()->IgnoreParenCasts())) { 229 if (RecE->getMethodFamily() == OMF_alloc) 230 return false; 231 } 232 return true; 233 }; 234 235 if (ObjCMethodDecl *MD = E->getMethodDecl()) { 236 SymbolRoleSet Roles{}; 237 SmallVector<SymbolRelation, 2> Relations; 238 addCallRole(Roles, Relations); 239 Stmt *Containing = getParentStmt(); 240 241 auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool { 242 const auto *E = POE->getSyntacticForm(); 243 if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) 244 E = BinOp->getLHS(); 245 const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E); 246 if (!PRE) 247 return false; 248 if (PRE->isExplicitProperty()) 249 return false; 250 if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) { 251 // Class properties that are explicitly defined using @property 252 // declarations are represented implicitly as there is no ivar for 253 // class properties. 254 if (Getter->isClassMethod() && 255 Getter->getCanonicalDecl()->findPropertyDecl()) 256 return false; 257 } 258 return true; 259 }; 260 bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing); 261 // Implicit property message sends are not 'implicit'. 262 if ((E->isImplicit() || IsPropCall) && 263 !(IsPropCall && 264 IsImplicitProperty(cast<PseudoObjectExpr>(Containing)))) 265 Roles |= (unsigned)SymbolRole::Implicit; 266 267 if (isDynamic(E)) { 268 Roles |= (unsigned)SymbolRole::Dynamic; 269 270 auto addReceivers = [&](const ObjCObjectType *Ty) { 271 if (!Ty) 272 return; 273 if (const auto *clsD = Ty->getInterface()) { 274 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 275 clsD); 276 } 277 for (const auto *protD : Ty->quals()) { 278 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 279 protD); 280 } 281 }; 282 QualType recT = E->getReceiverType(); 283 if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>()) 284 addReceivers(Ptr->getObjectType()); 285 else 286 addReceivers(recT->getAs<ObjCObjectType>()); 287 } 288 289 return IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 290 Parent, ParentDC, Roles, Relations, E); 291 } 292 return true; 293 } 294 295 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { 296 if (E->isExplicitProperty()) { 297 SmallVector<SymbolRelation, 2> Relations; 298 SymbolRoleSet Roles = getRolesForRef(E, Relations); 299 return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 300 Parent, ParentDC, Roles, Relations, E); 301 } else if (const ObjCMethodDecl *Getter = E->getImplicitPropertyGetter()) { 302 // Class properties that are explicitly defined using @property 303 // declarations are represented implicitly as there is no ivar for class 304 // properties. 305 if (Getter->isClassMethod()) { 306 if (const auto *PD = Getter->getCanonicalDecl()->findPropertyDecl()) { 307 SmallVector<SymbolRelation, 2> Relations; 308 SymbolRoleSet Roles = getRolesForRef(E, Relations); 309 return IndexCtx.handleReference(PD, E->getLocation(), Parent, 310 ParentDC, Roles, Relations, E); 311 } 312 } 313 } 314 315 // No need to do a handleReference for the objc method, because there will 316 // be a message expr as part of PseudoObjectExpr. 317 return true; 318 } 319 320 bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { 321 return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), 322 Parent, ParentDC, SymbolRoleSet(), {}, E); 323 } 324 325 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { 326 return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), 327 Parent, ParentDC, SymbolRoleSet(), {}, E); 328 } 329 330 bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) { 331 SymbolRoleSet Roles{}; 332 SmallVector<SymbolRelation, 2> Relations; 333 addCallRole(Roles, Relations); 334 Roles |= (unsigned)SymbolRole::Implicit; 335 return IndexCtx.handleReference(MD, E->getBeginLoc(), Parent, ParentDC, 336 Roles, Relations, E); 337 } 338 339 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { 340 if (ObjCMethodDecl *MD = E->getBoxingMethod()) { 341 return passObjCLiteralMethodCall(MD, E); 342 } 343 return true; 344 } 345 346 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { 347 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { 348 return passObjCLiteralMethodCall(MD, E); 349 } 350 return true; 351 } 352 353 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { 354 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { 355 return passObjCLiteralMethodCall(MD, E); 356 } 357 return true; 358 } 359 360 bool VisitCXXConstructExpr(CXXConstructExpr *E) { 361 SymbolRoleSet Roles{}; 362 SmallVector<SymbolRelation, 2> Relations; 363 addCallRole(Roles, Relations); 364 return IndexCtx.handleReference(E->getConstructor(), E->getLocation(), 365 Parent, ParentDC, Roles, Relations, E); 366 } 367 368 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, 369 DataRecursionQueue *Q = nullptr) { 370 if (E->getOperatorLoc().isInvalid()) 371 return true; // implicit. 372 return base::TraverseCXXOperatorCallExpr(E, Q); 373 } 374 375 bool VisitDeclStmt(DeclStmt *S) { 376 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 377 IndexCtx.indexDeclGroupRef(S->getDeclGroup()); 378 return true; 379 } 380 381 DeclGroupRef DG = S->getDeclGroup(); 382 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 383 const Decl *D = *I; 384 if (!D) 385 continue; 386 if (!isFunctionLocalSymbol(D)) 387 IndexCtx.indexTopLevelDecl(D); 388 } 389 390 return true; 391 } 392 393 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, 394 Expr *Init) { 395 if (C->capturesThis() || C->capturesVLAType()) 396 return true; 397 398 if (!base::TraverseStmt(Init)) 399 return false; 400 401 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) 402 return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), 403 Parent, ParentDC, SymbolRoleSet()); 404 405 return true; 406 } 407 408 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating 409 // the things that we visit. Make sure to only visit the semantic form. 410 // Also visit things that are in the syntactic form but not the semantic one, 411 // for example the indices in DesignatedInitExprs. 412 bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { 413 auto visitForm = [&](InitListExpr *Form) { 414 for (Stmt *SubStmt : Form->children()) { 415 if (!TraverseStmt(SubStmt, Q)) 416 return false; 417 } 418 return true; 419 }; 420 421 auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool { 422 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 423 if (D.isFieldDesignator()) { 424 if (const FieldDecl *FD = D.getFieldDecl()) { 425 return IndexCtx.handleReference(FD, D.getFieldLoc(), Parent, 426 ParentDC, SymbolRoleSet(), 427 /*Relations=*/{}, E); 428 } 429 } 430 } 431 return true; 432 }; 433 434 InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); 435 InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; 436 437 if (SemaForm) { 438 // Visit things present in syntactic form but not the semantic form. 439 if (SyntaxForm) { 440 for (Expr *init : SyntaxForm->inits()) { 441 if (auto *DIE = dyn_cast<DesignatedInitExpr>(init)) 442 visitSyntacticDesignatedInitExpr(DIE); 443 } 444 } 445 return visitForm(SemaForm); 446 } 447 448 // No semantic, try the syntactic. 449 if (SyntaxForm) { 450 return visitForm(SyntaxForm); 451 } 452 453 return true; 454 } 455 456 bool VisitOffsetOfExpr(OffsetOfExpr *S) { 457 for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { 458 const OffsetOfNode &Component = S->getComponent(I); 459 if (Component.getKind() == OffsetOfNode::Field) 460 IndexCtx.handleReference(Component.getField(), Component.getEndLoc(), 461 Parent, ParentDC, SymbolRoleSet(), {}); 462 // FIXME: Try to resolve dependent field references. 463 } 464 return true; 465 } 466 467 bool VisitParmVarDecl(ParmVarDecl* D) { 468 // Index the parameters of lambda expression and requires expression. 469 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 470 const auto *DC = D->getDeclContext(); 471 if (DC && (isLambdaCallOperator(DC) || isa<RequiresExprBodyDecl>(DC))) 472 IndexCtx.handleDecl(D); 473 } 474 return true; 475 } 476 477 bool VisitOverloadExpr(OverloadExpr *E) { 478 SmallVector<SymbolRelation, 4> Relations; 479 SymbolRoleSet Roles = getRolesForRef(E, Relations); 480 for (auto *D : E->decls()) 481 IndexCtx.handleReference(D, E->getNameLoc(), Parent, ParentDC, Roles, 482 Relations, E); 483 return true; 484 } 485 486 bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) { 487 IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(), 488 Parent, ParentDC); 489 return true; 490 } 491 492 bool TraverseTypeConstraint(const TypeConstraint *C) { 493 IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(), 494 Parent, ParentDC); 495 return RecursiveASTVisitor::TraverseTypeConstraint(C); 496 } 497 }; 498 499 } // anonymous namespace 500 501 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 502 const DeclContext *DC) { 503 if (!S) 504 return; 505 506 if (!DC) 507 DC = Parent->getLexicalDeclContext(); 508 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 509 } 510