diff options
-rw-r--r-- | include/clang/Index/ASTLocation.h | 121 | ||||
-rw-r--r-- | lib/Analysis/CallGraph.cpp | 5 | ||||
-rw-r--r-- | lib/Index/ASTLocation.cpp | 141 | ||||
-rw-r--r-- | lib/Index/Analyzer.cpp | 5 | ||||
-rw-r--r-- | lib/Index/ResolveLocation.cpp | 2 | ||||
-rw-r--r-- | test/Index/resolve-loc.c | 4 | ||||
-rw-r--r-- | tools/CIndex/CIndex.cpp | 4 | ||||
-rw-r--r-- | tools/index-test/index-test.cpp | 8 |
8 files changed, 157 insertions, 133 deletions
diff --git a/include/clang/Index/ASTLocation.h b/include/clang/Index/ASTLocation.h index ba213052ab..9620ec5dbd 100644 --- a/include/clang/Index/ASTLocation.h +++ b/include/clang/Index/ASTLocation.h @@ -14,7 +14,8 @@ #ifndef LLVM_CLANG_INDEX_ASTLOCATION_H #define LLVM_CLANG_INDEX_ASTLOCATION_H -#include <cassert> +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/PointerIntPair.h" namespace llvm { class raw_ostream; @@ -23,7 +24,7 @@ namespace llvm { namespace clang { class Decl; class Stmt; - class SourceRange; + class NamedDecl; namespace idx { class TranslationUnit; @@ -37,26 +38,105 @@ namespace idx { /// like the declaration context, ASTContext, etc. /// class ASTLocation { - const Decl *D; - const Stmt *Stm; +public: + enum NodeKind { + N_Decl, N_NamedRef, N_Stmt, N_Type + }; + + struct NamedRef { + NamedDecl *ND; + SourceLocation Loc; + + NamedRef() : ND(0) { } + NamedRef(NamedDecl *nd, SourceLocation loc) : ND(nd), Loc(loc) { } + }; + +private: + llvm::PointerIntPair<Decl *, 2, NodeKind> ParentDecl; + + union { + Decl *D; + Stmt *Stm; + struct { + NamedDecl *ND; + unsigned RawLoc; + } NDRef; + struct { + void *TyPtr; + void *Data; + } Ty; + }; public: - ASTLocation() : D(0), Stm(0) {} + ASTLocation() { } + + explicit ASTLocation(const Decl *d) + : ParentDecl(const_cast<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { } - explicit ASTLocation(const Decl *d, const Stmt *stm = 0) : D(d), Stm(stm) { - assert((Stm == 0 || isImmediateParent(D, Stm)) && - "The Decl is not the immediate parent of the Stmt."); + ASTLocation(const Decl *parentDecl, const Stmt *stm) + : ParentDecl(const_cast<Decl*>(parentDecl), N_Stmt), + Stm(const_cast<Stmt*>(stm)) { + if (!stm) ParentDecl.setPointer(0); } - const Decl *getDecl() const { return D; } - const Stmt *getStmt() const { return Stm; } - Decl *getDecl() { return const_cast<Decl*>(D); } - Stmt *getStmt() { return const_cast<Stmt*>(Stm); } + ASTLocation(const Decl *parentDecl, NamedDecl *ndRef, SourceLocation loc) + : ParentDecl(const_cast<Decl*>(parentDecl), N_NamedRef) { + if (ndRef) { + NDRef.ND = ndRef; + NDRef.RawLoc = loc.getRawEncoding(); + } else + ParentDecl.setPointer(0); + } + + ASTLocation(const Decl *parentDecl, TypeLoc tyLoc) + : ParentDecl(const_cast<Decl*>(parentDecl), N_Type) { + if (tyLoc) { + Ty.TyPtr = tyLoc.getSourceType().getAsOpaquePtr(); + Ty.Data = tyLoc.getOpaqueData(); + } else + ParentDecl.setPointer(0); + } - bool isValid() const { return D != 0; } + bool isValid() const { return ParentDecl.getPointer() != 0; } bool isInvalid() const { return !isValid(); } - bool isDecl() const { return isValid() && Stm == 0; } - bool isStmt() const { return isValid() && Stm != 0; } + + NodeKind getKind() const { + assert(isValid()); + return (NodeKind)ParentDecl.getInt(); + } + + Decl *getParentDecl() const { return ParentDecl.getPointer(); } + + Decl *AsDecl() const { + assert(getKind() == N_Decl); + return D; + } + Stmt *AsStmt() const { + assert(getKind() == N_Stmt); + return Stm; + } + NamedRef AsNamedRef() const { + assert(getKind() == N_NamedRef); + return NamedRef(NDRef.ND, SourceLocation::getFromRawEncoding(NDRef.RawLoc)); + } + TypeLoc AsTypeLoc() const { + assert(getKind() == N_Type); + return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data); + } + + Decl *dyn_AsDecl() const { return getKind() == N_Decl ? D : 0; } + Stmt *dyn_AsStmt() const { return getKind() == N_Stmt ? Stm : 0; } + NamedRef dyn_AsNamedRef() const { + return getKind() == N_Type ? AsNamedRef() : NamedRef(); + } + TypeLoc dyn_AsTypeLoc() const { + return getKind() == N_Type ? AsTypeLoc() : TypeLoc(); + } + + bool isDecl() const { return isValid() && getKind() == N_Decl; } + bool isStmt() const { return isValid() && getKind() == N_Stmt; } + bool isNamedRef() const { return isValid() && getKind() == N_NamedRef; } + bool isType() const { return isValid() && getKind() == N_Type; } /// \brief Returns the declaration that this ASTLocation references. /// @@ -70,17 +150,6 @@ public: SourceRange getSourceRange() const; - /// \brief Checks that D is the immediate Decl parent of Node. - static bool isImmediateParent(const Decl *D, const Stmt *Node); - static const Decl *FindImmediateParent(const Decl *D, const Stmt *Node); - - friend bool operator==(const ASTLocation &L, const ASTLocation &R) { - return L.D == R.D && L.Stm == R.Stm; - } - friend bool operator!=(const ASTLocation &L, const ASTLocation &R) { - return !(L == R); - } - void print(llvm::raw_ostream &OS) const; }; diff --git a/lib/Analysis/CallGraph.cpp b/lib/Analysis/CallGraph.cpp index f605bd98f5..ae8845db63 100644 --- a/lib/Analysis/CallGraph.cpp +++ b/lib/Analysis/CallGraph.cpp @@ -51,10 +51,7 @@ void CGBuilder::VisitCallExpr(CallExpr *CE) { if (FunctionDecl *CalleeDecl = CE->getDirectCallee()) { Entity Ent = Entity::get(CalleeDecl, G.getProgram()); CallGraphNode *CalleeNode = G.getOrInsertFunction(Ent); - - const Decl *Parent = ASTLocation::FindImmediateParent(FD, CE); - - CallerNode->addCallee(ASTLocation(Parent, CE), CalleeNode); + CallerNode->addCallee(ASTLocation(FD, CE), CalleeNode); } } diff --git a/lib/Index/ASTLocation.cpp b/lib/Index/ASTLocation.cpp index 7bad129d6c..6294d699a8 100644 --- a/lib/Index/ASTLocation.cpp +++ b/lib/Index/ASTLocation.cpp @@ -39,94 +39,40 @@ static Decl *getDeclFromExpr(Stmt *E) { Decl *ASTLocation::getReferencedDecl() { if (isInvalid()) return 0; - if (isDecl()) - return getDecl(); - assert(getStmt()); - return getDeclFromExpr(getStmt()); -} - - -static bool isContainedInStatement(const Stmt *Node, const Stmt *Parent) { - assert(Node && Parent && "Passed null Node or Parent"); - - if (Node == Parent) - return true; - - for (Stmt::const_child_iterator - I = Parent->child_begin(), E = Parent->child_end(); I != E; ++I) { - if (*I) - if (isContainedInStatement(Node, *I)) - return true; - } - - return false; -} - -const Decl *ASTLocation::FindImmediateParent(const Decl *D, const Stmt *Node) { - assert(D && Node && "Passed null Decl or null Stmt"); - - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { - const Expr *Init = VD->getInit(); - if (Init == 0) - return 0; - return isContainedInStatement(Node, Init) ? D : 0; - } - - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - if (!FD->isThisDeclarationADefinition()) - return 0; - - for (DeclContext::decl_iterator - I = FD->decls_begin(), E = FD->decls_end(); I != E; ++I) { - const Decl *Child = FindImmediateParent(*I, Node); - if (Child) - return Child; - } - - assert(FD->getBody() && "If not definition we should have exited already"); - return isContainedInStatement(Node, FD->getBody()) ? D : 0; - } - - if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { - if (!MD->getBody()) - return 0; - - for (DeclContext::decl_iterator - I = MD->decls_begin(), E = MD->decls_end(); I != E; ++I) { - const Decl *Child = FindImmediateParent(*I, Node); - if (Child) - return Child; - } - - assert(MD->getBody() && "If not definition we should have exited already"); - return isContainedInStatement(Node, MD->getBody()) ? D : 0; - } - - if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { - for (DeclContext::decl_iterator - I = BD->decls_begin(), E = BD->decls_end(); I != E; ++I) { - const Decl *Child = FindImmediateParent(*I, Node); - if (Child) - return Child; - } - - assert(BD->getBody() && "BlockDecl without body ?"); - return isContainedInStatement(Node, BD->getBody()) ? D : 0; + switch (getKind()) { + default: assert(0 && "Invalid Kind"); + case N_Type: + return 0; + case N_Decl: + return D; + case N_NamedRef: + return NDRef.ND; + case N_Stmt: + return getDeclFromExpr(Stm); } - + return 0; } -bool ASTLocation::isImmediateParent(const Decl *D, const Stmt *Node) { - assert(D && Node && "Passed null Decl or null Stmt"); - return D == FindImmediateParent(D, Node); -} - SourceRange ASTLocation::getSourceRange() const { if (isInvalid()) return SourceRange(); - return isDecl() ? getDecl()->getSourceRange() : getStmt()->getSourceRange(); + + switch (getKind()) { + default: assert(0 && "Invalid Kind"); + return SourceRange(); + case N_Decl: + return D->getSourceRange(); + case N_Stmt: + return Stm->getSourceRange(); + case N_NamedRef: + return SourceRange(AsNamedRef().Loc, AsNamedRef().Loc); + case N_Type: + return AsTypeLoc().getSourceRange(); + } + + return SourceRange(); } void ASTLocation::print(llvm::raw_ostream &OS) const { @@ -134,21 +80,36 @@ void ASTLocation::print(llvm::raw_ostream &OS) const { OS << "<< Invalid ASTLocation >>\n"; return; } - - OS << "[Decl: " << getDecl()->getDeclKindName() << " "; - if (const NamedDecl *ND = dyn_cast<NamedDecl>(getDecl())) - OS << ND->getNameAsString(); - - if (getStmt()) { - ASTContext &Ctx = getDecl()->getASTContext(); - OS << " | Stmt: " << getStmt()->getStmtClassName() << " "; - getStmt()->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions())); + + ASTContext &Ctx = getParentDecl()->getASTContext(); + + switch (getKind()) { + case N_Decl: + OS << "[Decl: " << AsDecl()->getDeclKindName() << " "; + if (const NamedDecl *ND = dyn_cast<NamedDecl>(AsDecl())) + OS << ND->getNameAsString(); + break; + + case N_Stmt: + OS << "[Stmt: " << AsStmt()->getStmtClassName() << " "; + AsStmt()->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions())); + break; + + case N_NamedRef: + OS << "[NamedRef: " << AsNamedRef().ND->getDeclKindName() << " "; + OS << AsNamedRef().ND->getNameAsString(); + break; + + case N_Type: { + QualType T = AsTypeLoc().getSourceType(); + OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString(); + } } OS << "] <"; SourceRange Range = getSourceRange(); - SourceManager &SourceMgr = getDecl()->getASTContext().getSourceManager(); + SourceManager &SourceMgr = Ctx.getSourceManager(); Range.getBegin().print(OS, SourceMgr); OS << ", "; Range.getEnd().print(OS, SourceMgr); diff --git a/lib/Index/Analyzer.cpp b/lib/Index/Analyzer.cpp index cda2c505fd..300a469220 100644 --- a/lib/Index/Analyzer.cpp +++ b/lib/Index/Analyzer.cpp @@ -144,16 +144,15 @@ public: /// It returns true "eagerly", meaning it will return false only if it can /// "prove" statically that the interface cannot accept this message. bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) { - assert(ASTLoc.isValid()); assert(ASTLoc.isStmt()); // FIXME: Finding @selector references should be through another Analyzer // method, like FindSelectors. - if (isa<ObjCSelectorExpr>(ASTLoc.getStmt())) + if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt())) return false; ObjCInterfaceDecl *MsgD = 0; - ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.getStmt()); + ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt()); if (Msg->getReceiver()) { const ObjCObjectPointerType *OPT = diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp index 281f4d9df1..37dd94509f 100644 --- a/lib/Index/ResolveLocation.cpp +++ b/lib/Index/ResolveLocation.cpp @@ -183,7 +183,7 @@ ASTLocation DeclLocResolver::VisitDeclContext(DeclContext *DC) { ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { ASTLocation ASTLoc = VisitDeclContext(TU); - if (ASTLoc.getDecl() == TU) + if (ASTLoc.getParentDecl() == TU) return ASTLocation(); return ASTLoc; } diff --git a/test/Index/resolve-loc.c b/test/Index/resolve-loc.c index 6da59f0342..cae86f38dd 100644 --- a/test/Index/resolve-loc.c +++ b/test/Index/resolve-loc.c @@ -26,13 +26,11 @@ struct S { // RUN: index-test %t.ast -point-at %s:9:15 | grep for_var && // RUN: index-test %t.ast -point-at %s:9:43 > %t && -// RUN: grep top_func_def %s && -// RUN: grep '++for_var' %s && +// RUN: grep '++for_var' %t && // RUN: index-test %t.ast -point-at %s:10:9 | grep local_var2 && // RUN: index-test %t.ast -point-at %s:10:30 > %t && -// RUN: grep local_var2 %t && // RUN: grep 'for_var + 1' %t && // fields test. diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index d3e37837df..a2719f6fdd 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -512,8 +512,8 @@ CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name, ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc); - Decl *Dcl = ALoc.getDecl(); - Stmt *Stm = ALoc.getStmt(); + Decl *Dcl = ALoc.getParentDecl(); + Stmt *Stm = ALoc.dyn_AsStmt(); if (Dcl) { if (Stm) { if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Stm)) { diff --git a/tools/index-test/index-test.cpp b/tools/index-test/index-test.cpp index decc921ded..103874c77d 100644 --- a/tools/index-test/index-test.cpp +++ b/tools/index-test/index-test.cpp @@ -132,7 +132,7 @@ static void ProcessObjCMessage(ObjCMessageExpr *Msg, Indexer &Idxer) { Analyz.FindObjCMethods(Msg, Results); for (ResultsTy::iterator I = Results.begin(), E = Results.end(); I != E; ++I) { - const ObjCMethodDecl *D = cast<ObjCMethodDecl>(I->getDecl()); + const ObjCMethodDecl *D = cast<ObjCMethodDecl>(I->AsDecl()); if (D->isThisDeclarationADefinition()) I->print(OS); } @@ -146,7 +146,7 @@ static void ProcessASTLocation(ASTLocation ASTLoc, Indexer &Idxer) { assert(ASTLoc.isValid()); if (ObjCMessageExpr *Msg = - dyn_cast_or_null<ObjCMessageExpr>(ASTLoc.getStmt())) + dyn_cast_or_null<ObjCMessageExpr>(ASTLoc.dyn_AsStmt())) return ProcessObjCMessage(Msg, Idxer); Decl *D = ASTLoc.getReferencedDecl(); @@ -184,7 +184,7 @@ static void ProcessASTLocation(ASTLocation ASTLoc, Indexer &Idxer) { Analyz.FindDeclarations(D, Results); for (ResultsTy::iterator I = Results.begin(), E = Results.end(); I != E; ++I) { - const Decl *D = I->getDecl(); + const Decl *D = I->AsDecl(); bool isDef = false; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) isDef = FD->isThisDeclarationADefinition(); @@ -285,7 +285,7 @@ int main(int argc, char **argv) { llvm::raw_ostream &OS = llvm::outs(); ASTLoc.print(OS); if (const char *Comment = - FirstAST->getASTContext().getCommentForDecl(ASTLoc.getDecl())) + FirstAST->getASTContext().getCommentForDecl(ASTLoc.dyn_AsDecl())) OS << "Comment associated with this declaration:\n" << Comment << "\n"; } else { ProcessASTLocation(ASTLoc, Idxer); |