Index: clang/include/clang/Basic/DiagnosticGroups.td =================================================================== --- clang/include/clang/Basic/DiagnosticGroups.td +++ clang/include/clang/Basic/DiagnosticGroups.td @@ -459,7 +459,9 @@ def RangeLoopAnalysis : DiagGroup<"range-loop-analysis", [RangeLoopConstruct, RangeLoopBindReference]>; def ForLoopAnalysis : DiagGroup<"for-loop-analysis">; -def LoopAnalysis : DiagGroup<"loop-analysis", [ForLoopAnalysis, +def WhileLoopAnalysis : DiagGroup<"while-loop-analysis">; +def LoopAnalysis : DiagGroup<"loop-analysis", [WhileLoopAnalysis, + ForLoopAnalysis, RangeLoopAnalysis]>; def MalformedWarningCheck : DiagGroup<"malformed-warning-check">; def Main : DiagGroup<"main">; @@ -977,6 +979,7 @@ DeleteNonVirtualDtor, Format, ForLoopAnalysis, + WhileLoopAnalysis, FrameAddress, Implicit, InfiniteRecursion, Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -28,6 +28,12 @@ InGroup, DefaultIgnore; def note_loop_iteration_here : Note<"%select{decremented|incremented}0 here">; +// While loop analysis +def warn_variables_not_in_while_loop_body : Warning< + "variable%select{s| %1|s %1 and %2|s %1, %2, and %3|s %1, %2, %3, and %4}0 " + "used in loop condition not modified in loop body">, + InGroup, DefaultIgnore; + def warn_duplicate_enum_values : Warning< "element %0 has been implicitly assigned %1 which another element has " "been assigned">, InGroup>, DefaultIgnore; Index: clang/lib/Sema/SemaStmt.cpp =================================================================== --- clang/lib/Sema/SemaStmt.cpp +++ clang/lib/Sema/SemaStmt.cpp @@ -1673,51 +1673,6 @@ } } -StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, - SourceLocation LParenLoc, ConditionResult Cond, - SourceLocation RParenLoc, Stmt *Body) { - if (Cond.isInvalid()) - return StmtError(); - - auto CondVal = Cond.get(); - CheckBreakContinueBinding(CondVal.second); - - if (CondVal.second && - !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) - CommaVisitor(*this).Visit(CondVal.second); - - if (isa(Body)) - getCurCompoundScope().setHasEmptyLoopBodies(); - - return WhileStmt::Create(Context, CondVal.first, CondVal.second, Body, - WhileLoc, LParenLoc, RParenLoc); -} - -StmtResult -Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, - SourceLocation WhileLoc, SourceLocation CondLParen, - Expr *Cond, SourceLocation CondRParen) { - assert(Cond && "ActOnDoStmt(): missing expression"); - - CheckBreakContinueBinding(Cond); - ExprResult CondResult = CheckBooleanCondition(DoLoc, Cond); - if (CondResult.isInvalid()) - return StmtError(); - Cond = CondResult.get(); - - CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false); - if (CondResult.isInvalid()) - return StmtError(); - Cond = CondResult.get(); - - // Only call the CommaVisitor for C89 due to differences in scope flags. - if (Cond && !getLangOpts().C99 && !getLangOpts().CPlusPlus && - !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc())) - CommaVisitor(*this).Visit(Cond); - - return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); -} - namespace { // Use SetVector since the diagnostic cares about the ordering of the Decl's. using DeclSetVector = @@ -1741,7 +1696,7 @@ Ranges(Ranges), Simple(true) {} - bool isSimple() { return Simple; } + bool isSimple() const { return Simple; } // Replaces the method in EvaluatedExprVisitor. void VisitMemberExpr(MemberExpr* E) { @@ -1887,6 +1842,51 @@ }; // end class DeclMatcher + void CheckWhileLoopConditionalStatement(Sema &S, Expr *Cond, Stmt *Body) { + + if (S.Diags.isIgnored(diag::warn_variables_not_in_while_loop_body, + Cond->getBeginLoc())) + return; + + DeclSetVector Decls; + SmallVector Ranges; + DeclExtractor DE(S, Decls, Ranges); + DE.Visit(Cond); + + // Don't analyze complex conditionals. + if (!DE.isSimple()) + return; + + // No decls found. + if (Decls.empty()) + return; + + // Don't warn on volatile, static, or global variables. + if (std::any_of(Decls.begin(), Decls.end(), [](const auto *VD) { + return VD->getType().isVolatileQualified() || VD->hasGlobalStorage(); + })) + return; + + if (DeclMatcher(S, Decls, Cond).FoundDeclInUse() || + DeclMatcher(S, Decls, Body).FoundDeclInUse()) + return; + + auto Diag = S.Diag(Ranges.begin()->getBegin(), + diag::warn_variables_not_in_while_loop_body); + + // Load decl names into diagnostic. + if (Decls.size() > 4) { + Diag << 0; + } else { + Diag << (unsigned)Decls.size(); + for (auto *VD : Decls) + Diag << VD->getDeclName(); + } + + for (auto Range : Ranges) + Diag << Range; + } + void CheckForLoopConditionalStatement(Sema &S, Expr *Second, Expr *Third, Stmt *Body) { // Condition is empty @@ -2101,6 +2101,55 @@ } // end namespace +StmtResult Sema::ActOnWhileStmt(SourceLocation WhileLoc, + SourceLocation LParenLoc, ConditionResult Cond, + SourceLocation RParenLoc, Stmt *Body) { + if (Cond.isInvalid()) + return StmtError(); + + auto CondVal = Cond.get(); + CheckBreakContinueBinding(CondVal.second); + + if (CondVal.second && + !Diags.isIgnored(diag::warn_comma_operator, CondVal.second->getExprLoc())) + CommaVisitor(*this).Visit(CondVal.second); + + // Check only if variable is not declared inside the condition. + if (!CondVal.first) + CheckWhileLoopConditionalStatement(*this, CondVal.second, Body); + + if (isa(Body)) + getCurCompoundScope().setHasEmptyLoopBodies(); + + return WhileStmt::Create(Context, CondVal.first, CondVal.second, Body, + WhileLoc, LParenLoc, RParenLoc); +} + +StmtResult Sema::ActOnDoStmt(SourceLocation DoLoc, Stmt *Body, + SourceLocation WhileLoc, SourceLocation CondLParen, + Expr *Cond, SourceLocation CondRParen) { + assert(Cond && "ActOnDoStmt(): missing expression"); + + CheckBreakContinueBinding(Cond); + ExprResult CondResult = CheckBooleanCondition(DoLoc, Cond); + if (CondResult.isInvalid()) + return StmtError(); + Cond = CondResult.get(); + + CondResult = ActOnFinishFullExpr(Cond, DoLoc, /*DiscardedValue*/ false); + if (CondResult.isInvalid()) + return StmtError(); + Cond = CondResult.get(); + + // Only call the CommaVisitor for C89 due to differences in scope flags. + if (Cond && !getLangOpts().C99 && !getLangOpts().CPlusPlus && + !Diags.isIgnored(diag::warn_comma_operator, Cond->getExprLoc())) + CommaVisitor(*this).Visit(Cond); + + CheckWhileLoopConditionalStatement(*this, Cond, Body); + + return new (Context) DoStmt(Body, Cond, DoLoc, WhileLoc, CondRParen); +} void Sema::CheckBreakContinueBinding(Expr *E) { if (!E || getLangOpts().CPlusPlus) Index: clang/test/Index/pragma-diag-reparse.c =================================================================== --- clang/test/Index/pragma-diag-reparse.c +++ clang/test/Index/pragma-diag-reparse.c @@ -12,7 +12,7 @@ } #pragma clang diagnostic ignored "-Wmisleading-indentation" -void foo(void) { int b=0; while (b==b); } +void foo(void) { int b=0; while (b==b) ++b; } // RUN: env CINDEXTEST_EDITING=1 CINDEXTEST_FAILONERROR=1 c-index-test -test-load-source-reparse 5 local \ // RUN: -I%S/Inputs \ Index: clang/test/Misc/warning-wall.c =================================================================== --- clang/test/Misc/warning-wall.c +++ clang/test/Misc/warning-wall.c @@ -19,6 +19,7 @@ CHECK-NEXT: -Wformat-invalid-specifier CHECK-NEXT: -Wformat-insufficient-args CHECK-NEXT: -Wfor-loop-analysis +CHECK-NEXT: -Wwhile-loop-analysis CHECK-NEXT: -Wframe-address CHECK-NEXT: -Wimplicit CHECK-NEXT: -Wimplicit-function-declaration Index: clang/test/Preprocessor/pragma_diagnostic_sections.cpp =================================================================== --- clang/test/Preprocessor/pragma_diagnostic_sections.cpp +++ clang/test/Preprocessor/pragma_diagnostic_sections.cpp @@ -2,14 +2,14 @@ // rdar://8365684 struct S { - void m1() { int b; while (b==b); } // expected-warning {{always evaluates to true}} + void m1() { int b; while (b==b) ++b; } // expected-warning {{always evaluates to true}} #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-compare" - void m2() { int b; while (b==b); } + void m2() { int b; while (b==b) ++b; } #pragma clang diagnostic pop - void m3() { int b; while (b==b); } // expected-warning {{always evaluates to true}} + void m3() { int b; while (b==b) ++b; } // expected-warning {{always evaluates to true}} }; //------------------------------------------------------------------------------ @@ -18,7 +18,7 @@ #pragma clang diagnostic ignored "-Wtautological-compare" template struct TS { - void m() { T b; while (b==b); } + void m() { T b; while (b==b) ++b; } }; #pragma clang diagnostic pop Index: clang/test/SemaCXX/warn-loop-analysis.cpp =================================================================== --- clang/test/SemaCXX/warn-loop-analysis.cpp +++ clang/test/SemaCXX/warn-loop-analysis.cpp @@ -41,6 +41,82 @@ for (int *i; *i; ) {} } +void test_while1() { + S s; + int i, j; + while (!s.stop()) {} + while (s.keep_running) {} + while (i < 1) { ++i; } + while (i < 1) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i < 1) { return; } + while (i < 1) { break; } + while (i < 1) { goto exit_loop; } + +exit_loop: + while (i < 1) { by_ref(i); } + while (i < 1) { by_value(i); } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i < 1) { by_pointer(&i); } + + while (i < 1) { + while (j < 1) { ++j; } + ++i; + } + while (i < 1) { + while (j < 1) { ++i; } // expected-warning {{variable 'j' used in loop condition not modified in loop body}} + ++i; + } + while (i < 1) { + while (i < 1) { ++j; } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + ++i; + } + + int *ip, *jp; + while (ip < jp) { ++ip; } + while (ip < jp) {} // expected-warning {{variables 'ip' and 'jp' used in loop condition not modified in loop body}} + + // Dereferencing pointers is ignored for now. + while (*ip) {} +} + +void test_do_while1() { + S s; + int i, j; + do {} while (!s.stop()); + do {} while (s.keep_running); + do { ++i; } while (i < 1); + do {} while (i < 1); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { return; } while (i < 1); + do { break; } while (i < 1); + do { goto exit_loop; } while (i < 1); + +exit_loop: + do { by_ref(i); } while (i < 1); + do { by_value(i); } while (i < 1); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { by_pointer(&i); } while (i < 1); + + do { + do { ++j; } while (j < 1); + ++i; + } while (i < 1); + + do { + do { ++i; } while (j < 1); // expected-warning {{variable 'j' used in loop condition not modified in loop body}} + ++i; + } while (i < 1); + + do { + do { ++j; } while (i < 1); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + ++i; + } while (i < 1); + + int *ip, *jp; + do { ++ip; } while (ip < jp); + do {} while (ip < jp); // expected-warning {{variables 'ip' and 'jp' used in loop condition not modified in loop body}} + + // Dereferencing pointers is ignored for now. + do {} while (*ip); +} + void test2() { int i, j, k; int *ptr; @@ -107,6 +183,138 @@ for (; i < sizeof(j); ) { ++i; } } +void test_while2() { + int i, j, k; + int *ptr; + + // Testing CastExpr + while (i) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i) { i = 5; } + + // Testing BinaryOperator + while (i < j) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}} + while (i < j) { i = 5; } + while (i < j) { j = 5; } + + // Testing IntegerLiteral + while (i < 5) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i < 5) { i = 5; } + + // Testing FloatingLiteral + while (i < 5.0) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i < 5.0) { i = 5; } + + // Testing CharacterLiteral + while (i == 'a') {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i == 'a') { i = 5; } + + // Testing CXXBoolLiteralExpr + while (i == true) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i == true) { i = 5; } + + // Testing GNUNullExpr + while (ptr == __null) {} // expected-warning {{variable 'ptr' used in loop condition not modified in loop body}} + while (ptr == __null) { ptr = &i; } + + // Testing UnaryOperator + while (-i > 5) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (-i > 5) { ++i; } + + // Testing ImaginaryLiteral + while (i != 3i) {} // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i != 3i) { ++i; } + + // Testing ConditionalOperator + while (i ? j : k) {} // expected-warning {{variables 'i', 'j', and 'k' used in loop condition not modified in loop body}} + while (i ? j : k) { ++i; } + while (i ? j : k) { ++j; } + while (i ? j : k) { ++k; } + while (i) { j = i ? i : i; } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i) { j = (i = 1) ? i : i; } + while (i) { j = i ? i : ++i; } + + // Testing BinaryConditionalOperator + while (i ?: j) {} // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}} + while (i ?: j) { ++i; } + while (i ?: j) { ++j; } + while (i) { j = i ?: i; } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + + // Testing ParenExpr + while ((i)) { } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while ((i)) { ++i; } + + // Testing non-evaluated variables + while (i < sizeof(j)) { } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i < sizeof(j)) { ++j; } // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + while (i < sizeof(j)) { ++i; } +} + +void test_do_while2() { + int i, j, k; + int *ptr; + + // Testing CastExpr + do {} while (i); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { i = 5; } while (i); + + // Testing BinaryOperator + do {} while (i < j); // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}} + do { i = 5; } while (i < j); + do { j = 5; } while (i < j); + + // Testing IntegerLiteral + do {} while (i < 5); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { i = 5; } while (i < 5); + + // Testing FloatingLiteral + do {} while (i < 5.0); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { i = 5; } while (i < 5.0); + + // Testing CharacterLiteral + do {} while (i == 'a'); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { i = 5; } while (i == 'a'); + + // Testing CXXBoolLiteralExpr + do {} while (i == true); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { i = 5; } while (i == true); + + // Testing GNUNullExpr + do {} while (ptr == __null); // expected-warning {{variable 'ptr' used in loop condition not modified in loop body}} + do { ptr = &i; } while (ptr == __null); + + // Testing UnaryOperator + do {} while (-i > 5); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { ++i; } while (-i > 5); + + // Testing ImaginaryLiteral + do {} while (i != 3i); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { ++i; } while (i != 3i); + + // Testing ConditionalOperator + do {} while (i ? j : k); // expected-warning {{variables 'i', 'j', and 'k' used in loop condition not modified in loop body}} + do { ++i; } while (i ? j : k); + do { ++j; } while (i ? j : k); + do { ++k; } while (i ? j : k); + do { j = i ? i : i; } while (i); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { j = (i = 1) ? i : i; } while (i); + do { j = i ? i : ++i; } while (i); + + // Testing BinaryConditionalOperator + do {} while (i ?: j); // expected-warning {{variables 'i' and 'j' used in loop condition not modified in loop body}} + do { ++i; } while (i ?: j); + do { ++j; } while (i ?: j); + do { j = i ?: i; } while (i); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + + // Testing ParenExpr + do {} while ((i)); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { ++i; } while ((i)); + + // Testing non-evaluated variables + do {} while (i < sizeof(j)); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { ++j; } while (i < sizeof(j)); // expected-warning {{variable 'i' used in loop condition not modified in loop body}} + do { ++i; } while (i < sizeof(j)); +} + // False positive and how to silence. void test3() { int x; @@ -119,6 +327,28 @@ } } +void test_while3() { + int x; + int *ptr = &x; + while (x < 5) { *ptr = 6; } // expected-warning {{variable 'x' used in loop condition not modified in loop body}} + + while (x < 5) { + *ptr = 6; + (void)x; + } +} + +void test_do_while3() { + int x; + int *ptr = &x; + do { *ptr = 6; } while (x < 5); // expected-warning {{variable 'x' used in loop condition not modified in loop body}} + + do { + *ptr = 6; + (void)x; + } while (x < 5); +} + // Check ordering and printing of variables. Max variables is currently 4. void test4() { int a, b, c, d, e, f; @@ -132,6 +362,30 @@ for (; d + c + b + a;); // expected-warning {{variables 'd', 'c', 'b', and 'a' used in loop condition not modified in loop body}} } +void test_while4() { + int a, b, c, d, e, f; + while (a); // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + while (a + b); // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}} + while (a + b + c); // expected-warning {{variables 'a', 'b', and 'c' used in loop condition not modified in loop body}} + while (a + b + c + d); // expected-warning {{variables 'a', 'b', 'c', and 'd' used in loop condition not modified in loop body}} + while (a + b + c + d + e); // expected-warning {{variables used in loop condition not modified in loop body}} + while (a + b + c + d + e + f); // expected-warning {{variables used in loop condition not modified in loop body}} + while (a + c + d + b); // expected-warning {{variables 'a', 'c', 'd', and 'b' used in loop condition not modified in loop body}} + while (d + c + b + a); // expected-warning {{variables 'd', 'c', 'b', and 'a' used in loop condition not modified in loop body}} +} + +void test_do_while4() { + int a, b, c, d, e, f; + do {} while (a); // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + do {} while (a + b); // expected-warning {{variables 'a' and 'b' used in loop condition not modified in loop body}} + do {} while (a + b + c); // expected-warning {{variables 'a', 'b', and 'c' used in loop condition not modified in loop body}} + do {} while (a + b + c + d); // expected-warning {{variables 'a', 'b', 'c', and 'd' used in loop condition not modified in loop body}} + do {} while (a + b + c + d + e); // expected-warning {{variables used in loop condition not modified in loop body}} + do {} while (a + b + c + d + e + f); // expected-warning {{variables used in loop condition not modified in loop body}} + do {} while (a + c + d + b); // expected-warning {{variables 'a', 'c', 'd', and 'b' used in loop condition not modified in loop body}} + do {} while (d + c + b + a); // expected-warning {{variables 'd', 'c', 'b', and 'a' used in loop condition not modified in loop body}} +} + // Ensure that the warning doesn't fail when lots of variables are used // in the conditional. void test5() { @@ -145,6 +399,30 @@ // expected-warning {{variable 'a' used in loop condition not modified in loop body}} } +void test_while5() { + int a; + while (a+a+a+a+a+a+a+a+a+a); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + while (a+a+a+a+a+a+a+a+a+a+a); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + while (a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + while (a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a);//\ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} +} + +void test_do_while5() { + int a; + do {} while (a+a+a+a+a+a+a+a+a+a); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + do {} while (a+a+a+a+a+a+a+a+a+a+a); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + do {} while (a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a); // \ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} + do {} while (a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a+a);//\ + // expected-warning {{variable 'a' used in loop condition not modified in loop body}} +} + // Ignore global variables and static variables. int x6; void test6() { @@ -153,6 +431,18 @@ for (;y;); } +void test_while6() { + static int y; + while (x6); + while (y); +} + +void test_do_while6() { + static int y; + do {} while (x6); + do {} while (y); +} + void test7() { int i; for (;;i++) { // expected-note{{incremented here}} @@ -279,6 +569,12 @@ for (int i = 0; int x = f(i); ++i) {} } +void test_while9() { + // Don't warn when variable is defined by the loop condition. + int i = 0; + while (int x = f(i)) { ++i; } +} + // Don't warn when decomposition variables are in the loop condition. // TODO: BindingDecl's which make a copy should warn. void test10() { @@ -299,3 +595,41 @@ for (auto[i, j, k] = arr; i < a; ++i) { } for (auto[i, j, k] = arr; i < a; ++arr[0]) { } }; + +void test_while10() { + int arr[] = {1, 2, 3}; + auto[i, j, k] = arr; + while (i < j) { ++i; ++j; } + + while (i) {} + while (i < j) {} + while (i < j ) { ++arr[0]; } + + int a = 1, b = 2; + while (a < b) {} // expected-warning{{variables 'a' and 'b' used in loop condition not modified in loop body}} + while (a < b ) { ++a; } + + while (i < a) {} + while (i < a) { ++a; } + while (i < a) { ++i; } + while (i < a) { ++arr[0]; } +}; + +void test_do_while10() { + int arr[] = {1, 2, 3}; + auto[i, j, k] = arr; + do { ++i; ++j; } while(i < j); + + do {} while (i); + do {} while (i < j); + do { ++arr[0]; } while (i < j ); + + int a = 1, b = 2; + do {} while (a < b); // expected-warning{{variables 'a' and 'b' used in loop condition not modified in loop body}} + do { ++a; } while (a < b ); + + do {} while (i < a); + do { ++a; } while (i < a); + do { ++i; } while (i < a); + do { ++arr[0]; } while (i < a); +};