IndexDecl.cpp revision 8818d4570b916762513e2b5ec4ca7178b1e736a9
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 14using namespace clang; 15using namespace cxindex; 16 17namespace { 18 19class IndexingDeclVisitor : public DeclVisitor<IndexingDeclVisitor, bool> { 20 IndexingContext &IndexCtx; 21 22public: 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.indexFunctionLocalSymbols()) { 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 bool VisitFunctionDecl(FunctionDecl *D) { 45 IndexCtx.handleFunction(D); 46 handleDeclarator(D); 47 48 if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { 49 // Constructor initializers. 50 for (CXXConstructorDecl::init_iterator I = Ctor->init_begin(), 51 E = Ctor->init_end(); 52 I != E; ++I) { 53 CXXCtorInitializer *Init = *I; 54 if (Init->isWritten()) { 55 IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); 56 if (const FieldDecl *Member = Init->getAnyMember()) 57 IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D); 58 IndexCtx.indexBody(Init->getInit(), D, D); 59 } 60 } 61 } 62 63 if (D->isThisDeclarationADefinition()) { 64 const Stmt *Body = D->getBody(); 65 if (Body) { 66 IndexCtx.indexBody(Body, D, D); 67 } 68 } 69 return true; 70 } 71 72 bool VisitVarDecl(VarDecl *D) { 73 IndexCtx.handleVar(D); 74 handleDeclarator(D); 75 IndexCtx.indexBody(D->getInit(), D); 76 return true; 77 } 78 79 bool VisitFieldDecl(FieldDecl *D) { 80 IndexCtx.handleField(D); 81 handleDeclarator(D); 82 if (D->isBitField()) 83 IndexCtx.indexBody(D->getBitWidth(), D); 84 else if (D->hasInClassInitializer()) 85 IndexCtx.indexBody(D->getInClassInitializer(), D); 86 return true; 87 } 88 89 bool VisitEnumConstantDecl(EnumConstantDecl *D) { 90 IndexCtx.handleEnumerator(D); 91 IndexCtx.indexBody(D->getInitExpr(), D); 92 return true; 93 } 94 95 bool VisitTypedefDecl(TypedefNameDecl *D) { 96 IndexCtx.handleTypedefName(D); 97 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 98 return true; 99 } 100 101 bool VisitTagDecl(TagDecl *D) { 102 // Non-free standing tags are handled in indexTypeSourceInfo. 103 if (D->isFreeStanding()) 104 IndexCtx.indexTagDecl(D); 105 return true; 106 } 107 108 bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { 109 IndexCtx.handleObjCInterface(D); 110 111 if (D->isThisDeclarationADefinition()) { 112 IndexCtx.indexTUDeclsInObjCContainer(); 113 IndexCtx.indexDeclContext(D); 114 } 115 return true; 116 } 117 118 bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) { 119 IndexCtx.handleObjCProtocol(D); 120 121 if (D->isThisDeclarationADefinition()) { 122 IndexCtx.indexTUDeclsInObjCContainer(); 123 IndexCtx.indexDeclContext(D); 124 } 125 return true; 126 } 127 128 bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) { 129 const ObjCInterfaceDecl *Class = D->getClassInterface(); 130 if (!Class) 131 return true; 132 133 if (Class->isImplicitInterfaceDecl()) 134 IndexCtx.handleObjCInterface(Class); 135 136 IndexCtx.handleObjCImplementation(D); 137 138 IndexCtx.indexTUDeclsInObjCContainer(); 139 IndexCtx.indexDeclContext(D); 140 return true; 141 } 142 143 bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) { 144 IndexCtx.handleObjCCategory(D); 145 146 IndexCtx.indexTUDeclsInObjCContainer(); 147 IndexCtx.indexDeclContext(D); 148 return true; 149 } 150 151 bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { 152 const ObjCCategoryDecl *Cat = D->getCategoryDecl(); 153 if (!Cat) 154 return true; 155 156 IndexCtx.handleObjCCategoryImpl(D); 157 158 IndexCtx.indexTUDeclsInObjCContainer(); 159 IndexCtx.indexDeclContext(D); 160 return true; 161 } 162 163 bool VisitObjCMethodDecl(ObjCMethodDecl *D) { 164 IndexCtx.handleObjCMethod(D); 165 IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D); 166 for (ObjCMethodDecl::param_iterator 167 I = D->param_begin(), E = D->param_end(); I != E; ++I) 168 handleDeclarator(*I, D); 169 170 if (D->isThisDeclarationADefinition()) { 171 const Stmt *Body = D->getBody(); 172 if (Body) { 173 IndexCtx.indexBody(Body, D, D); 174 } 175 } 176 return true; 177 } 178 179 bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) { 180 IndexCtx.handleObjCProperty(D); 181 IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); 182 return true; 183 } 184 185 bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { 186 ObjCPropertyDecl *PD = D->getPropertyDecl(); 187 IndexCtx.handleSynthesizedObjCProperty(D); 188 189 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) 190 return true; 191 assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); 192 193 if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { 194 if (!IvarD->getSynthesize()) 195 IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0, 196 D->getDeclContext()); 197 } 198 199 if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { 200 if (MD->isSynthesized()) 201 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); 202 } 203 if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { 204 if (MD->isSynthesized()) 205 IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation()); 206 } 207 return true; 208 } 209 210 bool VisitNamespaceDecl(NamespaceDecl *D) { 211 IndexCtx.handleNamespace(D); 212 IndexCtx.indexDeclContext(D); 213 return true; 214 } 215 216 bool VisitClassTemplateDecl(ClassTemplateDecl *D) { 217 IndexCtx.handleClassTemplate(D); 218 if (D->isThisDeclarationADefinition()) 219 IndexCtx.indexDeclContext(D->getTemplatedDecl()); 220 return true; 221 } 222 223 bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { 224 IndexCtx.handleFunctionTemplate(D); 225 FunctionDecl *FD = D->getTemplatedDecl(); 226 handleDeclarator(FD, D); 227 if (FD->isThisDeclarationADefinition()) { 228 const Stmt *Body = FD->getBody(); 229 if (Body) { 230 IndexCtx.indexBody(Body, D, FD); 231 } 232 } 233 return true; 234 } 235 236 bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { 237 IndexCtx.handleTypeAliasTemplate(D); 238 IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D); 239 return true; 240 } 241}; 242 243} // anonymous namespace 244 245void IndexingContext::indexDecl(const Decl *D) { 246 bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D)); 247 if (!Handled && isa<DeclContext>(D)) 248 indexDeclContext(cast<DeclContext>(D)); 249} 250 251void IndexingContext::indexDeclContext(const DeclContext *DC) { 252 for (DeclContext::decl_iterator 253 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { 254 indexDecl(*I); 255 } 256} 257 258void IndexingContext::indexTopLevelDecl(Decl *D) { 259 if (isNotFromSourceFile(D->getLocation())) 260 return; 261 262 if (isa<ObjCMethodDecl>(D)) 263 return; // Wait for the objc container. 264 265 indexDecl(D); 266} 267 268void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { 269 for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) 270 indexTopLevelDecl(*I); 271} 272 273void IndexingContext::indexTUDeclsInObjCContainer() { 274 for (unsigned i = 0, e = TUDeclsInObjCContainer.size(); i != e; ++i) 275 indexDeclGroupRef(TUDeclsInObjCContainer[i]); 276 TUDeclsInObjCContainer.clear(); 277} 278