[clang] [analyzer] Do list initialization for CXXNewExpr with initializer list arg (PR #127702)

Michael Flanders via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 20 07:36:48 PST 2025


================
@@ -254,6 +254,200 @@ void foo() {
 }
 } // namespace CXX17_aggregate_construction
 
+namespace newexpr_init_list_initialization {
+struct S {
+  int foo;
+  int bar;
+};
+void none_designated() {
+  S *s = new S{13,1};
+  clang_analyzer_eval(13 == s->foo); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == s->bar); // expected-warning{{TRUE}}
+  delete s;
+}
+void none_designated_swapped() {
+  S *s = new S{1,13};
+  clang_analyzer_eval(1 == s->foo); // expected-warning{{TRUE}}
+  clang_analyzer_eval(13 == s->bar); // expected-warning{{TRUE}}
+  delete s;
+}
+void one_designated_one_not() {
+  S *s = new S{ 1, .bar = 13 };
+  clang_analyzer_eval(1 == s->foo); // expected-warning{{TRUE}}
+  clang_analyzer_eval(13 == s->bar); // expected-warning{{TRUE}}
+  delete s;
+}
+void all_designated() {
+  S *s = new S{
+      .foo = 13,
+      .bar = 1,
+  };
+  clang_analyzer_eval(13 == s->foo); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == s->bar); // expected-warning{{TRUE}}
+  delete s;
+}
+void non_designated_array_of_aggr_struct() {
+  S *s = new S[2] { {1, 2}, {3, 4} };
+  clang_analyzer_eval(1 == s[0].foo); // expected-warning{{TRUE}}
+  clang_analyzer_eval(2 == s[0].bar); // expected-warning{{TRUE}}
+  clang_analyzer_eval(3 == s[1].foo); // expected-warning{{TRUE}}
+  clang_analyzer_eval(4 == s[1].bar); // expected-warning{{TRUE}}
+  delete[] s;
+}
+
+struct WithGaps {
+  int foo;
+  int bar;
+  int baz;
+};
+void out_of_order_designated_initializers_with_gaps() {
+  WithGaps *s = new WithGaps{
+    .foo = 13,
+    .baz = 1,
+  };
+  clang_analyzer_eval(13 == s->foo); // expected-warning{{TRUE}}
+  clang_analyzer_eval(0 == s->bar); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == s->baz); // expected-warning{{TRUE}}
+  delete s;
+}
+
+// https://eel.is/c++draft/dcl.init.aggr#note-6:
+// Static data members, non-static data members of anonymous
+// union members, and unnamed bit-fields are not considered
+// elements of the aggregate.
+struct NonConsideredFields {
+  int i;
+  static int s;
+  int j;
+  int :17;
+  int k;
+};
+void considered_fields_initd() {
+  auto S = new NonConsideredFields { 1, 2, 3 };
+  clang_analyzer_eval(1 == S->i); // expected-warning{{TRUE}}
+  clang_analyzer_eval(2 == S->j); // expected-warning{{TRUE}}
+  clang_analyzer_eval(3 == S->k); // expected-warning{{TRUE}}
+  delete S;
+}
+
+enum Enum : int {
+};
+// FIXME: uncomment when CSA supports list init of enums
+void list_init_enum() {
+  // Enum *E = new Enum{53};
+  // clang_analyzer_eval(53 == *E); // should be TRUE
+  // delete E;
+}
----------------
Flandini wrote:

When I uncomment those lines, the test fails and then all the other tests after it fail. Looks like `-std=c++11` causes this test to fail with:

```
clang++: warning: argument unused during compilation: '-S' [-Wunused-command-line-argument]
<source>:4:22: error: cannot initialize a new value of type 'Enum' with an rvalue of type 'int'
    4 |   Enum *E = new Enum{53};
      |                      ^~
1 error generated.
Compiler returned: 1
```
https://compiler-explorer.com/z/hj7qdehs3

I wrongly assumed it just wasn't supported then, but I guess this is different in C++11 vs later editions. Seems like it is clang/Sema warning on this https://godbolt.org/z/d7xEec8Ec. 

So this test case would need to be executed only for some version after C++11 then. I don't currently know which version makes this possible, but I'll look.

https://github.com/llvm/llvm-project/pull/127702


More information about the cfe-commits mailing list