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