Teach the cursor visitor to walk statements and expressions, including

a few important subkinds. Now we're cookin' with gas!

llvm-svn: 94116
This commit is contained in:
Douglas Gregor 2010-01-21 23:27:09 +00:00
parent 60dbeebee8
commit 5e8cf37917
2 changed files with 74 additions and 23 deletions

View File

@ -87,3 +87,15 @@ int main (int argc, const char * argv[]) {
// CHECK: c-index-api-loadTU-test.m:49:13: VarDecl=d:49:13 (Definition) [Extent=49:13:49:13]
// CHECK: c-index-api-loadTU-test.m:49:2: TypeRef=id:0:0 [Extent=49:2:49:3]
// CHECK: c-index-api-loadTU-test.m:49:6: ObjCProtocolRef=Proto:24:1 [Extent=49:6:49:10]
// CHECK: c-index-api-loadTU-test.m:50:2: DeclRefExpr=d:49:13 [Extent=50:2:50:2]
// CHECK: c-index-api-loadTU-test.m:50:6: DeclRefExpr=c:48:12 [Extent=50:6:50:6]
// CHECK: c-index-api-loadTU-test.m:51:2: ObjCMessageExpr=pMethod:25:1 [Extent=51:2:51:12]
// CHECK: c-index-api-loadTU-test.m:51:3: DeclRefExpr=d:49:13 [Extent=51:3:51:3]
// CHECK: c-index-api-loadTU-test.m:52:2: ObjCMessageExpr=catMethodWithFloat::20:1 [Extent=52:2:52:43]
// CHECK: c-index-api-loadTU-test.m:52:3: DeclRefExpr=bee:46:8 [Extent=52:3:52:5]
// CHECK: c-index-api-loadTU-test.m:52:26: ObjCMessageExpr=floatMethod:21:1 [Extent=52:26:52:42]
// CHECK: c-index-api-loadTU-test.m:52:27: DeclRefExpr=bee:46:8 [Extent=52:27:52:29]
// CHECK: c-index-api-loadTU-test.m:53:3: CallExpr=main:45:5 [Extent=53:3:53:36]
// CHECK: c-index-api-loadTU-test.m:53:3: DeclRefExpr=main:45:5 [Extent=53:3:53:6]
// CHECK: c-index-api-loadTU-test.m:53:8: DeclRefExpr=someEnum:42:3 [Extent=53:8:53:15]
// CHECK: c-index-api-loadTU-test.m:53:33: DeclRefExpr=bee:46:8 [Extent=53:33:53:35]

View File

@ -142,7 +142,8 @@ namespace {
// Cursor visitor.
class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
public TypeLocVisitor<CursorVisitor, bool>
public TypeLocVisitor<CursorVisitor, bool>,
public StmtVisitor<CursorVisitor, bool>
{
ASTUnit *TU;
CXCursor Parent;
@ -157,6 +158,7 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
using DeclVisitor<CursorVisitor, bool>::Visit;
using TypeLocVisitor<CursorVisitor, bool>::Visit;
using StmtVisitor<CursorVisitor, bool>::Visit;
public:
CursorVisitor(ASTUnit *TU, CXCursorVisitor Visitor, CXClientData ClientData,
@ -178,6 +180,7 @@ public:
bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
bool VisitDeclaratorDecl(DeclaratorDecl *DD);
bool VisitFunctionDecl(FunctionDecl *ND);
bool VisitObjCContainerDecl(ObjCContainerDecl *D);
bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
@ -205,6 +208,10 @@ public:
// implemented
bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
// Statement visitors
bool VisitStmt(Stmt *S);
bool VisitDeclStmt(DeclStmt *S);
};
} // end anonymous namespace
@ -247,6 +254,11 @@ bool CursorVisitor::Visit(CXCursor Cursor) {
/// \returns true if the visitation should be aborted, false if it
/// should continue.
bool CursorVisitor::VisitChildren(CXCursor Cursor) {
if (clang_isReference(Cursor.kind)) {
// By definition, references have no children.
return false;
}
// Set the Parent field to Cursor, then back to its old value once we're
// done.
class SetParentRAII {
@ -276,6 +288,11 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
return Visit(D);
}
if (clang_isStatement(Cursor.kind))
return Visit(getCursorStmt(Cursor));
if (clang_isExpression(Cursor.kind))
return Visit(getCursorExpr(Cursor));
if (clang_isTranslationUnit(Cursor.kind)) {
ASTUnit *CXXUnit = getCursorASTUnit(Cursor);
if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls()) {
@ -294,7 +311,6 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
}
// Nothing to visit at the moment.
// FIXME: Traverse statements, declarations, etc. here.
return false;
}
@ -325,21 +341,17 @@ bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
if (VisitDeclaratorDecl(ND))
return true;
// FIXME: This is wrong. We want to visit the body as a statement.
if (ND->isThisDeclarationADefinition()) {
return VisitDeclContext(ND);
#if 0
// Not currently needed.
CompoundStmt *Body = dyn_cast<CompoundStmt>(ND->getBody());
CRefVisitor RVisit(CDecl, Callback, CData);
RVisit.Visit(Body);
#endif
}
if (ND->isThisDeclarationADefinition() &&
Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
return true;
return false;
}
bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
return VisitDeclContext(D);
}
bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
TU)))
@ -351,7 +363,7 @@ bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
return true;
return VisitDeclContext(ND);
return VisitObjCContainerDecl(ND);
}
bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
@ -368,13 +380,23 @@ bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
return true;
return VisitDeclContext(D);
return VisitObjCContainerDecl(D);
}
bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
// FIXME: Wrong in the same way that VisitFunctionDecl is wrong.
if (ND->getBody())
return VisitDeclContext(ND);
// FIXME: We really need a TypeLoc covering Objective-C method declarations.
// At the moment, we don't have information about locations in the return
// type.
for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
PEnd = ND->param_end();
P != PEnd; ++P) {
if (Visit(MakeCXCursor(*P, TU)))
return true;
}
if (ND->isThisDeclarationADefinition() &&
Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
return true;
return false;
}
@ -386,7 +408,7 @@ bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
return true;
return VisitDeclContext(PID);
return VisitObjCContainerDecl(PID);
}
bool CursorVisitor::VisitTagDecl(TagDecl *D) {
@ -517,9 +539,6 @@ bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
if (Visit(TL.getResultLoc()))
return true;
// FIXME: For function definitions, this means that we'll end up
// visiting the parameters twice, because VisitFunctionDecl is
// walking the DeclContext.
for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
if (Visit(MakeCXCursor(TL.getArg(I), TU)))
return true;
@ -548,6 +567,26 @@ bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
return false;
}
bool CursorVisitor::VisitStmt(Stmt *S) {
for (Stmt::child_iterator Child = S->child_begin(), ChildEnd = S->child_end();
Child != ChildEnd; ++Child) {
if (Visit(MakeCXCursor(*Child, StmtParent, TU)))
return true;
}
return false;
}
bool CursorVisitor::VisitDeclStmt(DeclStmt *S) {
for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
D != DEnd; ++D) {
if (Visit(MakeCXCursor(*D, TU)))
return true;
}
return false;
}
CXString CIndexer::createCXString(const char *String, bool DupString){
CXString Str;
if (DupString) {