From a59e390ed6d722f0eaaa9f7eb106eaaf470df3f1 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 21 Jan 2010 23:27:09 +0000 Subject: [PATCH] Teach the cursor visitor to walk statements and expressions, including a few important subkinds. Now we're cookin' with gas! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94116 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Index/c-index-api-loadTU-test.m | 12 ++++ tools/CIndex/CIndex.cpp | 85 ++++++++++++++++++++-------- 2 files changed, 74 insertions(+), 23 deletions(-) diff --git a/test/Index/c-index-api-loadTU-test.m b/test/Index/c-index-api-loadTU-test.m index 677191d7f9..6ddfa1ba18 100644 --- a/test/Index/c-index-api-loadTU-test.m +++ b/test/Index/c-index-api-loadTU-test.m @@ -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] diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 070cb18d77..84073f07a9 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -142,7 +142,8 @@ namespace { // Cursor visitor. class CursorVisitor : public DeclVisitor, - public TypeLocVisitor + public TypeLocVisitor, + public StmtVisitor { ASTUnit *TU; CXCursor Parent; @@ -157,6 +158,7 @@ class CursorVisitor : public DeclVisitor, using DeclVisitor::Visit; using TypeLocVisitor::Visit; + using StmtVisitor::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()) { @@ -292,9 +309,8 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { return false; } - + // 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(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) {