diff options
-rw-r--r-- | test/Index/load-stmts.cpp | 2 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 95 |
2 files changed, 74 insertions, 23 deletions
diff --git a/test/Index/load-stmts.cpp b/test/Index/load-stmts.cpp index b03d78f6ff..cb99aee3ad 100644 --- a/test/Index/load-stmts.cpp +++ b/test/Index/load-stmts.cpp @@ -54,6 +54,6 @@ void f(int x) { // CHECK: load-stmts.cpp:8:13: DeclRefExpr=z4:8:13 Extent=[8:13 - 8:15] // CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[8:21 - 10:4] // CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:3 - 9:17] -// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:12 - 9:17] // CHECK: load-stmts.cpp:9:8: UnexposedExpr= Extent=[9:8 - 9:10] +// CHECK: <invalid loc>:0:0: UnexposedStmt= Extent=[9:12 - 9:17] diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 7f227a01eb..ffcaa882bb 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -239,6 +239,27 @@ class CursorVisitor : public DeclVisitor<CursorVisitor, bool>, /// \param R a half-open source range retrieved from the abstract syntax tree. RangeComparisonResult CompareRegionOfInterest(SourceRange R); + class SetParentRAII { + CXCursor &Parent; + Decl *&StmtParent; + CXCursor OldParent; + + public: + SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent) + : Parent(Parent), StmtParent(StmtParent), OldParent(Parent) + { + Parent = NewParent; + if (clang_isDeclaration(Parent.kind)) + StmtParent = getCursorDecl(Parent); + } + + ~SetParentRAII() { + Parent = OldParent; + if (clang_isDeclaration(Parent.kind)) + StmtParent = getCursorDecl(Parent); + } + }; + public: CursorVisitor(ASTUnit *TU, CXCursorVisitor Visitor, CXClientData ClientData, unsigned MaxPCHLevel, @@ -316,8 +337,10 @@ public: // FIXME: LabelStmt label? bool VisitIfStmt(IfStmt *S); bool VisitSwitchStmt(SwitchStmt *S); + bool VisitCaseStmt(CaseStmt *S); bool VisitWhileStmt(WhileStmt *S); bool VisitForStmt(ForStmt *S); +// bool VisitSwitchCase(SwitchCase *S); // Expression visitors bool VisitBlockExpr(BlockExpr *B); @@ -436,26 +459,7 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) { // Set the Parent field to Cursor, then back to its old value once we're // done. - class SetParentRAII { - CXCursor &Parent; - Decl *&StmtParent; - CXCursor OldParent; - - public: - SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent) - : Parent(Parent), StmtParent(StmtParent), OldParent(Parent) - { - Parent = NewParent; - if (clang_isDeclaration(Parent.kind)) - StmtParent = getCursorDecl(Parent); - } - - ~SetParentRAII() { - Parent = OldParent; - if (clang_isDeclaration(Parent.kind)) - StmtParent = getCursorDecl(Parent); - } - } SetParent(Parent, StmtParent, Cursor); + SetParentRAII SetParent(Parent, StmtParent, Cursor); if (clang_isDeclaration(Cursor.kind)) { Decl *D = getCursorDecl(Cursor); @@ -888,13 +892,60 @@ bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { bool CursorVisitor::VisitStmt(Stmt *S) { for (Stmt::child_iterator Child = S->child_begin(), ChildEnd = S->child_end(); Child != ChildEnd; ++Child) { - if (*Child && Visit(MakeCXCursor(*Child, StmtParent, TU))) - return true; + if (Stmt *C = *Child) + if (Visit(MakeCXCursor(C, StmtParent, TU))) + return true; } return false; } +bool CursorVisitor::VisitCaseStmt(CaseStmt *S) { + // Specially handle CaseStmts because they can be nested, e.g.: + // + // case 1: + // case 2: + // + // In this case the second CaseStmt is the child of the first. Walking + // these recursively can blow out the stack. + CXCursor Cursor = MakeCXCursor(S, StmtParent, TU); + while (true) { + // Set the Parent field to Cursor, then back to its old value once we're + // done. + SetParentRAII SetParent(Parent, StmtParent, Cursor); + + if (Stmt *LHS = S->getLHS()) + if (Visit(MakeCXCursor(LHS, StmtParent, TU))) + return true; + if (Stmt *RHS = S->getRHS()) + if (Visit(MakeCXCursor(RHS, StmtParent, TU))) + return true; + if (Stmt *SubStmt = S->getSubStmt()) { + if (!isa<CaseStmt>(SubStmt)) + return Visit(MakeCXCursor(SubStmt, StmtParent, TU)); + + // Specially handle 'CaseStmt' so that we don't blow out the stack. + CaseStmt *CS = cast<CaseStmt>(SubStmt); + Cursor = MakeCXCursor(CS, StmtParent, TU); + if (RegionOfInterest.isValid()) { + SourceRange Range = CS->getSourceRange(); + if (Range.isInvalid() || CompareRegionOfInterest(Range)) + return false; + } + + switch (Visitor(Cursor, Parent, ClientData)) { + case CXChildVisit_Break: return true; + case CXChildVisit_Continue: return false; + case CXChildVisit_Recurse: + // Perform tail-recursion manually. + S = CS; + continue; + } + } + return false; + } +} + bool CursorVisitor::VisitDeclStmt(DeclStmt *S) { for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); D != DEnd; ++D) { |