From 8f670d5b6d8f39bf9bf1d142dacef3afaed6d70b Mon Sep 17 00:00:00 2001 From: James Y Knight Date: Sun, 31 Jan 2021 18:42:39 -0500 Subject: [PATCH] CFG: Create scope for non-compound range-for body. Previously, it was omitting the destructor call from the CFG, which could result in incorrect diagnostics. --- clang/lib/Analysis/CFG.cpp | 6 +++ clang/test/Analysis/auto-obj-dtors-cfg-output.cpp | 53 +++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index edc86c4..5644588 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -4475,8 +4475,14 @@ CFGBlock *CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) { // Add implicit scope and dtors for loop variable. addLocalScopeAndDtors(S->getLoopVarStmt()); + // If body is not a compound statement create implicit scope + // and add destructors. + if (!isa(S->getBody())) + addLocalScopeAndDtors(S->getBody()); + // Populate a new block to contain the loop body and loop variable. addStmt(S->getBody()); + if (badCFG) return nullptr; CFGBlock *LoopVarStmtBlock = addStmt(S->getLoopVarStmt()); diff --git a/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp b/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp index 5b98dea..8e396bd 100644 --- a/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp +++ b/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp @@ -1075,6 +1075,59 @@ void test_for_implicit_scope() { A c; } +// CHECK-LABEL: void test_for_range_implicit_scope() +// CHECK: [B5 (ENTRY)] +// CHECK-NEXT: Succs (1): B4 +// CHECK: [B1] +// CHECK-NEXT: 1: __begin1 +// CHECK-NEXT: 2: [B1.1] (ImplicitCastExpr, LValueToRValue, int *) +// CHECK-NEXT: 3: __end1 +// CHECK-NEXT: 4: [B1.3] (ImplicitCastExpr, LValueToRValue, int *) +// CHECK-NEXT: 5: [B1.2] != [B1.4] +// CHECK-NEXT: T: for (int n : [B4.2]) +// CHECK-NEXT:[B3.7] +// CHECK-NEXT: Preds (2): B2 B4 +// CHECK-NEXT: Succs (2): B3 B0 +// CHECK: [B2] +// CHECK-NEXT: 1: __begin1 +// CHECK-NEXT: 2: ++[B2.1] +// CHECK-NEXT: Preds (1): B3 +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B3] +// CHECK-NEXT: 1: __begin1 +// CHECK-NEXT: 2: [B3.1] (ImplicitCastExpr, LValueToRValue, int *) +// CHECK-NEXT: 3: *[B3.2] +// CHECK-NEXT: 4: [B3.3] (ImplicitCastExpr, LValueToRValue, int) +// CHECK-NEXT: 5: int n = *__begin1; +// WARNINGS-NEXT: 6: (CXXConstructExpr, class A) +// ANALYZER-NEXT: 6: (CXXConstructExpr, [B3.7], class A) +// CHECK-NEXT: 7: A c; +// CHECK-NEXT: 8: [B3.7].~A() (Implicit destructor) +// CHECK-NEXT: Preds (1): B1 +// CHECK-NEXT: Succs (1): B2 +// CHECK: [B4] +// CHECK-NEXT: 1: int nums[4]; +// CHECK-NEXT: 2: nums +// CHECK-NEXT: 3: auto &&__range1 = nums; +// CHECK-NEXT: 4: __range1 +// CHECK-NEXT: 5: [B4.4] (ImplicitCastExpr, ArrayToPointerDecay, int *) +// CHECK-NEXT: 6: 4L +// CHECK-NEXT: 7: [B4.5] + [B4.6] +// CHECK-NEXT: 8: auto __end1 = __range1 + 4L; +// CHECK-NEXT: 9: __range1 +// CHECK-NEXT: 10: [B4.9] (ImplicitCastExpr, ArrayToPointerDecay, int *) +// CHECK-NEXT: 11: auto __begin1 = __range1; +// CHECK-NEXT: Preds (1): B5 +// CHECK-NEXT: Succs (1): B1 +// CHECK: [B0 (EXIT)] +// CHECK-NEXT: Preds (1): B1 +void test_for_range_implicit_scope() { + int nums[4]; + for (int n : nums) + A c; +} + + // CHECK: [B12 (ENTRY)] // CHECK-NEXT: Succs (1): B11 // CHECK: [B1] -- 2.7.4