[cfe-commits] r103687 - in /cfe/trunk: test/Index/load-stmts.cpp tools/libclang/CIndex.cpp

Ted Kremenek kremenek at apple.com
Wed May 12 17:25:00 PDT 2010


Author: kremenek
Date: Wed May 12 19:25:00 2010
New Revision: 103687

URL: http://llvm.org/viewvc/llvm-project?rev=103687&view=rev
Log:
Specially handle CaseStmts in CursorVisitor because they can be nested and walking them
can blow out the stack.

Modified:
    cfe/trunk/test/Index/load-stmts.cpp
    cfe/trunk/tools/libclang/CIndex.cpp

Modified: cfe/trunk/test/Index/load-stmts.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/load-stmts.cpp?rev=103687&r1=103686&r2=103687&view=diff
==============================================================================
--- cfe/trunk/test/Index/load-stmts.cpp (original)
+++ cfe/trunk/test/Index/load-stmts.cpp Wed May 12 19:25:00 2010
@@ -54,6 +54,6 @@
 // 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]
 

Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=103687&r1=103686&r2=103687&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Wed May 12 19:25:00 2010
@@ -239,6 +239,27 @@
   /// \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 @@
   // 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 @@
 
   // 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::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) {





More information about the cfe-commits mailing list