llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-static-analyzer-1

@llvm/pr-subscribers-clang-analysis

Author: Taufiq Rahman (Inconnu08)

<details>
<summary>Changes</summary>

The CFG builder adds statements in reverse execution order. Add the range-for 
end declaration before the begin declaration so that the resulting CFG 
initializes begin before end.

Add a regression covering distinct iterator and sentinel types with non-trivial 
destructors, checking initialization and reverse destruction order with rich 
constructors both enabled and disabled. Update the affected CFG dump 
expectations.

Validation: all 28 selected CFG and range-for Analysis tests passed. The new 
regression also fails with the original implementation.

Fixes #<!-- -->233806 

---
Full diff: https://github.com/llvm/llvm-project/pull/234467.diff


4 Files Affected:

- (modified) clang/lib/Analysis/CFG.cpp (+1-1) 
- (modified) clang/test/Analysis/auto-obj-dtors-cfg-output.cpp (+6-6) 
- (added) clang/test/Analysis/cfg-range-for-init-order.cpp (+35) 
- (modified) clang/test/Analysis/scopes-cfg-output.cpp (+12-10) 


``````````diff
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 556e08f5c1df80..63c8d62c5808e1 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -4989,8 +4989,8 @@ CFGBlock 
*CFGBuilder::VisitCXXForRangeStmt(CXXForRangeStmt *S) {
 
   // Add the initialization statements.
   Block = createBlock();
-  addStmt(S->getBeginStmt());
   addStmt(S->getEndStmt());
+  addStmt(S->getBeginStmt());
   CFGBlock *Head = addStmt(S->getRangeStmt());
   if (S->getInit())
     Head = addStmt(S->getInit());
diff --git a/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp 
b/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp
index 96b9a5508cc084..4a39b70f8ab335 100644
--- a/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp
+++ b/clang/test/Analysis/auto-obj-dtors-cfg-output.cpp
@@ -1117,12 +1117,12 @@ void test_for_implicit_scope() {
 // CHECK-NEXT:   3: auto &&__range1 = nums;
 // CHECK-NEXT:   4: __range1
 // CHECK-NEXT:   5: [B4.4] (ImplicitCastExpr, ArrayToPointerDecay, int *)
-// CHECK-NEXT:   6: 4{{L*}}
-// CHECK-NEXT:   7: [B4.5] + [B4.6]
-// CHECK-NEXT:   8: auto __end1 = __range1 + 4{{L*}};
-// CHECK-NEXT:   9: __range1
-// CHECK-NEXT:  10: [B4.9] (ImplicitCastExpr, ArrayToPointerDecay, int *)
-// CHECK-NEXT:  11: auto __begin1 = __range1;
+// CHECK-NEXT:   6: auto __begin1 = __range1;
+// CHECK-NEXT:   7: __range1
+// CHECK-NEXT:   8: [B4.7] (ImplicitCastExpr, ArrayToPointerDecay, int *)
+// CHECK-NEXT:   9: 4{{L*}}
+// CHECK-NEXT:  10: [B4.8] + [B4.9]
+// CHECK-NEXT:  11: auto __end1 = __range1 + 4{{L*}};
 // CHECK-NEXT:   Preds (1): B5
 // CHECK-NEXT:   Succs (1): B1
 // CHECK:      [B0 (EXIT)]
diff --git a/clang/test/Analysis/cfg-range-for-init-order.cpp 
b/clang/test/Analysis/cfg-range-for-init-order.cpp
new file mode 100644
index 00000000000000..2bbca5c1fd83a7
--- /dev/null
+++ b/clang/test/Analysis/cfg-range-for-init-order.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=debug.DumpCFG 
-analyzer-config cfg-rich-constructors=false %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
+// RUN: %clang_analyze_cc1 -std=c++17 -analyzer-checker=debug.DumpCFG 
-analyzer-config cfg-rich-constructors=true %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
+
+struct Begin {
+  ~Begin();
+};
+
+struct End {
+  ~End();
+};
+
+bool operator!=(const Begin &, const End &);
+void operator++(Begin &);
+int &operator*(const Begin &);
+
+struct Range {
+  Begin begin();
+  End end();
+};
+
+// The cleanup block appears before the initialization block in the dump.
+// Iterators must initialize begin before end and be destroyed in reverse 
order.
+//
+// CHECK-LABEL: void range_for_init_order(
+// CHECK: .~End() (Implicit destructor)
+// CHECK: .~Begin() (Implicit destructor)
+// CHECK: auto &&__range{{[0-9]*}} = range;
+// CHECK: auto __begin{{[0-9]*}} = {{.*}}.begin();
+// CHECK: auto __end{{[0-9]*}} = {{.*}}.end();
+void range_for_init_order(Range range) {
+  for (int &value : range)
+    (void)value;
+}
\ No newline at end of file
diff --git a/clang/test/Analysis/scopes-cfg-output.cpp 
b/clang/test/Analysis/scopes-cfg-output.cpp
index ac8ff1179a9945..13c6c42555ffae 100644
--- a/clang/test/Analysis/scopes-cfg-output.cpp
+++ b/clang/test/Analysis/scopes-cfg-output.cpp
@@ -890,7 +890,7 @@ void test_for_compound_and_break() {
 // CHECK-NEXT:   3: __end1
 // CHECK-NEXT:   4: [B2.3] (ImplicitCastExpr, LValueToRValue, A *)
 // CHECK-NEXT:   5: [B2.2] != [B2.4]
-// CHECK-NEXT:   T: for (auto &i : [B5.4])
+// CHECK-NEXT:   T: for (auto &i : [B5.5])
 // CHECK:         [B4.11];
 // CHECK:        Preds (2): B3 B5
 // CHECK-NEXT:   Succs (2): B4 B1
@@ -918,17 +918,19 @@ void test_for_compound_and_break() {
 // CHECK-NEXT:   1: CFGScopeBegin(a)
 // CHECK-NEXT:   2:  (CXXConstructExpr, [B5.3], A[10])
 // CHECK-NEXT:   3: A a[10];
-// CHECK-NEXT:   4: a
-// CHECK-NEXT:   5: auto &&__range1 = a;
-// CHECK-NEXT:   6: CFGScopeBegin(__end1)
-// CHECK-NEXT:   7: __range1
-// CHECK-NEXT:   8: [B5.7] (ImplicitCastExpr, ArrayToPointerDecay, A *)
-// CHECK-NEXT:   9: 10
-// CHECK-NEXT:  10: [B5.8] + [B5.9]
-// CHECK-NEXT:  11: auto __end1 = __range1 + 10
+// CHECK-NEXT:   4: CFGScopeBegin(__range1)
+// CHECK-NEXT:   5: a
+// CHECK-NEXT:   6: auto &&__range1 = a;
+// CHECK-NEXT:   7: CFGScopeBegin(__begin1)
+// CHECK-NEXT:   8: __range1
+// CHECK-NEXT:   9: [B5.8] (ImplicitCastExpr, ArrayToPointerDecay, A *)
+// CHECK-NEXT:  10: auto __begin1 = __range1;
+// CHECK-NEXT:  11: CFGScopeBegin(__end1)
 // CHECK-NEXT:  12: __range1
 // CHECK-NEXT:  13: [B5.12] (ImplicitCastExpr, ArrayToPointerDecay, A *)
-// CHECK-NEXT:  14: auto __begin1 = __range1;
+// CHECK-NEXT:  14: 10{{L*}}
+// CHECK-NEXT:  15: [B5.13] + [B5.14]
+// CHECK-NEXT:  16: auto __end1 = __range1 + 10{{L*}};
 // CHECK-NEXT:   Preds (1): B6
 // CHECK-NEXT:   Succs (1): B2
 // CHECK:      [B0 (EXIT)]

``````````

</details>


https://github.com/llvm/llvm-project/pull/234467
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to