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 13 using namespace clang; 14 using namespace clang::index; 15 16 namespace { 17 18 class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> { 19 IndexingContext &IndexCtx; 20 const NamedDecl *Parent; 21 const DeclContext *ParentDC; 22 SmallVector<Stmt*, 16> StmtStack; 23 24 typedef RecursiveASTVisitor<BodyIndexer> base; 25 public: 26 BodyIndexer(IndexingContext &indexCtx, 27 const NamedDecl *Parent, const DeclContext *DC) 28 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } 29 30 bool shouldWalkTypesOfTypeLocs() const { return false; } 31 32 bool dataTraverseStmtPre(Stmt *S) { 33 StmtStack.push_back(S); 34 return true; 35 } 36 37 bool dataTraverseStmtPost(Stmt *S) { 38 assert(StmtStack.back() == S); 39 StmtStack.pop_back(); 40 return true; 41 } 42 43 bool TraverseTypeLoc(TypeLoc TL) { 44 IndexCtx.indexTypeLoc(TL, Parent, ParentDC); 45 return true; 46 } 47 48 bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS) { 49 IndexCtx.indexNestedNameSpecifierLoc(NNS, Parent, ParentDC); 50 return true; 51 } 52 53 SymbolRoleSet getRolesForRef(const Expr *E, 54 SmallVectorImpl<SymbolRelation> &Relations) { 55 SymbolRoleSet Roles{}; 56 assert(!StmtStack.empty() && E == StmtStack.back()); 57 if (StmtStack.size() == 1) 58 return Roles; 59 auto It = StmtStack.end()-2; 60 while (isa<CastExpr>(*It) || isa<ParenExpr>(*It)) { 61 if (auto ICE = dyn_cast<ImplicitCastExpr>(*It)) { 62 if (ICE->getCastKind() == CK_LValueToRValue) 63 Roles |= (unsigned)(unsigned)SymbolRole::Read; 64 } 65 if (It == StmtStack.begin()) 66 break; 67 --It; 68 } 69 const Stmt *Parent = *It; 70 71 if (auto BO = dyn_cast<BinaryOperator>(Parent)) { 72 if (BO->getOpcode() == BO_Assign && BO->getLHS()->IgnoreParenCasts() == E) 73 Roles |= (unsigned)SymbolRole::Write; 74 75 } else if (auto UO = dyn_cast<UnaryOperator>(Parent)) { 76 if (UO->isIncrementDecrementOp()) { 77 Roles |= (unsigned)SymbolRole::Read; 78 Roles |= (unsigned)SymbolRole::Write; 79 } else if (UO->getOpcode() == UO_AddrOf) { 80 Roles |= (unsigned)SymbolRole::AddressOf; 81 } 82 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 CE = dyn_cast<CallExpr>(Parent)) { 90 if (CE->getCallee()->IgnoreParenCasts() == E) { 91 addCallRole(Roles, Relations); 92 if (auto *ME = dyn_cast<MemberExpr>(E)) { 93 if (auto *CXXMD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl())) 94 if (CXXMD->isVirtual() && !ME->hasQualifier()) { 95 Roles |= (unsigned)SymbolRole::Dynamic; 96 auto BaseTy = ME->getBase()->IgnoreImpCasts()->getType(); 97 if (!BaseTy.isNull()) 98 if (auto *CXXRD = BaseTy->getPointeeCXXRecordDecl()) 99 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, 100 CXXRD); 101 } 102 } 103 } else if (auto CXXOp = dyn_cast<CXXOperatorCallExpr>(CE)) { 104 if (CXXOp->getNumArgs() > 0 && CXXOp->getArg(0)->IgnoreParenCasts() == E) { 105 OverloadedOperatorKind Op = CXXOp->getOperator(); 106 if (Op == OO_Equal) { 107 Roles |= (unsigned)SymbolRole::Write; 108 } else if ((Op >= OO_PlusEqual && Op <= OO_PipeEqual) || 109 Op == OO_LessLessEqual || Op == OO_GreaterGreaterEqual || 110 Op == OO_PlusPlus || Op == OO_MinusMinus) { 111 Roles |= (unsigned)SymbolRole::Read; 112 Roles |= (unsigned)SymbolRole::Write; 113 } else if (Op == OO_Amp) { 114 Roles |= (unsigned)SymbolRole::AddressOf; 115 } 116 } 117 } 118 } 119 120 return Roles; 121 } 122 123 void addCallRole(SymbolRoleSet &Roles, 124 SmallVectorImpl<SymbolRelation> &Relations) { 125 Roles |= (unsigned)SymbolRole::Call; 126 if (auto *FD = dyn_cast<FunctionDecl>(ParentDC)) 127 Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, FD); 128 else if (auto *MD = dyn_cast<ObjCMethodDecl>(ParentDC)) 129 Relations.emplace_back((unsigned)SymbolRole::RelationCalledBy, MD); 130 } 131 132 bool VisitDeclRefExpr(DeclRefExpr *E) { 133 SmallVector<SymbolRelation, 4> Relations; 134 SymbolRoleSet Roles = getRolesForRef(E, Relations); 135 return IndexCtx.handleReference(E->getDecl(), E->getLocation(), 136 Parent, ParentDC, Roles, Relations, E); 137 } 138 139 bool VisitMemberExpr(MemberExpr *E) { 140 SourceLocation Loc = E->getMemberLoc(); 141 if (Loc.isInvalid()) 142 Loc = E->getLocStart(); 143 SmallVector<SymbolRelation, 4> Relations; 144 SymbolRoleSet Roles = getRolesForRef(E, Relations); 145 return IndexCtx.handleReference(E->getMemberDecl(), Loc, 146 Parent, ParentDC, Roles, Relations, E); 147 } 148 149 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { 150 for (DesignatedInitExpr::reverse_designators_iterator 151 D = E->designators_rbegin(), DEnd = E->designators_rend(); 152 D != DEnd; ++D) { 153 if (D->isFieldDesignator()) 154 return IndexCtx.handleReference(D->getField(), D->getFieldLoc(), 155 Parent, ParentDC, SymbolRoleSet(), 156 {}, E); 157 } 158 return true; 159 } 160 161 bool VisitObjCIvarRefExpr(ObjCIvarRefExpr *E) { 162 SmallVector<SymbolRelation, 4> Relations; 163 SymbolRoleSet Roles = getRolesForRef(E, Relations); 164 return IndexCtx.handleReference(E->getDecl(), E->getLocation(), 165 Parent, ParentDC, Roles, Relations, E); 166 } 167 168 bool VisitObjCMessageExpr(ObjCMessageExpr *E) { 169 auto isDynamic = [](const ObjCMessageExpr *MsgE)->bool { 170 if (MsgE->getReceiverKind() != ObjCMessageExpr::Instance) 171 return false; 172 if (auto *RecE = dyn_cast<ObjCMessageExpr>( 173 MsgE->getInstanceReceiver()->IgnoreParenCasts())) { 174 if (RecE->getMethodFamily() == OMF_alloc) 175 return false; 176 } 177 return true; 178 }; 179 180 if (ObjCMethodDecl *MD = E->getMethodDecl()) { 181 SymbolRoleSet Roles{}; 182 SmallVector<SymbolRelation, 2> Relations; 183 addCallRole(Roles, Relations); 184 if (E->isImplicit()) 185 Roles |= (unsigned)SymbolRole::Implicit; 186 187 if (isDynamic(E)) { 188 Roles |= (unsigned)SymbolRole::Dynamic; 189 if (auto *RecD = E->getReceiverInterface()) 190 Relations.emplace_back((unsigned)SymbolRole::RelationReceivedBy, RecD); 191 } 192 193 return IndexCtx.handleReference(MD, E->getSelectorStartLoc(), 194 Parent, ParentDC, Roles, Relations, E); 195 } 196 return true; 197 } 198 199 bool VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *E) { 200 if (E->isExplicitProperty()) 201 return IndexCtx.handleReference(E->getExplicitProperty(), E->getLocation(), 202 Parent, ParentDC, SymbolRoleSet(), {}, E); 203 204 // No need to do a handleReference for the objc method, because there will 205 // be a message expr as part of PseudoObjectExpr. 206 return true; 207 } 208 209 bool VisitMSPropertyRefExpr(MSPropertyRefExpr *E) { 210 return IndexCtx.handleReference(E->getPropertyDecl(), E->getMemberLoc(), 211 Parent, ParentDC, SymbolRoleSet(), {}, E); 212 } 213 214 bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) { 215 return IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(), 216 Parent, ParentDC, SymbolRoleSet(), {}, E); 217 } 218 219 bool passObjCLiteralMethodCall(const ObjCMethodDecl *MD, const Expr *E) { 220 SymbolRoleSet Roles{}; 221 SmallVector<SymbolRelation, 2> Relations; 222 addCallRole(Roles, Relations); 223 Roles |= (unsigned)SymbolRole::Implicit; 224 return IndexCtx.handleReference(MD, E->getLocStart(), 225 Parent, ParentDC, Roles, Relations, E); 226 } 227 228 bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) { 229 if (ObjCMethodDecl *MD = E->getBoxingMethod()) { 230 return passObjCLiteralMethodCall(MD, E); 231 } 232 return true; 233 } 234 235 bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) { 236 if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod()) { 237 return passObjCLiteralMethodCall(MD, E); 238 } 239 return true; 240 } 241 242 bool VisitObjCArrayLiteral(ObjCArrayLiteral *E) { 243 if (ObjCMethodDecl *MD = E->getArrayWithObjectsMethod()) { 244 return passObjCLiteralMethodCall(MD, E); 245 } 246 return true; 247 } 248 249 bool VisitCXXConstructExpr(CXXConstructExpr *E) { 250 SymbolRoleSet Roles{}; 251 SmallVector<SymbolRelation, 2> Relations; 252 addCallRole(Roles, Relations); 253 return IndexCtx.handleReference(E->getConstructor(), E->getLocation(), 254 Parent, ParentDC, Roles, Relations, E); 255 } 256 257 bool TraverseCXXOperatorCallExpr(CXXOperatorCallExpr *E, 258 DataRecursionQueue *Q = nullptr) { 259 if (E->getOperatorLoc().isInvalid()) 260 return true; // implicit. 261 return base::TraverseCXXOperatorCallExpr(E, Q); 262 } 263 264 bool VisitDeclStmt(DeclStmt *S) { 265 if (IndexCtx.shouldIndexFunctionLocalSymbols()) { 266 IndexCtx.indexDeclGroupRef(S->getDeclGroup()); 267 return true; 268 } 269 270 DeclGroupRef DG = S->getDeclGroup(); 271 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) { 272 const Decl *D = *I; 273 if (!D) 274 continue; 275 if (!IndexCtx.isFunctionLocalDecl(D)) 276 IndexCtx.indexTopLevelDecl(D); 277 } 278 279 return true; 280 } 281 282 bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C) { 283 if (C->capturesThis() || C->capturesVLAType()) 284 return true; 285 286 if (C->capturesVariable() && IndexCtx.shouldIndexFunctionLocalSymbols()) 287 return IndexCtx.handleReference(C->getCapturedVar(), C->getLocation(), 288 Parent, ParentDC, SymbolRoleSet()); 289 290 // FIXME: Lambda init-captures. 291 return true; 292 } 293 294 // RecursiveASTVisitor visits both syntactic and semantic forms, duplicating 295 // the things that we visit. Make sure to only visit the semantic form. 296 // Also visit things that are in the syntactic form but not the semantic one, 297 // for example the indices in DesignatedInitExprs. 298 bool TraverseInitListExpr(InitListExpr *S, DataRecursionQueue *Q = nullptr) { 299 300 class SyntacticFormIndexer : 301 public RecursiveASTVisitor<SyntacticFormIndexer> { 302 IndexingContext &IndexCtx; 303 const NamedDecl *Parent; 304 const DeclContext *ParentDC; 305 306 public: 307 SyntacticFormIndexer(IndexingContext &indexCtx, 308 const NamedDecl *Parent, const DeclContext *DC) 309 : IndexCtx(indexCtx), Parent(Parent), ParentDC(DC) { } 310 311 bool shouldWalkTypesOfTypeLocs() const { return false; } 312 313 bool VisitDesignatedInitExpr(DesignatedInitExpr *E) { 314 for (DesignatedInitExpr::reverse_designators_iterator 315 D = E->designators_rbegin(), DEnd = E->designators_rend(); 316 D != DEnd; ++D) { 317 if (D->isFieldDesignator()) 318 return IndexCtx.handleReference(D->getField(), D->getFieldLoc(), 319 Parent, ParentDC, SymbolRoleSet(), 320 {}, E); 321 } 322 return true; 323 } 324 }; 325 326 auto visitForm = [&](InitListExpr *Form) { 327 for (Stmt *SubStmt : Form->children()) { 328 if (!TraverseStmt(SubStmt, Q)) 329 return false; 330 } 331 return true; 332 }; 333 334 InitListExpr *SemaForm = S->isSemanticForm() ? S : S->getSemanticForm(); 335 InitListExpr *SyntaxForm = S->isSemanticForm() ? S->getSyntacticForm() : S; 336 337 if (SemaForm) { 338 // Visit things present in syntactic form but not the semantic form. 339 if (SyntaxForm) { 340 SyntacticFormIndexer(IndexCtx, Parent, ParentDC).TraverseStmt(SyntaxForm); 341 } 342 return visitForm(SemaForm); 343 } 344 345 // No semantic, try the syntactic. 346 if (SyntaxForm) { 347 return visitForm(SyntaxForm); 348 } 349 350 return true; 351 } 352 }; 353 354 } // anonymous namespace 355 356 void IndexingContext::indexBody(const Stmt *S, const NamedDecl *Parent, 357 const DeclContext *DC) { 358 if (!S) 359 return; 360 361 if (!DC) 362 DC = Parent->getLexicalDeclContext(); 363 BodyIndexer(*this, Parent, DC).TraverseStmt(const_cast<Stmt*>(S)); 364 } 365