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