forked from OSchip/llvm-project
Modify ASTLocation and apart from being a Decl or Stmt, allow it to also be:
-A NamedDecl reference -A TypeLoc llvm-svn: 83095
This commit is contained in:
parent
73360e1bbb
commit
4cbe85904c
|
@ -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, const Stmt *stm = 0) : D(d), Stm(stm) {
|
||||
assert((Stm == 0 || isImmediateParent(D, Stm)) &&
|
||||
"The Decl is not the immediate parent of the Stmt.");
|
||||
explicit ASTLocation(const Decl *d)
|
||||
: ParentDecl(const_cast<Decl*>(d), N_Decl), D(const_cast<Decl*>(d)) { }
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
bool isValid() const { return D != 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 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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
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 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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ASTContext &Ctx = getParentDecl()->getASTContext();
|
||||
|
||||
OS << "[Decl: " << getDecl()->getDeclKindName() << " ";
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(getDecl()))
|
||||
OS << ND->getNameAsString();
|
||||
switch (getKind()) {
|
||||
case N_Decl:
|
||||
OS << "[Decl: " << AsDecl()->getDeclKindName() << " ";
|
||||
if (const NamedDecl *ND = dyn_cast<NamedDecl>(AsDecl()))
|
||||
OS << ND->getNameAsString();
|
||||
break;
|
||||
|
||||
if (getStmt()) {
|
||||
ASTContext &Ctx = getDecl()->getASTContext();
|
||||
OS << " | Stmt: " << getStmt()->getStmtClassName() << " ";
|
||||
getStmt()->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
|
||||
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);
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue