- Implement support for various types of "refs" (initially to help test clang_getCursor()).
- Add missing prototypes for dispose functions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82564 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index de50b80..d0c1ea5 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -17,6 +17,7 @@
#include "clang/Index/ASTLocation.h"
#include "clang/Index/Utils.h"
#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
#include "clang/AST/Decl.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
@@ -27,6 +28,45 @@
namespace {
+class CRefVisitor : public StmtVisitor<CRefVisitor> {
+ CXDecl CDecl;
+ CXDeclIterator Callback;
+ CXClientData CData;
+
+ void Call(enum CXCursorKind CK, Stmt *SRef) {
+ CXCursor C = { CK, CDecl, SRef };
+ Callback(CDecl, C, CData);
+ }
+
+public:
+ CRefVisitor(CXDecl C, CXDeclIterator cback, CXClientData D) :
+ CDecl(C), Callback(cback), CData(D) {}
+
+ void VisitStmt(Stmt *S) {
+ for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
+ C != CEnd; ++C)
+ Visit(*C);
+ }
+ void VisitDeclRefExpr(DeclRefExpr *Node) {
+ NamedDecl *D = Node->getDecl();
+ if (isa<VarDecl>(D))
+ Call(CXCursor_VarRef, Node);
+ else if (isa<FunctionDecl>(D))
+ Call(CXCursor_FunctionRef, Node);
+ else if (isa<EnumConstantDecl>(D))
+ Call(CXCursor_EnumConstantRef, Node);
+ }
+ void VisitMemberExpr(MemberExpr *Node) {
+ Call(CXCursor_MemberRef, Node);
+ }
+ void VisitObjCMessageExpr(ObjCMessageExpr *Node) {
+ Call(CXCursor_ObjCSelectorRef, Node);
+ }
+ void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
+ Call(CXCursor_ObjCIvarRef, Node);
+ }
+};
+
// Translation Unit Visitor.
class TUVisitor : public DeclVisitor<TUVisitor> {
CXTranslationUnit TUnit;
@@ -34,7 +74,7 @@
CXClientData CData;
void Call(enum CXCursorKind CK, NamedDecl *ND) {
- CXCursor C = { CK, ND };
+ CXCursor C = { CK, ND, 0 };
Callback(TUnit, C, CData);
}
public:
@@ -103,7 +143,7 @@
// Disable the callback when the context is equal to the visiting decl.
if (CDecl == ND && !clang_isReference(CK))
return;
- CXCursor C = { CK, ND };
+ CXCursor C = { CK, ND, 0 };
Callback(CDecl, C, CData);
}
public:
@@ -168,6 +208,9 @@
void VisitFunctionDecl(FunctionDecl *ND) {
if (ND->isThisDeclarationADefinition()) {
VisitDeclContext(dyn_cast<DeclContext>(ND));
+
+ CRefVisitor RVisit(CDecl, Callback, CData);
+ RVisit.Visit(ND->getBody());
}
}
void VisitObjCMethodDecl(ObjCMethodDecl *ND) {
@@ -323,6 +366,22 @@
assert(OID && "clang_getCursorLine(): Missing protocol decl");
return OID->getIdentifier()->getName();
}
+ case CXCursor_ObjCSelectorRef:
+ {
+ ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
+ static_cast<Stmt *>(C.stmt));
+ assert(OME && "clang_getCursorLine(): Missing message expr");
+ return OME->getSelector().getAsString().c_str();
+ }
+ case CXCursor_VarRef:
+ case CXCursor_FunctionRef:
+ case CXCursor_EnumConstantRef:
+ {
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
+ static_cast<Stmt *>(C.stmt));
+ assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
+ return DRE->getDecl()->getIdentifier()->getName();
+ }
default:
return "<not implemented>";
}
@@ -358,6 +417,13 @@
case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
case CXCursor_ObjCProtocolRef: return "ObjCProtocolRef";
case CXCursor_ObjCClassRef: return "ObjCClassRef";
+ case CXCursor_ObjCSelectorRef: return "ObjCSelectorRef";
+
+ case CXCursor_VarRef: return "VarRef";
+ case CXCursor_FunctionRef: return "FunctionRef";
+ case CXCursor_EnumConstantRef: return "EnumConstantRef";
+ case CXCursor_MemberRef: return "MemberRef";
+
case CXCursor_InvalidFile: return "InvalidFile";
case CXCursor_NoDeclFound: return "NoDeclFound";
case CXCursor_NotImplemented: return "NotImplemented";
@@ -376,6 +442,8 @@
case Decl::Var: return CXCursor_VarDecl;
case Decl::ParmVar: return CXCursor_ParmDecl;
case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
+ case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
+ case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
case Decl::ObjCMethod: {
ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
if (MD->isInstanceMethod())
@@ -399,7 +467,7 @@
const FileEntry *File = FMgr.getFile(source_name,
source_name+strlen(source_name));
if (!File) {
- CXCursor C = { CXCursor_InvalidFile, 0 };
+ CXCursor C = { CXCursor_InvalidFile, 0, 0 };
return C;
}
SourceLocation SLoc =
@@ -409,10 +477,10 @@
Decl *Dcl = ALoc.getDecl();
if (Dcl) {
- CXCursor C = { TranslateKind(Dcl), Dcl };
+ CXCursor C = { TranslateKind(Dcl), Dcl, 0 };
return C;
}
- CXCursor C = { CXCursor_NoDeclFound, 0 };
+ CXCursor C = { CXCursor_NoDeclFound, 0, 0 };
return C;
}
@@ -421,7 +489,7 @@
assert(AnonDecl && "Passed null CXDecl");
NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- CXCursor C = { TranslateKind(ND), ND };
+ CXCursor C = { TranslateKind(ND), ND, 0 };
return C;
}
@@ -472,6 +540,22 @@
assert(OID && "clang_getCursorLine(): Missing protocol decl");
return OID->getLocation();
}
+ case CXCursor_ObjCSelectorRef:
+ {
+ ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
+ static_cast<Stmt *>(C.stmt));
+ assert(OME && "clang_getCursorLine(): Missing message expr");
+ return OME->getLeftLoc(); /* FIXME: should be a range */
+ }
+ case CXCursor_VarRef:
+ case CXCursor_FunctionRef:
+ case CXCursor_EnumConstantRef:
+ {
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
+ static_cast<Stmt *>(C.stmt));
+ assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
+ return DRE->getLocation();
+ }
default:
return SourceLocation();
}