diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-01-21 23:27:09 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-01-21 23:27:09 +0000 |
commit | a59e390ed6d722f0eaaa9f7eb106eaaf470df3f1 (patch) | |
tree | bb26bdc35f5e3fe2d8c1fb69a0c5293c5ff51c55 | |
parent | b5c775575b496c03d862ea03587a9f1d74193c9f (diff) |
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
-rw-r--r-- | test/Index/c-index-api-loadTU-test.m | 12 | ||||
-rw-r--r-- | 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<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()) { @@ -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<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) { |