Block = Succ = TransitionBlock = createBlock(false);
TransitionBlock->setLoopTarget(F);
+
+ // Loop iteration (after increment) should end with destructor of Condition
+ // variable (if any).
+ addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
+
if (Stmt *I = F->getInc()) {
// Generate increment code in its own basic block. This is the target of
// continue statements.
ContinueJumpTarget = JumpTarget(Succ, ContinueScopePos);
ContinueJumpTarget.block->setLoopTarget(F);
- // Loop body should end with destructor of Condition variable (if any).
- addAutomaticObjHandling(ScopePos, LoopBeginScopePos, F);
// If body is not a compound statement create implicit scope
// and add destructors.
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B2.1].x
+// CHECK-NEXT: 3: ++[B2.2]
+// CHECK-NEXT: 4: [B4.4].~A() (Implicit destructor)
// CHECK-NEXT: Preds (1): B3
// CHECK-NEXT: Succs (1): B4
// CHECK: [B3]
// ANALYZER-NEXT: 1: (CXXConstructExpr, [B3.2], A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
-// CHECK-NEXT: 4: [B4.4].~A() (Implicit destructor)
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B2
// CHECK: [B4]
// CHECK-NEXT: 8: [B4.6]
// CHECK-NEXT: 9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, int)
// CHECK: 10: [B4.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
-// CHECK-NEXT: T: for (...; [B4.10]; )
+// CHECK-NEXT: T: for (...; [B4.10]; ...)
// CHECK-NEXT: Preds (2): B2 B5
// CHECK-NEXT: Succs (2): B3 B1
// CHECK: [B5]
// CHECK: [B0 (EXIT)]
// CHECK-NEXT: Preds (1): B1
void test_for_implicit_scope() {
- for (A a; A b = a; )
+ for (A a; A b = a; ++b.x)
A c;
}
// CHECK-NEXT: Preds (2): B8 B10
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
+// CHECK-NEXT: 1: [B10.4].~A() (Implicit destructor)
// CHECK-NEXT: Preds (2): B3 B6
// CHECK-NEXT: Succs (1): B10
// CHECK: [B3]
// CHECK-NEXT: 2: A e;
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B9.2].~A() (Implicit destructor)
-// CHECK-NEXT: 5: [B10.4].~A() (Implicit destructor)
// CHECK-NEXT: Preds (1): B5
// CHECK-NEXT: Succs (1): B2
// CHECK: [B4]
// CHECK-NEXT: Preds (2): B1 B4
void test_for_jumps() {
A a;
- for (A b; A c = b; ) {
+ for (A b; A c = b;) {
A d;
if (UV) break;
if (UV) continue;
A f;
}
+// CHECK: [B9 (ENTRY)]
+// CHECK-NEXT: Succs (1): B8
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B7.4].~A() (Implicit destructor)
+// CHECK-NEXT: 2: [B8.2].~A() (Implicit destructor)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: [B5.4] ? [B3.3] : [B4.1]
+// CHECK-NEXT: 2: [B7.4].~A() (Implicit destructor)
+// CHECK-NEXT: Preds (2): B3 B4
+// CHECK-NEXT: Succs (1): B7
+// CHECK: [B3]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B3.1].x
+// CHECK-NEXT: 3: [B3.2]++
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: 0
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B5]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B5.1].x
+// CHECK-NEXT: 3: [B5.2] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT: 4: [B5.3] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: [B5.4] ? ... : ...
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (2): B3 B4
+// CHECK: [B6]
+// CHECK-NEXT: 1: 0
+// CHECK-NEXT: 2: (void)[B6.1] (CStyleCastExpr, ToVoid, void)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B7]
+// CHECK-NEXT: 1: a
+// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, NoOp, const A)
+// WARNINGS-NEXT: 3: [B7.2] (CXXConstructExpr, A)
+// ANALYZER-NEXT: 3: [B7.2] (CXXConstructExpr, [B7.4], A)
+// CHECK-NEXT: 4: A b = a;
+// CHECK-NEXT: 5: b
+// CHECK-NEXT: 6: [B7.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 7: [B7.6].operator int
+// CHECK-NEXT: 8: [B7.6]
+// CHECK-NEXT: 9: [B7.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 10: [B7.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: for (...; [B7.10]; ...)
+// CHECK-NEXT: Preds (2): B2 B8
+// CHECK-NEXT: Succs (2): B6 B1
+// CHECK: [B8]
+// WARNINGS-NEXT: 1: (CXXConstructExpr, A)
+// ANALYZER-NEXT: 1: (CXXConstructExpr, [B8.2], A)
+// CHECK-NEXT: 2: A a;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B7
+void test_for_inc_conditional() {
+ for (A a; A b = a; b.x ? b.x++ : 0)
+ (void)0;
+}
+
// CHECK: [B3 (ENTRY)]
// CHECK-NEXT: Succs (1): B0
// CHECK: [B1]
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B2.1].p
+// CHECK-NEXT: 3: [B4.4] (Lifetime ends)
// CHECK-NEXT: Preds (1): B3
// CHECK-NEXT: Succs (1): B4
// CHECK: [B3]
// CHECK-NEXT: 1: (CXXConstructExpr, A)
// CHECK-NEXT: 2: A c;
// CHECK-NEXT: 3: [B3.2] (Lifetime ends)
-// CHECK-NEXT: 4: [B4.4] (Lifetime ends)
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B2
// CHECK: [B4]
// CHECK-NEXT: 8: [B4.6]
// CHECK-NEXT: 9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, int)
// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
-// CHECK-NEXT: T: for (...; [B4.10]; )
+// CHECK-NEXT: T: for (...; [B4.10]; ...)
// CHECK-NEXT: Preds (2): B2 B5
// CHECK-NEXT: Succs (2): B3 B1
// CHECK: [B5]
// CHECK: [B0 (EXIT)]
// CHECK-NEXT: Preds (1): B1
void test_for_implicit_scope() {
- for (A a; A b = a;)
+ for (A a; A b = a; b.p)
A c;
}
// CHECK-NEXT: Preds (2): B8 B10
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
+// CHECK-NEXT: 1: [B10.4] (Lifetime ends)
// CHECK-NEXT: Preds (2): B3 B6
// CHECK-NEXT: Succs (1): B10
// CHECK: [B3]
// CHECK-NEXT: 2: A e;
// CHECK-NEXT: 3: [B3.2] (Lifetime ends)
// CHECK-NEXT: 4: [B9.2] (Lifetime ends)
-// CHECK-NEXT: 5: [B10.4] (Lifetime ends)
// CHECK-NEXT: Preds (1): B5
// CHECK-NEXT: Succs (1): B2
// CHECK: [B4]
// CHECK-NEXT: Preds (2): B1 B4
void test_for_jumps() {
A a;
- for (A b; A c = b;) {
+ for (A b; A c = b; ) {
A d;
if (UV)
break;
A f;
}
+// CHECK: [B9 (ENTRY)]
+// CHECK-NEXT: Succs (1): B8
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B7.4] (Lifetime ends)
+// CHECK-NEXT: 2: [B8.2] (Lifetime ends)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: [B5.4] ? [B3.3] : [B4.2]
+// CHECK-NEXT: 2: [B7.4] (Lifetime ends)
+// CHECK-NEXT: Preds (2): B3 B4
+// CHECK-NEXT: Succs (1): B7
+// CHECK: [B3]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B3.1].p
+// CHECK-NEXT: 3: [B3.2]++
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: 0
+// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, NullToPointer, int *)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B5]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B5.1].p
+// CHECK-NEXT: 3: [B5.2] (ImplicitCastExpr, LValueToRValue, int *)
+// CHECK-NEXT: 4: [B5.3] (ImplicitCastExpr, PointerToBoolean, _Bool)
+// CHECK-NEXT: T: [B5.4] ? ... : ...
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (2): B3 B4
+// CHECK: [B6]
+// CHECK-NEXT: 1: 0
+// CHECK-NEXT: 2: (void)[B6.1] (CStyleCastExpr, ToVoid, void)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B7]
+// CHECK-NEXT: 1: a
+// CHECK-NEXT: 2: [B7.1] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT: 3: [B7.2] (CXXConstructExpr, A)
+// CHECK-NEXT: 4: A b = a;
+// CHECK-NEXT: 5: b
+// CHECK-NEXT: 6: [B7.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 7: [B7.6].operator int
+// CHECK-NEXT: 8: [B7.6]
+// CHECK-NEXT: 9: [B7.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 10: [B7.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: for (...; [B7.10]; ...)
+// CHECK-NEXT: Preds (2): B2 B8
+// CHECK-NEXT: Succs (2): B6 B1
+// CHECK: [B8]
+// CHECK-NEXT: 1: (CXXConstructExpr, A)
+// CHECK-NEXT: 2: A a;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B7
+void test_for_inc_conditional() {
+ for (A a; A b = a; b.p ? b.p++ : 0)
+ (void)0;
+}
+
// CHECK: [B2 (ENTRY)]
// CHECK-NEXT: Succs (1): B1
// CHECK: [B1]
// CHECK: [B0 (EXIT)]
// CHECK-NEXT: Preds (1): B1
operator int() const { return 1; }
+ int *p;
};
int getX();
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B2.1].p
+// CHECK-NEXT: 3: [B4.5].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(b)
// CHECK-NEXT: Preds (1): B3
// CHECK-NEXT: Succs (1): B4
// CHECK: [B3]
// CHECK-NEXT: 3: A c;
// CHECK-NEXT: 4: [B3.3].~A() (Implicit destructor)
// CHECK-NEXT: 5: CFGScopeEnd(c)
-// CHECK-NEXT: 6: [B4.5].~A() (Implicit destructor)
-// CHECK-NEXT: 7: CFGScopeEnd(b)
// CHECK-NEXT: Preds (1): B4
// CHECK-NEXT: Succs (1): B2
// CHECK: [B4]
// CHECK-NEXT: 9: [B4.7]
// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, UserDefinedConversion, int)
// CHECK-NEXT: 11: [B4.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
-// CHECK-NEXT: T: for (...; [B4.11]; )
+// CHECK-NEXT: T: for (...; [B4.11]; ...)
// CHECK-NEXT: Preds (2): B2 B5
// CHECK-NEXT: Succs (2): B3 B1
// CHECK: [B5]
// CHECK: [B0 (EXIT)]
// CHECK-NEXT: Preds (1): B1
void test_for_implicit_scope() {
- for (A a; A b = a; )
+ for (A a; A b = a; b.p)
A c;
}
// CHECK-NEXT: Preds (2): B8 B10
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
+// CHECK-NEXT: 1: [B10.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(c)
// CHECK-NEXT: Preds (2): B3 B6
// CHECK-NEXT: Succs (1): B10
// CHECK: [B3]
// CHECK-NEXT: 3: [B3.2].~A() (Implicit destructor)
// CHECK-NEXT: 4: [B9.3].~A() (Implicit destructor)
// CHECK-NEXT: 5: CFGScopeEnd(d)
-// CHECK-NEXT: 6: [B10.5].~A() (Implicit destructor)
-// CHECK-NEXT: 7: CFGScopeEnd(c)
// CHECK-NEXT: Preds (1): B5
// CHECK-NEXT: Succs (1): B2
// CHECK: [B4]
}
// CHECK: [B9 (ENTRY)]
+// CHECK-NEXT: Succs (1): B8
+// CHECK: [B1]
+// CHECK-NEXT: 1: [B7.5].~A() (Implicit destructor)
+// CHECK-NEXT: 2: CFGScopeEnd(b)
+// CHECK-NEXT: 3: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT: 4: CFGScopeEnd(a)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B0
+// CHECK: [B2]
+// CHECK-NEXT: 1: [B5.4] ? [B3.3] : [B4.2]
+// CHECK-NEXT: 2: [B7.5].~A() (Implicit destructor)
+// CHECK-NEXT: 3: CFGScopeEnd(b)
+// CHECK-NEXT: Preds (2): B3 B4
+// CHECK-NEXT: Succs (1): B7
+// CHECK: [B3]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B3.1].p
+// CHECK-NEXT: 3: [B3.2]++
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B4]
+// CHECK-NEXT: 1: 0
+// CHECK-NEXT: 2: [B4.1] (ImplicitCastExpr, NullToPointer, int *)
+// CHECK-NEXT: Preds (1): B5
+// CHECK-NEXT: Succs (1): B2
+// CHECK: [B5]
+// CHECK-NEXT: 1: b
+// CHECK-NEXT: 2: [B5.1].p
+// CHECK-NEXT: 3: [B5.2] (ImplicitCastExpr, LValueToRValue, int *)
+// CHECK-NEXT: 4: [B5.3] (ImplicitCastExpr, PointerToBoolean, _Bool)
+// CHECK-NEXT: T: [B5.4] ? ... : ...
+// CHECK-NEXT: Preds (1): B6
+// CHECK-NEXT: Succs (2): B3 B4
+// CHECK: [B6]
+// CHECK-NEXT: 1: 0
+// CHECK-NEXT: 2: (void)[B6.1] (CStyleCastExpr, ToVoid, void)
+// CHECK-NEXT: Preds (1): B7
+// CHECK-NEXT: Succs (1): B5
+// CHECK: [B7]
+// CHECK-NEXT: 1: CFGScopeBegin(b)
+// CHECK-NEXT: 2: a
+// CHECK-NEXT: 3: [B7.2] (ImplicitCastExpr, NoOp, const A)
+// CHECK-NEXT: 4: [B7.3] (CXXConstructExpr, [B7.5], A)
+// CHECK-NEXT: 5: A b = a;
+// CHECK-NEXT: 6: b
+// CHECK-NEXT: 7: [B7.6] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT: 8: [B7.7].operator int
+// CHECK-NEXT: 9: [B7.7]
+// CHECK-NEXT: 10: [B7.9] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK-NEXT: 11: [B7.10] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT: T: for (...; [B7.11]; ...)
+// CHECK-NEXT: Preds (2): B2 B8
+// CHECK-NEXT: Succs (2): B6 B1
+// CHECK: [B8]
+// CHECK-NEXT: 1: CFGScopeBegin(a)
+// CHECK-NEXT: 2: (CXXConstructExpr, [B8.3], A)
+// CHECK-NEXT: 3: A a;
+// CHECK-NEXT: Preds (1): B9
+// CHECK-NEXT: Succs (1): B7
+void test_for_inc_conditional() {
+ for (A a; A b = a; b.p ? b.p++ : 0)
+ (void)0;
+}
+
+// CHECK: [B9 (ENTRY)]
// CHECK-NEXT: Succs (1): B7
// CHECK: [B1]
// CHECK-NEXT: l1: