IndexBody.cpp revision 344779
1//===- IndexBody.cpp - Indexing statements --------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "IndexingContext.h" 11#include "clang/AST/RecursiveASTVisitor.h" 12#include "clang/AST/ASTLambda.h" 13 14using namespace clang; 15using namespace clang::index; 16 17namespace { 18 19class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> { 20 IndexingContext &IndexCtx; 21 const NamedDecl *Parent; 22 const DeclContext *ParentDC; 23 SmallVector<Stmt*, 16> StmtStack; 24 25 typedef RecursiveASTVisitor<BodyIndexer> base; 26 27 Stmt *getParentStmt() const { 28 return StmtStack.size() < 2 ? nullptr : StmtStack.end()[-2]; 29 } 30public: 31 BodyIndexer(IndexingContext &indexCtx, 32 const NamedDecl *Parent, const DeclContext *DC) 33 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } 34 35 bool shouldWalkTypesOfTypeLocs() const { return false; } 36 37 bool dataTraverseStmtPre(Stmt *S) { 38 StmtStack.push_back(S); 39 return true; 40 } 41 42 bool dataTraverseStmtPost(Stmt *S) { 43 assert(StmtStack.back() == S); 44 StmtStack.pop_back(); 45 return true; 46 } 47 48 bool TraverseTypeLoc(TypeLoc TL) { 49 IndexCtx.indexTypeLoc(TL, Parent, ParentDC); 50 return true; 51 } 52 53 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { 54 IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); 55 return true; 56 } 57 58 SymbolRoleSet getRolesForRef(const Expr *E, 59 SmallVectorImpl<SymbolRelation> &Relations) { 60 SymbolRoleSet Roles{}; 61 assert(!StmtStack.empty() && E == StmtStack.back()); 62 if (StmtStack.size() == 1) 63 return Roles; 64 auto It = StmtStack.end()-2; 65 while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) { 66 if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) { 67 if (ICE->getCastKind() == CK_LValueToRValue) 68 Roles |= (unsigned)(unsigned)SymbolRole::Read; 69 } 70 if (It == StmtStack.begin()) 71 break; 72 --It; 73 } 74 const Stmt *Parent = *It; 75 76 if (auto BO = dyn_cast<BinaryOperator>(Parent)) { 77 if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E) 78 Roles |= (unsigned)SymbolRole::Write; 79 80 } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) { 81 if (UO->isIncrementDecrementOp()) { 82 Roles |= (unsigned)SymbolRole::Read; 83 Roles |= (unsigned)SymbolRole::Write; 84 } else if (UO->getOpcode() == UO_AddrOf) { 85 Roles |= (unsigned)SymbolRole::AddressOf; 86 } 87 88 } else if (auto CA = dyn_cast<CompoundAssignOperator>(Parent)) { 89 if (CA->getLHS()->IgnoreParenCasts() == E) { 90 Roles |= (unsigned)SymbolRole::Read; 91 Roles |= (unsigned)SymbolRole::Write; 92 } 93 94 } else if (auto CE = dyn_cast<CallExpr>(Parent)) { 95 if (CE->getCallee()->IgnoreParenCasts() == E) { 96 addCallRole(Roles, Relations); 97 if (auto *ME = dyn_cast<MemberExpr>(E)) { 98 if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl())) 99 if (CXXMD->isVirtual() && !ME->hasQualifier()) { 100 Roles |= (unsigned)SymbolRole::Dynamic; 101 auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType(); 102 if (!BaseTy.isNull()) 103 if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl()) 104 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 105 CXXRD); 106 } 107 } 108 } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) { 109 if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) { 110 OverloadedOperatorKind Op = CXXOp->getOperator(); 111 if (Op == OO_Equal) { 112 Roles |= (unsigned)SymbolRole::Write; 113 } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) || 114 Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual || 115 Op == OO_PlusPlus || Op == OO_MinusMinus) { 116 Roles |= (unsigned)SymbolRole::Read; 117 Roles |= (unsigned)SymbolRole::Write; 118 } else if (Op == OO_Amp) { 119 Roles |= (unsigned)SymbolRole::AddressOf; 120 } 121 } 122 } 123 } 124 125 return Roles; 126 } 127 128 void addCallRole(SymbolRoleSet &Roles, 129 SmallVectorImpl<SymbolRelation> &Relations) { 130 Roles |= (unsigned)SymbolRole::Call; 131 if (auto *FD = dyn_cast<FunctionDecl>(ParentDC)) 132 Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD); 133 else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC)) 134 Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD); 135 } 136 137 bool VisitDeclRefExpr(DeclRefExpr *E) { 138 SmallVector<SymbolRelation, 4> Relations; 139 SymbolRoleSet Roles = getRolesForRef(E, Relations); 140 return IndexCtx.handleReference(E->getDecl(), E->getLocation(), 141 Parent, ParentDC, Roles, Relations, E); 142 } 143 144 bool VisitMemberExpr(MemberExpr *E) { 145 SourceLocation Loc = E->getMemberLoc(); 146 if (Loc.isInvalid()) 147 Loc = E->getBeginLoc(); 148 SmallVector<SymbolRelation, 4> Relations; 149 SymbolRoleSet Roles = getRolesForRef(E, Relations); 150 return IndexCtx.handleReference(E->getMemberDecl(), Loc, 151 Parent, ParentDC, Roles, Relations, E); 152 } 153 154 bool indexDependentReference( 155 const Expr *E, const Type *T, const DeclarationNameInfo &NameInfo, 156 llvm::function_ref<bool(const NamedDecl *ND)> Filter) { 157 if (!T) 158 return true; 159 const TemplateSpecializationType *TST = 160 T->getAs<TemplateSpecializationType>(); 161 if (!TST) 162 return true; 163 TemplateName TN = TST->getTemplateName(); 164 const ClassTemplateDecl *TD = 165 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl()); 166 if (!TD) 167 return true; 168 CXXRecordDecl *RD = TD->getTemplatedDecl(); 169 if (!RD->hasDefinition()) 170 return true; 171 RD = RD->getDefinition(); 172 std::vector<const NamedDecl *> Symbols = 173 RD->lookupDependentName(NameInfo.getName(), Filter); 174 // FIXME: Improve overload handling. 175 if (Symbols.size() != 1) 176 return true; 177 SourceLocation Loc = NameInfo.getLoc(); 178 if (Loc.isInvalid()) 179 Loc = E->getBeginLoc(); 180 SmallVector<SymbolRelation, 4> Relations; 181 SymbolRoleSet Roles = getRolesForRef(E, Relations); 182 return IndexCtx.handleReference(Symbols[0], Loc, Parent, ParentDC, Roles, 183 Relations, E); 184 } 185 186 bool VisitCXXDependentScopeMemberExpr(CXXDependentScopeMemberExpr *E) { 187 const DeclarationNameInfo &Info = E->getMemberNameInfo(); 188 return indexDependentReference( 189 E, E->getBaseType().getTypePtrOrNull(), Info, 190 [](const NamedDecl *D) { return D->isCXXInstanceMember(); }); 191 } 192 193 bool VisitDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E) { 194 const DeclarationNameInfo &Info = E->getNameInfo(); 195 const NestedNameSpecifier *NNS = E->getQualifier(); 196 return indexDependentReference( 197 E, NNS->getAsType(), Info, 198 [](const NamedDecl *D) { return !D->isCXXInstanceMember(); }); 199 } 200 201 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { 202 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 203 if (D.isFieldDesignator() && D.getField()) 204 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), Parent, 205 ParentDC, SymbolRoleSet(), {}, E); 206 } 207 return true; 208 } 209 210 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 211 SmallVector<SymbolRelation, 4> Relations; 212 SymbolRoleSet Roles = getRolesForRef(E, Relations); 213 return IndexCtx.handleReference(E->getDecl(), E->getLocation(), 214 Parent, ParentDC, Roles, Relations, E); 215 } 216 217 bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 218 auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool { 219 if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) 220 return false; 221 if (auto *RecE = dyn_cast<ObjCMessageExpr>( 222 MsgE->getInstanceReceiver()->IgnoreParenCasts())) { 223 if (RecE->getMethodFamily() == OMF_alloc) 224 return false; 225 } 226 return true; 227 }; 228 229 if (ObjCMethodDecl *MD = E->getMethodDecl()) { 230 SymbolRoleSet Roles{}; 231 SmallVector<SymbolRelation, 2> Relations; 232 addCallRole(Roles, Relations); 233 Stmt *Containing = getParentStmt(); 234 235 auto IsImplicitProperty = [](const PseudoObjectExpr *POE) -> bool { 236 const auto *E = POE->getSyntacticForm(); 237 if (const auto *BinOp = dyn_cast<BinaryOperator>(E)) 238 E = BinOp->getLHS(); 239 const auto *PRE = dyn_cast<ObjCPropertyRefExpr>(E); 240 if (!PRE) 241 return false; 242 if (PRE->isExplicitProperty()) 243 return false; 244 if (const ObjCMethodDecl *Getter = PRE->getImplicitPropertyGetter()) { 245 // Class properties that are explicitly defined using @property 246 // declarations are represented implicitly as there is no ivar for 247 // class properties. 248 if (Getter->isClassMethod() && 249 Getter->getCanonicalDecl()->findPropertyDecl()) 250 return false; 251 } 252 return true; 253 }; 254 bool IsPropCall = Containing && isa<PseudoObjectExpr>(Containing); 255 // Implicit property message sends are not 'implicit'. 256 if ((E->isImplicit() || IsPropCall) && 257 !(IsPropCall && 258 IsImplicitProperty(cast<PseudoObjectExpr>(Containing)))) 259 Roles |= (unsigned)SymbolRole::Implicit; 260 261 if (isDynamic(E)) { 262 Roles |= (unsigned)SymbolRole::Dynamic; 263 264 auto addReceivers = [&](const ObjCObjectType *Ty) { 265 if (!Ty) 266 return; 267 if (const auto *clsD = Ty->getInterface()) { 268 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 269 clsD); 270 } 271 for (const auto *protD : Ty->quals()) { 272 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 273 protD); 274 } 275 }; 276 QualType recT = E->getReceiverType(); 277 if (const auto *Ptr = recT->getAs<ObjCObjectPointerType>()) 278 addReceivers(Ptr->getObjectType()); 279 else 280 addReceivers(recT->getAs<ObjCObjectType>()); 281 } 282 283 return IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 284 Parent, ParentDC, Roles, Relations, E); 285 } 286 return true; 287 } 288 289 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { 290 if (E->isClassReceiver()) 291 IndexCtx.handleReference(E->getClassReceiver(), E->getReceiverLocation(), 292 Parent, ParentDC); 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 (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) 396 return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), 397 Parent, ParentDC, SymbolRoleSet()); 398 399 // FIXME: Lambda init-captures. 400 return true; 401 } 402 403 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating 404 // the things that we visit. Make sure to only visit the semantic form. 405 // Also visit things that are in the syntactic form but not the semantic one, 406 // for example the indices in DesignatedInitExprs. 407 bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { 408 auto visitForm = [&](InitListExpr *Form) { 409 for (Stmt *SubStmt : Form->children()) { 410 if (!TraverseStmt(SubStmt, Q)) 411 return false; 412 } 413 return true; 414 }; 415 416 auto visitSyntacticDesignatedInitExpr = [&](DesignatedInitExpr *E) -> bool { 417 for (DesignatedInitExpr::Designator &D : llvm::reverse(E->designators())) { 418 if (D.isFieldDesignator()) 419 return IndexCtx.handleReference(D.getField(), D.getFieldLoc(), 420 Parent, ParentDC, SymbolRoleSet(), 421 {}, E); 422 } 423 return true; 424 }; 425 426 InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); 427 InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; 428 429 if (SemaForm) { 430 // Visit things present in syntactic form but not the semantic form. 431 if (SyntaxForm) { 432 for (Expr *init : SyntaxForm->inits()) { 433 if (auto *DIE = dyn_cast<DesignatedInitExpr>(init)) 434 visitSyntacticDesignatedInitExpr(DIE); 435 } 436 } 437 return visitForm(SemaForm); 438 } 439 440 // No semantic, try the syntactic. 441 if (SyntaxForm) { 442 return visitForm(SyntaxForm); 443 } 444 445 return true; 446 } 447 448 bool VisitOffsetOfExpr(OffsetOfExpr *S) { 449 for (unsigned I = 0, E = S->getNumComponents(); I != E; ++I) { 450 const OffsetOfNode &Component = S->getComponent(I); 451 if (Component.getKind() == OffsetOfNode::Field) 452 IndexCtx.handleReference(Component.getField(), Component.getEndLoc(), 453 Parent, ParentDC, SymbolRoleSet(), {}); 454 // FIXME: Try to resolve dependent field references. 455 } 456 return true; 457 } 458 459 bool VisitParmVarDecl(ParmVarDecl* D) { 460 // Index the parameters of lambda expression. 461 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 462 const auto *DC = D->getDeclContext(); 463 if (DC && isLambdaCallOperator(DC)) 464 IndexCtx.handleDecl(D); 465 } 466 return true; 467 } 468}; 469 470} // anonymous namespace 471 472void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 473 const DeclContext *DC) { 474 if (!S) 475 return; 476 477 if (!DC) 478 DC = Parent->getLexicalDeclContext(); 479 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 480} 481