[cfe-commits] r139437 - in /cfe/trunk: include/clang/AST/Stmt.h lib/AST/Stmt.cpp lib/Analysis/CFG.cpp test/SemaCXX/return-noreturn.cpp

Chandler Carruth chandlerc at gmail.com
Fri Sep 9 17:02:35 PDT 2011


Author: chandlerc
Date: Fri Sep  9 19:02:34 2011
New Revision: 139437

URL: http://llvm.org/viewvc/llvm-project?rev=139437&view=rev
Log:
Extend the Stmt AST to make it easier to look through label, default,
and case statements. Use this to make the logic in the CFG builder more
robust at finding the actual statements within a compound statement,
even when there are many layers of labels obscuring it.

Also extend the test cases for a large chunk of PR10063. Still more work
to do here though.

Modified:
    cfe/trunk/include/clang/AST/Stmt.h
    cfe/trunk/lib/AST/Stmt.cpp
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/test/SemaCXX/return-noreturn.cpp

Modified: cfe/trunk/include/clang/AST/Stmt.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Stmt.h?rev=139437&r1=139436&r2=139437&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Stmt.h (original)
+++ cfe/trunk/include/clang/AST/Stmt.h Fri Sep  9 19:02:34 2011
@@ -296,6 +296,12 @@
   /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes.
   Stmt *IgnoreImplicit();
 
+  const Stmt *stripLabelLikeStatements() const;
+  Stmt *stripLabelLikeStatements() {
+    return const_cast<Stmt*>(
+      const_cast<const Stmt*>(this)->stripLabelLikeStatements());
+  }
+
   // Implement isa<T> support.
   static bool classof(const Stmt *) { return true; }
 

Modified: cfe/trunk/lib/AST/Stmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Stmt.cpp?rev=139437&r1=139436&r2=139437&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Stmt.cpp (original)
+++ cfe/trunk/lib/AST/Stmt.cpp Fri Sep  9 19:02:34 2011
@@ -97,6 +97,22 @@
   return s;
 }
 
+/// \brief Strip off all label-like statements.
+///
+/// This will strip off label statements, case statements, and default
+/// statements recursively.
+const Stmt *Stmt::stripLabelLikeStatements() const {
+  const Stmt *S = this;
+  while (true) {
+    if (const LabelStmt *LS = dyn_cast<LabelStmt>(S))
+      S = LS->getSubStmt();
+    else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))
+      S = SC->getSubStmt();
+    else
+      return S;
+  }
+}
+
 namespace {
   struct good {};
   struct bad {};

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=139437&r1=139436&r2=139437&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Fri Sep  9 19:02:34 2011
@@ -723,9 +723,7 @@
   if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
     for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end()
         ; BI != BE; ++BI) {
-      Stmt *SI = *BI;
-      if (LabelStmt *LS = dyn_cast<LabelStmt>(SI))
-        SI = LS->getSubStmt();
+      Stmt *SI = (*BI)->stripLabelLikeStatements();
       if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
         Scope = addLocalScopeForDeclStmt(DS, Scope);
     }
@@ -734,9 +732,7 @@
 
   // For any other statement scope will be implicit and as such will be
   // interesting only for DeclStmt.
-  if (LabelStmt *LS = dyn_cast<LabelStmt>(S))
-    S = LS->getSubStmt();
-  if (DeclStmt *DS = dyn_cast<DeclStmt>(S))
+  if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
     addLocalScopeForDeclStmt(DS);
 }
 

Modified: cfe/trunk/test/SemaCXX/return-noreturn.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/return-noreturn.cpp?rev=139437&r1=139436&r2=139437&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/return-noreturn.cpp (original)
+++ cfe/trunk/test/SemaCXX/return-noreturn.cpp Fri Sep  9 19:02:34 2011
@@ -8,23 +8,37 @@
   ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }
 };
 
-int pr6884_f(int x) {
-  switch (x) { default: pr6884_abort(); }
-}
-
-int pr6884_g(int x) {
-  switch (x) { default: pr6884_abort_struct(); }
-}
-
-int pr6884_g_positive(int x) {
-  switch (x) { default: ; }
-} // expected-warning {{control reaches end of non-void function}}
+// Ensure that destructors from objects are properly modeled in the CFG despite
+// the presence of switches, case statements, labels, and blocks. These tests
+// try to cover bugs reported in both PR6884 and PR10063.
+namespace abort_struct_complex_cfgs {
+  int basic(int x) {
+    switch (x) { default: pr6884_abort(); }
+  }
+  int f1(int x) {
+    switch (x) default: pr6884_abort_struct();
+  }
+  int f2(int x) {
+    switch (x) { default: pr6884_abort_struct(); }
+  }
+  int f2_positive(int x) {
+    switch (x) { default: ; }
+  } // expected-warning {{control reaches end of non-void function}}
+  int f3(int x) {
+    switch (x) { default: { pr6884_abort_struct(); } }
+  }
+  int f4(int x) {
+    switch (x) default: L1: L2: case 4: pr6884_abort_struct();
+  }
+  int f5(int x) {
+    switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }
+  }
+  int f6(int x) {
+    switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
+  }
 
-int pr6884_h(int x) {
-  switch (x) {
-    default: {
-      pr6884_abort_struct a;
-    }
+  int h(int x) {
+    switch (x) { default: { pr6884_abort_struct a; } }
   }
 }
 





More information about the cfe-commits mailing list