This revision was automatically updated to reflect the committed changes.
Closed by commit rL307051: [Sema] Make BreakContinueFinder handle nested loops. 
(authored by efriedma).

Changed prior to commit:
  https://reviews.llvm.org/D34568?vs=103761&id=105128#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D34568

Files:
  cfe/trunk/lib/Sema/SemaStmt.cpp
  cfe/trunk/test/Sema/loop-control.c
  cfe/trunk/test/SemaCXX/warn-loop-analysis.cpp

Index: cfe/trunk/lib/Sema/SemaStmt.cpp
===================================================================
--- cfe/trunk/lib/Sema/SemaStmt.cpp
+++ cfe/trunk/lib/Sema/SemaStmt.cpp
@@ -1544,23 +1544,78 @@
 
   // A visitor to determine if a continue or break statement is a
   // subexpression.
-  class BreakContinueFinder : public EvaluatedExprVisitor<BreakContinueFinder> {
+  class BreakContinueFinder : public ConstEvaluatedExprVisitor<BreakContinueFinder> {
     SourceLocation BreakLoc;
     SourceLocation ContinueLoc;
+    bool InSwitch = false;
+
   public:
-    BreakContinueFinder(Sema &S, Stmt* Body) :
+    BreakContinueFinder(Sema &S, const Stmt* Body) :
         Inherited(S.Context) {
       Visit(Body);
     }
 
-    typedef EvaluatedExprVisitor<BreakContinueFinder> Inherited;
+    typedef ConstEvaluatedExprVisitor<BreakContinueFinder> Inherited;
 
-    void VisitContinueStmt(ContinueStmt* E) {
+    void VisitContinueStmt(const ContinueStmt* E) {
       ContinueLoc = E->getContinueLoc();
     }
 
-    void VisitBreakStmt(BreakStmt* E) {
-      BreakLoc = E->getBreakLoc();
+    void VisitBreakStmt(const BreakStmt* E) {
+      if (!InSwitch)
+        BreakLoc = E->getBreakLoc();
+    }
+
+    void VisitSwitchStmt(const SwitchStmt* S) {
+      if (const Stmt *Init = S->getInit())
+        Visit(Init);
+      if (const Stmt *CondVar = S->getConditionVariableDeclStmt())
+        Visit(CondVar);
+      if (const Stmt *Cond = S->getCond())
+        Visit(Cond);
+
+      // Don't return break statements from the body of a switch.
+      InSwitch = true;
+      if (const Stmt *Body = S->getBody())
+        Visit(Body);
+      InSwitch = false;
+    }
+
+    void VisitForStmt(const ForStmt *S) {
+      // Only visit the init statement of a for loop; the body
+      // has a different break/continue scope.
+      if (const Stmt *Init = S->getInit())
+        Visit(Init);
+    }
+
+    void VisitWhileStmt(const WhileStmt *) {
+      // Do nothing; the children of a while loop have a different
+      // break/continue scope.
+    }
+
+    void VisitDoStmt(const DoStmt *) {
+      // Do nothing; the children of a while loop have a different
+      // break/continue scope.
+    }
+
+    void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
+      // Only visit the initialization of a for loop; the body
+      // has a different break/continue scope.
+      if (const Stmt *Range = S->getRangeStmt())
+        Visit(Range);
+      if (const Stmt *Begin = S->getBeginStmt())
+        Visit(Begin);
+      if (const Stmt *End = S->getEndStmt())
+        Visit(End);
+    }
+
+    void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
+      // Only visit the initialization of a for loop; the body
+      // has a different break/continue scope.
+      if (const Stmt *Element = S->getElement())
+        Visit(Element);
+      if (const Stmt *Collection = S->getCollection())
+        Visit(Collection);
     }
 
     bool ContinueFound() { return ContinueLoc.isValid(); }
Index: cfe/trunk/test/SemaCXX/warn-loop-analysis.cpp
===================================================================
--- cfe/trunk/test/SemaCXX/warn-loop-analysis.cpp
+++ cfe/trunk/test/SemaCXX/warn-loop-analysis.cpp
@@ -202,6 +202,12 @@
     if (true) continue;
     i--;
   }
+
+  // But do warn if the continue is in a nested loop.
+  for (;;i--) { // expected-note{{decremented here}}
+    for (int j = 0; j < 10; ++j) continue;
+    i--; // expected-warning{{decremented both}}
+  }
 }
 
 struct iterator {
@@ -259,6 +265,12 @@
     if (true) continue;
     i--;
   }
+
+  // But do warn if the continue is in a nested loop.
+  for (;;i--) { // expected-note{{decremented here}}
+    for (int j = 0; j < 10; ++j) continue;
+    i--; // expected-warning{{decremented both}}
+  }
 }
 
 int f(int);
Index: cfe/trunk/test/Sema/loop-control.c
===================================================================
--- cfe/trunk/test/Sema/loop-control.c
+++ cfe/trunk/test/Sema/loop-control.c
@@ -119,3 +119,51 @@
     for ( ; ({ ++y; break; y;}); ++y) {} // expected-warning{{'break' is bound to loop, GCC binds it to switch}}
   }
 }
+
+void pr32648_1(int x, int y) {
+  switch(x) {
+  case 1:
+    for ( ; ({ ++y; switch (y) { case 0: break; } y;}); ++y) {} // no warning
+  }
+}
+
+void pr32648_2(int x, int y) {
+  while(x) {
+    for ( ; ({ ++y; switch (y) { case 0: continue; } y;}); ++y) {}  // expected-warning {{'continue' is bound to current loop, GCC binds it to the enclosing loop}}
+  }
+}
+
+void pr32648_3(int x, int y) {
+  switch(x) {
+  case 1:
+    for ( ; ({ ++y; for (; y; y++) { break; } y;}); ++y) {} // no warning
+  }
+}
+
+void pr32648_4(int x, int y) {
+  switch(x) {
+  case 1:
+    for ( ; ({ ++y; for (({ break; }); y; y++) { } y;}); ++y) {} // expected-warning{{'break' is bound to loop, GCC binds it to switch}}
+  }
+}
+
+void pr32648_5(int x, int y) {
+  switch(x) {
+  case 1:
+    for ( ; ({ ++y; while (({ break; y; })) {} y;}); ++y) {} // expected-warning{{'break' is bound to current loop, GCC binds it to the enclosing loop}}
+  }
+}
+
+void pr32648_6(int x, int y) {
+  switch(x) {
+  case 1:
+    for ( ; ({ ++y; do {} while (({ break; y; })); y;}); ++y) {} // expected-warning{{'break' is bound to current loop, GCC binds it to the enclosing loop}}
+  }
+}
+
+void pr32648_7(int x, int y) {
+  switch(x) {
+  case 1:
+    for ( ; ({ ++y; do { break; } while (y); y;}); ++y) {} // no warning
+  }
+}
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D34568: [... Eli Friedman via Phabricator via cfe-commits
    • [PATCH] D345... Eli Friedman via Phabricator via cfe-commits
    • [PATCH] D345... Richard Smith - zygoloid via Phabricator via cfe-commits
    • [PATCH] D345... Eli Friedman via Phabricator via cfe-commits

Reply via email to