diff options
author | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
---|---|---|
committer | Zancanaro; Carlo <czan8762@plang3.cs.usyd.edu.au> | 2012-09-24 09:58:17 +1000 |
commit | 222e2a7620e6520ffaf4fc4e69d79c18da31542e (patch) | |
tree | 7bfbc05bfa3b41c8f9d2e56d53a0bc3e310df239 /clang/tools/libclang/IndexDecl.cpp | |
parent | 3d206f03985b50beacae843d880bccdc91a9f424 (diff) |
Add the clang library to the repo (with some of my changes, too).
Diffstat (limited to 'clang/tools/libclang/IndexDecl.cpp')
-rw-r--r-- | clang/tools/libclang/IndexDecl.cpp | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/clang/tools/libclang/IndexDecl.cpp b/clang/tools/libclang/IndexDecl.cpp new file mode 100644 index 0000000..c257c34 --- /dev/null +++ b/clang/tools/libclang/IndexDecl.cpp @@ -0,0 +1,336 @@ +//===- CIndexHigh.cpp - Higher level API functions ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "IndexingContext.h" + +#include "clang/AST/DeclVisitor.h" + +using namespace clang; +using namespace cxindex; + +namespace { + +class IndexingDeclVisitor : public DeclVisitor<IndexingDeclVisitor, bool> { + IndexingContext &IndexCtx; + +public: + explicit IndexingDeclVisitor(IndexingContext &indexCtx) + : IndexCtx(indexCtx) { } + + void handleDeclarator(DeclaratorDecl *D, const NamedDecl *Parent = 0) { + if (!Parent) Parent = D; + + if (!IndexCtx.shouldIndexFunctionLocalSymbols()) { + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), Parent); + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), Parent); + } else { + if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { + IndexCtx.handleVar(Parm); + } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + for (FunctionDecl::param_iterator + PI = FD->param_begin(), PE = FD->param_end(); PI != PE; ++PI) { + IndexCtx.handleVar(*PI); + } + } + } + } + + void handleObjCMethod(ObjCMethodDecl *D) { + IndexCtx.handleObjCMethod(D); + if (D->isImplicit()) + return; + + IndexCtx.indexTypeSourceInfo(D->getResultTypeSourceInfo(), D); + for (ObjCMethodDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) + handleDeclarator(*I, D); + + if (D->isThisDeclarationADefinition()) { + const Stmt *Body = D->getBody(); + if (Body) { + IndexCtx.indexBody(Body, D, D); + } + } + } + + bool VisitFunctionDecl(FunctionDecl *D) { + IndexCtx.handleFunction(D); + handleDeclarator(D); + + if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { + // Constructor initializers. + for (CXXConstructorDecl::init_iterator I = Ctor->init_begin(), + E = Ctor->init_end(); + I != E; ++I) { + CXXCtorInitializer *Init = *I; + if (Init->isWritten()) { + IndexCtx.indexTypeSourceInfo(Init->getTypeSourceInfo(), D); + if (const FieldDecl *Member = Init->getAnyMember()) + IndexCtx.handleReference(Member, Init->getMemberLocation(), D, D); + IndexCtx.indexBody(Init->getInit(), D, D); + } + } + } + + if (D->isThisDeclarationADefinition()) { + const Stmt *Body = D->getBody(); + if (Body) { + IndexCtx.indexBody(Body, D, D); + } + } + return true; + } + + bool VisitVarDecl(VarDecl *D) { + IndexCtx.handleVar(D); + handleDeclarator(D); + IndexCtx.indexBody(D->getInit(), D); + return true; + } + + bool VisitFieldDecl(FieldDecl *D) { + IndexCtx.handleField(D); + handleDeclarator(D); + if (D->isBitField()) + IndexCtx.indexBody(D->getBitWidth(), D); + else if (D->hasInClassInitializer()) + IndexCtx.indexBody(D->getInClassInitializer(), D); + return true; + } + + bool VisitEnumConstantDecl(EnumConstantDecl *D) { + IndexCtx.handleEnumerator(D); + IndexCtx.indexBody(D->getInitExpr(), D); + return true; + } + + bool VisitTypedefDecl(TypedefNameDecl *D) { + IndexCtx.handleTypedefName(D); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + return true; + } + + bool VisitTagDecl(TagDecl *D) { + // Non-free standing tags are handled in indexTypeSourceInfo. + if (D->isFreeStanding()) + IndexCtx.indexTagDecl(D); + return true; + } + + bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { + IndexCtx.handleObjCInterface(D); + + if (D->isThisDeclarationADefinition()) { + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.indexDeclContext(D); + } + return true; + } + + bool VisitObjCProtocolDecl(ObjCProtocolDecl *D) { + IndexCtx.handleObjCProtocol(D); + + if (D->isThisDeclarationADefinition()) { + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.indexDeclContext(D); + } + return true; + } + + bool VisitObjCImplementationDecl(ObjCImplementationDecl *D) { + const ObjCInterfaceDecl *Class = D->getClassInterface(); + if (!Class) + return true; + + if (Class->isImplicitInterfaceDecl()) + IndexCtx.handleObjCInterface(Class); + + IndexCtx.handleObjCImplementation(D); + + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.indexDeclContext(D); + return true; + } + + bool VisitObjCCategoryDecl(ObjCCategoryDecl *D) { + IndexCtx.handleObjCCategory(D); + + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.indexDeclContext(D); + return true; + } + + bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { + const ObjCCategoryDecl *Cat = D->getCategoryDecl(); + if (!Cat) + return true; + + IndexCtx.handleObjCCategoryImpl(D); + + IndexCtx.indexTUDeclsInObjCContainer(); + IndexCtx.indexDeclContext(D); + return true; + } + + bool VisitObjCMethodDecl(ObjCMethodDecl *D) { + // Methods associated with a property, even user-declared ones, are + // handled when we handle the property. + if (D->isSynthesized()) + return true; + + handleObjCMethod(D); + return true; + } + + bool VisitObjCPropertyDecl(ObjCPropertyDecl *D) { + if (ObjCMethodDecl *MD = D->getGetterMethodDecl()) + if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) + handleObjCMethod(MD); + if (ObjCMethodDecl *MD = D->getSetterMethodDecl()) + if (MD->getLexicalDeclContext() == D->getLexicalDeclContext()) + handleObjCMethod(MD); + IndexCtx.handleObjCProperty(D); + IndexCtx.indexTypeSourceInfo(D->getTypeSourceInfo(), D); + return true; + } + + bool VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { + ObjCPropertyDecl *PD = D->getPropertyDecl(); + IndexCtx.handleSynthesizedObjCProperty(D); + + if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + return true; + assert(D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize); + + if (ObjCIvarDecl *IvarD = D->getPropertyIvarDecl()) { + if (!IvarD->getSynthesize()) + IndexCtx.handleReference(IvarD, D->getPropertyIvarDeclLoc(), 0, + D->getDeclContext()); + } + + if (ObjCMethodDecl *MD = PD->getGetterMethodDecl()) { + if (MD->isSynthesized()) + IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), + D->getLexicalDeclContext()); + } + if (ObjCMethodDecl *MD = PD->getSetterMethodDecl()) { + if (MD->isSynthesized()) + IndexCtx.handleSynthesizedObjCMethod(MD, D->getLocation(), + D->getLexicalDeclContext()); + } + return true; + } + + bool VisitNamespaceDecl(NamespaceDecl *D) { + IndexCtx.handleNamespace(D); + IndexCtx.indexDeclContext(D); + return true; + } + + bool VisitUsingDecl(UsingDecl *D) { + // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, + // we should do better. + + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); + for (UsingDecl::shadow_iterator + I = D->shadow_begin(), E = D->shadow_end(); I != E; ++I) { + IndexCtx.handleReference((*I)->getUnderlyingDecl(), D->getLocation(), + D, D->getLexicalDeclContext()); + } + return true; + } + + bool VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { + // FIXME: Parent for the following is CXIdxEntity_Unexposed with no USR, + // we should do better. + + IndexCtx.indexNestedNameSpecifierLoc(D->getQualifierLoc(), D); + IndexCtx.handleReference(D->getNominatedNamespaceAsWritten(), + D->getLocation(), D, D->getLexicalDeclContext()); + return true; + } + + bool VisitClassTemplateDecl(ClassTemplateDecl *D) { + IndexCtx.handleClassTemplate(D); + if (D->isThisDeclarationADefinition()) + IndexCtx.indexDeclContext(D->getTemplatedDecl()); + return true; + } + + bool VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + // FIXME: Notify subsequent callbacks if info comes from implicit + // instantiation. + if (D->isThisDeclarationADefinition() && + (IndexCtx.shouldIndexImplicitTemplateInsts() || + !IndexCtx.isTemplateImplicitInstantiation(D))) + IndexCtx.indexTagDecl(D); + return true; + } + + bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + IndexCtx.handleFunctionTemplate(D); + FunctionDecl *FD = D->getTemplatedDecl(); + handleDeclarator(FD, D); + if (FD->isThisDeclarationADefinition()) { + const Stmt *Body = FD->getBody(); + if (Body) { + IndexCtx.indexBody(Body, D, FD); + } + } + return true; + } + + bool VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { + IndexCtx.handleTypeAliasTemplate(D); + IndexCtx.indexTypeSourceInfo(D->getTemplatedDecl()->getTypeSourceInfo(), D); + return true; + } +}; + +} // anonymous namespace + +void IndexingContext::indexDecl(const Decl *D) { + if (D->isImplicit() && shouldIgnoreIfImplicit(D)) + return; + + bool Handled = IndexingDeclVisitor(*this).Visit(const_cast<Decl*>(D)); + if (!Handled && isa<DeclContext>(D)) + indexDeclContext(cast<DeclContext>(D)); +} + +void IndexingContext::indexDeclContext(const DeclContext *DC) { + for (DeclContext::decl_iterator + I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { + indexDecl(*I); + } +} + +void IndexingContext::indexTopLevelDecl(Decl *D) { + if (isNotFromSourceFile(D->getLocation())) + return; + + if (isa<ObjCMethodDecl>(D)) + return; // Wait for the objc container. + + indexDecl(D); +} + +void IndexingContext::indexDeclGroupRef(DeclGroupRef DG) { + for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) + indexTopLevelDecl(*I); +} + +void IndexingContext::indexTUDeclsInObjCContainer() { + while (!TUDeclsInObjCContainer.empty()) { + DeclGroupRef DG = TUDeclsInObjCContainer.front(); + TUDeclsInObjCContainer.pop_front(); + indexDeclGroupRef(DG); + } +} |