1 //===- CIndexHigh.cpp - Higher level API functions ------------------------===// 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/DeclVisitor.h" 12 13 using namespace clang; 14 using namespace cxindex; 15 16 namespace { 17 18 class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { 19 IndexingContext &IndexCtx; 20 21 public: 22 explicit IndexingDeclVisitor(IndexingContext &indexCtx) 23 : IndexCtx(indexCtx) { } 24 25 /// \brief Returns true if the given method has been defined explicitly by the 26 /// user. 27 static bool hasUserDefined(const ObjCMethodDecl *D, 28 const ObjCImplDecl *Container) { 29 const ObjCMethodDecl *MD = Container->getMethod(D->getSelector(), 30 D->isInstanceMethod()); 31 return MD && !MD->isImplicit() && MD->isThisDeclarationADefinition(); 32 } 33 34 void handleDeclarator(const DeclaratorDecl *D, 35 const NamedDecl *Parent = nullptr) { 36 if (!Parent) Parent = D; 37 38 if (!IndexCtx.shouldIndexFunctionLocalSymbols()) { 39 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent); 40 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); 41 } else { 42 if (const ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { 43 IndexCtx.handleVar(Parm); 44 } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { 45 for (auto PI : FD->params()) { 46 IndexCtx.handleVar(PI); 47 } 48 } 49 } 50 } 51 52 void handleObjCMethod(const ObjCMethodDecl *D) { 53 IndexCtx.handleObjCMethod(D); 54 if (D->isImplicit()) 55 return; 56 57 IndexCtx.indexTypeSourceInfo(D->getReturnTypeSourceInfo(), D); 58 for (const auto *I : D->params()) 59 handleDeclarator(I, D); 60 61 if (D->isThisDeclarationADefinition()) { 62 const Stmt *Body = D->getBody(); 63 if (Body) { 64 IndexCtx.indexBody(Body, D, D); 65 } 66 } 67 } 68 69 bool VisitFunctionDecl(const FunctionDecl *D) { 70 IndexCtx.handleFunction(D); 71 handleDeclarator(D); 72 73 if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 74 // Constructor initializers. 75 for (const auto *Init : Ctor->inits()) { 76 if (Init->isWritten()) { 77 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 78 if (const FieldDecl *Member = Init->getAnyMember()) 79 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D); 80 IndexCtx.indexBody(Init->getInit(), D, D); 81 } 82 } 83 } 84 85 if (D->isThisDeclarationADefinition()) { 86 const Stmt *Body = D->getBody(); 87 if (Body) { 88 IndexCtx.indexBody(Body, D, D); 89 } 90 } 91 return true; 92 } 93 94 bool VisitVarDecl(const VarDecl *D) { 95 IndexCtx.handleVar(D); 96 handleDeclarator(D); 97 IndexCtx.indexBody(D->getInit(), D); 98 return true; 99 } 100 101 bool VisitFieldDecl(const FieldDecl *D) { 102 IndexCtx.handleField(D); 103 handleDeclarator(D); 104 if (D->isBitField()) 105 IndexCtx.indexBody(D->getBitWidth(), D); 106 else if (D->hasInClassInitializer()) 107 IndexCtx.indexBody(D->getInClassInitializer(), D); 108 return true; 109 } 110 111 bool VisitMSPropertyDecl(const MSPropertyDecl *D) { 112 handleDeclarator(D); 113 return true; 114 } 115 116 bool VisitEnumConstantDecl(const EnumConstantDecl *D) { 117 IndexCtx.handleEnumerator(D); 118 IndexCtx.indexBody(D->getInitExpr(), D); 119 return true; 120 } 121 122 bool VisitTypedefNameDecl(const TypedefNameDecl *D) { 123 IndexCtx.handleTypedefName(D); 124 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 125 return true; 126 } 127 128 bool VisitTagDecl(const TagDecl *D) { 129 // Non-free standing tags are handled in indexTypeSourceInfo. 130 if (D->isFreeStanding()) 131 IndexCtx.indexTagDecl(D); 132 return true; 133 } 134 135 bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { 136 IndexCtx.handleObjCInterface(D); 137 138 if (D->isThisDeclarationADefinition()) { 139 IndexCtx.indexTUDeclsInObjCContainer(); 140 IndexCtx.indexDeclContext(D); 141 } 142 return true; 143 } 144 145 bool VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { 146 IndexCtx.handleObjCProtocol(D); 147 148 if (D->isThisDeclarationADefinition()) { 149 IndexCtx.indexTUDeclsInObjCContainer(); 150 IndexCtx.indexDeclContext(D); 151 } 152 return true; 153 } 154 155 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { 156 const ObjCInterfaceDecl *Class = D->getClassInterface(); 157 if (!Class) 158 return true; 159 160 if (Class->isImplicitInterfaceDecl()) 161 IndexCtx.handleObjCInterface(Class); 162 163 IndexCtx.handleObjCImplementation(D); 164 165 IndexCtx.indexTUDeclsInObjCContainer(); 166 167 // Index the ivars first to make sure the synthesized ivars are indexed 168 // before indexing the methods that can reference them. 169 for (const auto *IvarI : D->ivars()) 170 IndexCtx.indexDecl(IvarI); 171 for (const auto *I : D->decls()) { 172 if (!isa<ObjCIvarDecl>(I)) 173 IndexCtx.indexDecl(I); 174 } 175 176 return true; 177 } 178 179 bool VisitObjCCategoryDecl(const ObjCCategoryDecl *D) { 180 IndexCtx.handleObjCCategory(D); 181 182 IndexCtx.indexTUDeclsInObjCContainer(); 183 IndexCtx.indexDeclContext(D); 184 return true; 185 } 186 187 bool VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { 188 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 189 if (!Cat) 190 return true; 191 192 IndexCtx.handleObjCCategoryImpl(D); 193 194 IndexCtx.indexTUDeclsInObjCContainer(); 195 IndexCtx.indexDeclContext(D); 196 return true; 197 } 198 199 bool VisitObjCMethodDecl(const ObjCMethodDecl *D) { 200 // Methods associated with a property, even user-declared ones, are 201 // handled when we handle the property. 202 if (D->isPropertyAccessor()) 203 return true; 204 205 handleObjCMethod(D); 206 return true; 207 } 208 209 bool VisitObjCPropertyDecl(const ObjCPropertyDecl *D) { 210 if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) 211 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 212 handleObjCMethod(MD); 213 if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) 214 if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) 215 handleObjCMethod(MD); 216 IndexCtx.handleObjCProperty(D); 217 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 218 return true; 219 } 220 221 bool VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { 222 ObjCPropertyDecl *PD = D->getPropertyDecl(); 223 IndexCtx.handleSynthesizedObjCProperty(D); 224 225 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 226 return true; 227 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 228 229 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 230 if (!IvarD->getSynthesize()) 231 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), nullptr, 232 D->getDeclContext()); 233 } 234 235 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 236 if (MD->isPropertyAccessor() && 237 !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext()))) 238 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), 239 D->getLexicalDeclContext()); 240 } 241 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 242 if (MD->isPropertyAccessor() && 243 !hasUserDefined(MD, cast<ObjCImplDecl>(D->getDeclContext()))) 244 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), 245 D->getLexicalDeclContext()); 246 } 247 return true; 248 } 249 250 bool VisitNamespaceDecl(const NamespaceDecl *D) { 251 IndexCtx.handleNamespace(D); 252 IndexCtx.indexDeclContext(D); 253 return true; 254 } 255 256 bool VisitUsingDecl(const UsingDecl *D) { 257 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, 258 // we should do better. 259 260 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 261 for (const auto *I : D->shadows()) 262 IndexCtx.handleReference(I->getUnderlyingDecl(), D->getLocation(), D, 263 D->getLexicalDeclContext()); 264 return true; 265 } 266 267 bool VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) { 268 // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, 269 // we should do better. 270 271 IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); 272 IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), 273 D->getLocation(), D, D->getLexicalDeclContext()); 274 return true; 275 } 276 277 bool VisitClassTemplateDecl(const ClassTemplateDecl *D) { 278 IndexCtx.handleClassTemplate(D); 279 if (D->isThisDeclarationADefinition()) 280 IndexCtx.indexDeclContext(D->getTemplatedDecl()); 281 return true; 282 } 283 284 bool VisitClassTemplateSpecializationDecl(const 285 ClassTemplateSpecializationDecl *D) { 286 // FIXME: Notify subsequent callbacks if info comes from implicit 287 // instantiation. 288 if (D->isThisDeclarationADefinition() && 289 (IndexCtx.shouldIndexImplicitTemplateInsts() || 290 !IndexCtx.isTemplateImplicitInstantiation(D))) 291 IndexCtx.indexTagDecl(D); 292 return true; 293 } 294 295 bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { 296 IndexCtx.handleFunctionTemplate(D); 297 FunctionDecl *FD = D->getTemplatedDecl(); 298 handleDeclarator(FD, D); 299 if (FD->isThisDeclarationADefinition()) { 300 const Stmt *Body = FD->getBody(); 301 if (Body) { 302 IndexCtx.indexBody(Body, D, FD); 303 } 304 } 305 return true; 306 } 307 308 bool VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D) { 309 IndexCtx.handleTypeAliasTemplate(D); 310 IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D); 311 return true; 312 } 313 314 bool VisitImportDecl(const ImportDecl *D) { 315 IndexCtx.importedModule(D); 316 return true; 317 } 318 }; 319 320 } // anonymous namespace 321 322 void IndexingContext::indexDecl(const Decl *D) { 323 if (D->isImplicit() && shouldIgnoreIfImplicit(D)) 324 return; 325 326 bool Handled = IndexingDeclVisitor(*this).Visit(D); 327 if (!Handled && isa<DeclContext>(D)) 328 indexDeclContext(cast<DeclContext>(D)); 329 } 330 331 void IndexingContext::indexDeclContext(const DeclContext *DC) { 332 for (const auto *I : DC->decls()) 333 indexDecl(I); 334 } 335 336 void IndexingContext::indexTopLevelDecl(const Decl *D) { 337 if (isNotFromSourceFile(D->getLocation())) 338 return; 339 340 if (isa<ObjCMethodDecl>(D)) 341 return; // Wait for the objc container. 342 343 indexDecl(D); 344 } 345 346 void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 347 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 348 indexTopLevelDecl(*I); 349 } 350 351 void IndexingContext::indexTUDeclsInObjCContainer() { 352 while (!TUDeclsInObjCContainer.empty()) { 353 DeclGroupRef DG = TUDeclsInObjCContainer.front(); 354 TUDeclsInObjCContainer.pop_front(); 355 indexDeclGroupRef(DG); 356 } 357 } 358