[clang] [analyzer] Add more C++ list initializer tests and regroup (PR #129182)

via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 27 21:07:03 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Michael Flanders (Flandini)

<details>
<summary>Changes</summary>

Related to #<!-- -->127702.

I figured that if I change list initialization like mentioned in #<!-- -->127702, then I would want these tests anyways, so I am adding them first. This adds more test coverage of C++ list initialization and aggregate initialization. I tried to make sure there is at least one basic test case for each paragraph/note of the list initialization and aggregate initialization sections, C++11 through C++20.

I grouped all of the C++ list-initialization-specifics tests into this new file `list-initialization.cpp`. `list-initialization.cpp` is separated into a 'common to all C++ standard editions' section and a 'C++17 and above section'. I figure this is fine since it still allows coverage for all of the list initialization and aggregate initialization sections, C++11 through C++20 at least.

This does not include the tests from #<!-- -->127702. If this is approved, I will merge the tests from this and #<!-- -->127702 into whichever gets merged last. This includes a test case for a related issue #<!-- -->54910.

There are `FIXME`'s for each test case that should have different behavior than current main branch. I checked all of these and checked them against normal compilation.

Happy to add more test cases if anyone can think of any more fun tests like #<!-- -->54910.

---

Patch is 39.60 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/129182.diff


3 Files Affected:

- (modified) clang/test/Analysis/initialization.cpp (-154) 
- (modified) clang/test/Analysis/initializer.cpp (-79) 
- (added) clang/test/Analysis/list-initialization.cpp (+910) 


``````````diff
diff --git a/clang/test/Analysis/initialization.cpp b/clang/test/Analysis/initialization.cpp
index e624ef5bae9e9..164011f19c5c3 100644
--- a/clang/test/Analysis/initialization.cpp
+++ b/clang/test/Analysis/initialization.cpp
@@ -4,105 +4,6 @@ template <typename T>
 void clang_analyzer_dump(T x);
 void clang_analyzer_eval(int);
 
-struct S {
-  int a = 3;
-};
-S const sarr[2] = {};
-void definit() {
-  int i = 1;
-  // FIXME: Should recognize that it is 3.
-  clang_analyzer_eval(sarr[i].a); // expected-warning{{UNKNOWN}}
-}
-
-int const glob_arr1[3] = {};
-void glob_array_index1() {
-  clang_analyzer_eval(glob_arr1[0] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr1[1] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr1[2] == 0); // expected-warning{{TRUE}}
-}
-
-void glob_invalid_index1() {
-  const int *ptr = glob_arr1;
-  int idx = -42;
-  auto x = ptr[idx]; // expected-warning{{garbage or undefined}}
-}
-
-void glob_symbolic_index1(int idx) {
-  clang_analyzer_dump(glob_arr1[idx]); // expected-warning{{Unknown}}
-}
-
-int const glob_arr2[4] = {1, 2};
-void glob_ptr_index1() {
-  int const *ptr = glob_arr2;
-  clang_analyzer_eval(ptr[0] == 1); // expected-warning{{TRUE}}
-  clang_analyzer_eval(ptr[1] == 2); // expected-warning{{TRUE}}
-  clang_analyzer_eval(ptr[2] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(ptr[3] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(ptr[4] == 0); // expected-warning{{UNDEFINED}}
-}
-
-void glob_invalid_index2() {
-  const int *ptr = glob_arr2;
-  int idx = 42;
-  auto x = ptr[idx]; // expected-warning{{garbage or undefined}}
-}
-
-const float glob_arr3[] = {
-    0.0000, 0.0235, 0.0470, 0.0706, 0.0941, 0.1176};
-float no_warn_garbage_value() {
-  return glob_arr3[0]; // no-warning (garbage or undefined)
-}
-
-int const glob_arr4[4][2] = {};
-void glob_array_index2() {
-  clang_analyzer_eval(glob_arr4[0][0] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr4[1][0] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr4[1][1] == 0); // expected-warning{{TRUE}}
-}
-
-void glob_invalid_index3() {
-  int idx = -42;
-  auto x = glob_arr4[1][idx]; // expected-warning{{garbage or undefined}}
-}
-
-void glob_invalid_index4() {
-  const int *ptr = glob_arr4[1];
-  int idx = -42;
-  auto x = ptr[idx]; // expected-warning{{garbage or undefined}}
-}
-
-int const glob_arr5[4][2] = {{1}, 3, 4, 5};
-void glob_array_index3() {
-  clang_analyzer_eval(glob_arr5[0][0] == 1); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr5[0][1] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr5[1][0] == 3); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr5[1][1] == 4); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr5[2][0] == 5); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr5[2][1] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr5[3][0] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr5[3][1] == 0); // expected-warning{{TRUE}}
-}
-
-void glob_ptr_index2() {
-  int const *ptr = glob_arr5[1];
-  clang_analyzer_eval(ptr[0] == 3); // expected-warning{{TRUE}}
-  clang_analyzer_eval(ptr[1] == 4); // expected-warning{{TRUE}}
-  clang_analyzer_eval(ptr[2] == 5); // expected-warning{{UNDEFINED}}
-  clang_analyzer_eval(ptr[3] == 0); // expected-warning{{UNDEFINED}}
-  clang_analyzer_eval(ptr[4] == 0); // expected-warning{{UNDEFINED}}
-}
-
-void glob_invalid_index5() {
-  int idx = -42;
-  auto x = glob_arr5[1][idx]; // expected-warning{{garbage or undefined}}
-}
-
-void glob_invalid_index6() {
-  int const *ptr = &glob_arr5[1][0];
-  int idx = 42;
-  auto x = ptr[idx]; // expected-warning{{garbage or undefined}}
-}
-
 extern const int glob_arr_no_init[10];
 void glob_array_index4() {
   clang_analyzer_eval(glob_arr_no_init[2]); // expected-warning{{UNKNOWN}}
@@ -147,26 +48,6 @@ void glob_invalid_index8() {
   auto x = ptr[idx]; // expected-warning{{garbage or undefined}}
 }
 
-char const glob_arr7[5] = {"123"};
-void glob_array_index6() {
-  clang_analyzer_eval(glob_arr7[0] == '1');  // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr7[1] == '2');  // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr7[2] == '3');  // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr7[3] == '\0'); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr7[4] == '\0'); // expected-warning{{TRUE}}
-}
-
-void glob_invalid_index9() {
-  int idx = -42;
-  auto x = glob_arr7[idx]; // expected-warning{{garbage or undefined}}
-}
-
-void glob_invalid_index10() {
-  const char *ptr = glob_arr7;
-  int idx = 42;
-  auto x = ptr[idx]; // expected-warning{{garbage or undefined}}
-}
-
 char const *const glob_ptr8 = "123";
 void glob_ptr_index4() {
   clang_analyzer_eval(glob_ptr8[0] == '1');  // expected-warning{{TRUE}}
@@ -221,38 +102,3 @@ void glob_ptr_index8() {
   clang_analyzer_eval(glob_ptr12[2] == 'c');  // expected-warning{{TRUE}}
   clang_analyzer_eval(glob_ptr12[3] == '\0'); // expected-warning{{TRUE}}
 }
-
-typedef int Int;
-typedef Int const CInt;
-typedef CInt Arr[2];
-typedef Arr Arr2[4];
-Arr2 glob_arr8 = {{1}, 3, 4, 5}; // const int[4][2]
-void glob_array_typedef1() {
-  clang_analyzer_eval(glob_arr8[0][0] == 1); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr8[0][1] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr8[1][0] == 3); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr8[1][1] == 4); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr8[2][0] == 5); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr8[2][1] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr8[3][0] == 0); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr8[3][1] == 0); // expected-warning{{TRUE}}
-}
-
-const int glob_arr9[2][4] = {{(1), 2, ((3)), 4}, 5, 6, (((7)))};
-void glob_array_parentheses1() {
-  clang_analyzer_eval(glob_arr9[0][0] == 1); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr9[0][1] == 2); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr9[0][2] == 3); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr9[0][3] == 4); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr9[1][0] == 5); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr9[1][1] == 6); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr9[1][2] == 7); // expected-warning{{TRUE}}
-  clang_analyzer_eval(glob_arr9[1][3] == 0); // expected-warning{{TRUE}}
-}
-
-enum class E {};
-const E glob[] = {{}};
-void initlistWithinInitlist() {
-  // no-crash
-  clang_analyzer_dump(glob[0]); // expected-warning-re {{reg_${{[0-9]+}}<enum E Element{glob,0 S64b,enum E}>}}
-}
diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp
index f50afff25d245..2dfb878fa057e 100644
--- a/clang/test/Analysis/initializer.cpp
+++ b/clang/test/Analysis/initializer.cpp
@@ -197,85 +197,6 @@ struct C {
 };
 }
 
-namespace CXX_initializer_lists {
-struct C {
-  C(std::initializer_list<int *> list);
-};
-void testPointerEscapeIntoLists() {
-  C empty{}; // no-crash
-
-  // Do not warn that 'x' leaks. It might have been deleted by
-  // the destructor of 'c'.
-  int *x = new int;
-  C c{x}; // no-warning
-}
-
-void testPassListsWithExplicitConstructors() {
-  (void)(std::initializer_list<int>){12}; // no-crash
-}
-}
-
-namespace CXX17_aggregate_construction {
-struct A {
-  A();
-};
-
-struct B: public A {
-};
-
-struct C: public B {
-};
-
-struct D: public virtual A {
-};
-
-// In C++17, classes B and C are aggregates, so they will be constructed
-// without actually calling their trivial constructor. Used to crash.
-void foo() {
-  B b = {}; // no-crash
-  const B &bl = {}; // no-crash
-  B &&br = {}; // no-crash
-
-  C c = {}; // no-crash
-  const C &cl = {}; // no-crash
-  C &&cr = {}; // no-crash
-
-  D d = {}; // no-crash
-
-#if __cplusplus >= 201703L
-  C cd = {{}}; // no-crash
-  const C &cdl = {{}}; // no-crash
-  C &&cdr = {{}}; // no-crash
-
-  const B &bll = {{}}; // no-crash
-  const B &bcl = C({{}}); // no-crash
-  B &&bcr = C({{}}); // no-crash
-#endif
-}
-} // namespace CXX17_aggregate_construction
-
-namespace CXX17_transparent_init_list_exprs {
-class A {};
-
-class B: private A {};
-
-B boo();
-void foo1() {
-  B b { boo() }; // no-crash
-}
-
-class C: virtual public A {};
-
-C coo();
-void foo2() {
-  C c { coo() }; // no-crash
-}
-
-B foo_recursive() {
-  B b { foo_recursive() };
-}
-} // namespace CXX17_transparent_init_list_exprs
-
 namespace skip_vbase_initializer_side_effects {
 int glob;
 struct S {
diff --git a/clang/test/Analysis/list-initialization.cpp b/clang/test/Analysis/list-initialization.cpp
new file mode 100644
index 0000000000000..2c68b437411ec
--- /dev/null
+++ b/clang/test/Analysis/list-initialization.cpp
@@ -0,0 +1,910 @@
+// RUN: %clang_analyze_cc1 -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++11
+// RUN: %clang_analyze_cc1 -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++17
+
+template <typename T>
+void clang_analyzer_dump(T x);
+void clang_analyzer_eval(bool);
+
+#include "Inputs/system-header-simulator-cxx.h"
+
+// in C++14 and below, class types with bases are not aggregates, but they
+// are in C++17 and above
+#if __cplusplus >= 201703L
+namespace CXX17_base_class_aggregates {
+struct A {
+  A();
+};
+
+struct B: public A {
+};
+
+struct C: public B {
+};
+
+struct D: public virtual A {
+};
+
+// In C++17, classes B and C are aggregates, so they will be constructed
+// without actually calling their trivial constructor. Used to crash.
+void foo() {
+  B b = {}; // no-crash
+  const B &bl = {}; // no-crash
+  B &&br = {}; // no-crash
+
+  C c = {}; // no-crash
+  const C &cl = {}; // no-crash
+  C &&cr = {}; // no-crash
+
+  D d = {}; // no-crash
+
+
+  C cd = {{}}; // no-crash
+  const C &cdl = {{}}; // no-crash
+  C &&cdr = {{}}; // no-crash
+
+  const B &bll = {{}}; // no-crash
+  const B &bcl = C({{}}); // no-crash
+  B &&bcr = C({{}}); // no-crash
+}
+
+struct S1 {
+  int one;
+  int two;
+};
+struct S2 {
+  int three;
+};
+struct T : public S1, public S2 {
+  int four;
+  int five;
+};
+void fields_init_in_order() {
+  T direct{1,2,3,4};
+  clang_analyzer_eval(direct.one == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(direct.two == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(direct.three == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(direct.four == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(direct.five == 0); // expected-warning{{TRUE}}
+
+  T copy = {1,2,3,4};
+  clang_analyzer_eval(copy.one == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(copy.two == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(copy.three == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(copy.four == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(copy.five == 0); // expected-warning{{TRUE}}
+
+  T *ptr = new T{1,2,3,4};
+  clang_analyzer_eval(ptr->one == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr->two == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr->three == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr->four == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(ptr->five == 0); // expected-warning{{TRUE}}
+  delete ptr;
+
+  T slot;
+  T *place = new (&slot) T{1,2,3,4};
+  clang_analyzer_eval(place->one == 1); // expected-warning{{TRUE}}
+  clang_analyzer_eval(place->two == 2); // expected-warning{{TRUE}}
+  clang_analyzer_eval(place->three == 3); // expected-warning{{TRUE}}
+  clang_analyzer_eval(place->four == 4); // expected-warning{{TRUE}}
+  clang_analyzer_eval(place->five == 0); // expected-warning{{TRUE}}
+}
+
+struct DefaultOne {
+  int one = 1;
+};
+struct DefaultTwo {
+  int two = 2;
+};
+struct Deriver : public DefaultOne, public DefaultTwo {
+};
+void empty_lists_bases() {
+  Deriver direct{{}, {}};
+  Deriver copy = {{}, {}};
+  Deriver *ptr = new Deriver{{},{}};
+
+  Deriver slot;
+  Deriver *place = new (&slot) Deriver{{},{}};
+
+  clang_analyzer_eval(1 == direct.one); // expected-warning{{TRUE}}
+  clang_analyzer_eval(2 == direct.two); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == copy.one); // expected-warning{{TRUE}}
+  clang_analyzer_eval(2 == copy.two); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == ptr->one); // expected-warning{{TRUE}}
+  clang_analyzer_eval(2 == ptr->two); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == place->one); // expected-warning{{TRUE}}
+  clang_analyzer_eval(2 == place->two); // expected-warning{{TRUE}}
+
+  delete ptr;
+}
+} // namespace CXX17_base_class_aggregates
+
+// C++14 and below don't allow list initialization of enums, C++17 and above do
+namespace CXX17_enum_list_init {
+
+enum class E {};
+const E glob[] = {{}};
+void initlistWithinInitlist() {
+  // no-crash
+  clang_analyzer_dump(glob[0]); // expected-warning-re {{reg_${{[0-9]+}}<enum CXX17_enum_list_init::E Element{glob,0 S64b,enum CXX17_enum_list_init::E}>}}
+}
+
+enum UnderlyingStorage : int {
+};
+void init_value() {
+  // No copy list initialization, only direct list init of enum with underlying type
+  // is allowed
+  UnderlyingStorage direct{1};
+  UnderlyingStorage *ptr = new UnderlyingStorage{1};
+  UnderlyingStorage slot;
+  UnderlyingStorage *place = new (&slot) UnderlyingStorage{1};
+  clang_analyzer_eval(1 == direct); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == *ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == *place); // expected-warning{{TRUE}}
+}
+void empty_list_init() {
+  UnderlyingStorage direct{};
+  UnderlyingStorage *ptr = new UnderlyingStorage{};
+  UnderlyingStorage slot;
+  UnderlyingStorage *place = new (&slot) UnderlyingStorage{};
+  clang_analyzer_eval(0 == direct); // expected-warning{{TRUE}}
+  clang_analyzer_eval(0 == *ptr); // expected-warning{{TRUE}}
+  clang_analyzer_eval(0 == *place); // expected-warning{{TRUE}}
+}
+} // namespace CXX17_enum_list_init
+
+namespace CXX17_anonymous_union_aggregate_member {
+struct S {
+  int x;
+  union {
+    int a;
+    int b;
+  };
+  int y;
+};
+void no_designated_clause() {
+  S direct{1,2};
+  clang_analyzer_eval(1 == direct.x); // expected-warning{{TRUE}}
+  // FIXME: should be TRUE
+  clang_analyzer_eval(2 == direct.y); // expected-warning{{FALSE}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(direct.a); // expected-warning{{UNKNOWN}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(direct.b); // expected-warning{{UNKNOWN}}
+
+  S copy = {3,4};
+  clang_analyzer_eval(3 == copy.x); // expected-warning{{TRUE}}
+  // FIXME: should be TRUE
+  clang_analyzer_eval(4 == copy.y); // expected-warning{{FALSE}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(copy.a); // expected-warning{{UNKNOWN}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(copy.b); // expected-warning{{UNKNOWN}}
+
+  S *ptr = new S{5, 6};
+  clang_analyzer_eval(5 == ptr->x); // expected-warning{{TRUE}}
+  // FIXME: should be TRUE
+  clang_analyzer_eval(6 == ptr->y); // expected-warning{{FALSE}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(ptr->a); // expected-warning{{UNKNOWN}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(ptr->b); // expected-warning{{UNKNOWN}}
+
+  S slot;
+  S *place = new (&slot) S{7,8};
+  clang_analyzer_eval(7 == place->x); // expected-warning{{TRUE}}
+  // FIXME: should be TRUE
+  clang_analyzer_eval(8 == place->y); // expected-warning{{FALSE}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(place->a); // expected-warning{{UNKNOWN}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(place->b); // expected-warning{{UNKNOWN}}
+
+  delete ptr;
+}
+void designated_clause() {
+  S direct{.a = 14};
+  clang_analyzer_eval(0 == direct.x); // expected-warning{{TRUE}}
+  clang_analyzer_eval(0 == direct.y); // expected-warning{{TRUE}}
+  // FIXME: should be TRUE
+  clang_analyzer_eval(14 == direct.a); // expected-warning{{UNKNOWN}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(direct.b); // expected-warning{{UNKNOWN}}
+
+  S copy = {.a = 14};
+  clang_analyzer_eval(0 == copy.x); // expected-warning{{TRUE}}
+  clang_analyzer_eval(0 == copy.y); // expected-warning{{TRUE}}
+  // FIXME: should be TRUE
+  clang_analyzer_eval(14 == copy.a); // expected-warning{{UNKNOWN}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(copy.b); // expected-warning{{UNKNOWN}}
+
+  S *ptr = new S{.b = 14};
+  clang_analyzer_eval(0 == ptr->x); // expected-warning{{TRUE}}
+  // FIXME: should be TRUE
+  clang_analyzer_eval(0 == ptr->y); // expected-warning{{TRUE}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(ptr->a); // expected-warning{{UNKNOWN}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(14 == ptr->b); // expected-warning{{UNKNOWN}}
+
+  S slot;
+  S *place = new (&slot) S{.b = 14};
+  clang_analyzer_eval(0 == place->x); // expected-warning{{TRUE}}
+  // FIXME: should be TRUE
+  clang_analyzer_eval(0 == place->y); // expected-warning{{TRUE}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(place->a); // expected-warning{{UNKNOWN}}
+  // FIXME: should be undefined
+  clang_analyzer_eval(14 == place->b); // expected-warning{{UNKNOWN}}
+
+  delete ptr;
+}
+} // namespace CXX17_anonymous_union_aggregate_member
+
+// These next are C++14 and up, but just test under C++17
+namespace CXX14_default_member_initializers {
+struct DMIPreviousField {
+  int a;
+  int b[2];
+  int c = b[a];
+};
+void dmi_properly_sequenced() {
+  DMIPreviousField direct{0, {14, 1}};
+  clang_analyzer_eval(0 == direct.a); // expected-warning{{TRUE}}
+  clang_analyzer_eval(14 == direct.b[0]); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == direct.b[1]); // expected-warning{{TRUE}}
+  // FIXME: should be true
+  clang_analyzer_eval(14 == direct.c); // expected-warning{{UNKNOWN}}
+
+  DMIPreviousField copy = {0, {14, 1}};
+  clang_analyzer_eval(0 == copy.a); // expected-warning{{TRUE}}
+  clang_analyzer_eval(14 == copy.b[0]); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == copy.b[1]); // expected-warning{{TRUE}}
+  // FIXME: should be true
+  clang_analyzer_eval(14 == copy.c); // expected-warning{{UNKNOWN}}
+
+  DMIPreviousField *ptr = new DMIPreviousField{0, {14, 1}};
+  clang_analyzer_eval(0 == ptr->a); // expected-warning{{TRUE}}
+  clang_analyzer_eval(14 == ptr->b[0]); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == ptr->b[1]); // expected-warning{{TRUE}}
+  // FIXME: should be true
+  clang_analyzer_eval(14 == ptr->c); // expected-warning{{UNKNOWN}}
+  delete ptr;
+
+  DMIPreviousField slot{0, {14, 1}};
+  auto place = new (&slot) DMIPreviousField{0, {14, 1}};
+  clang_analyzer_eval(0 == place->a); // expected-warning{{TRUE}}
+  clang_analyzer_eval(14 == place->b[0]); // expected-warning{{TRUE}}
+  clang_analyzer_eval(1 == place->b[1]); // expected-warning{{TRUE}}
+  // FIXME: should be true
+  clang_analyzer_eval(14 == place->c); // expected-warning{{UNKNOWN}}
+}
+
+union UDMI {
+  int x;
+  int y = 1;
+};
+void union_empty_init_list_default_member_initializer() {
+  UDMI direct{};
+  // FIXME: should be TRUE and undefined
+  clang_analyzer_eval(1 == direct.y); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(direct.x); // expected-warning{{UNKNOWN}}
+
+  UDMI copy = {};
+  // FIXME: should be TRUE and undefined
+  clang_analyzer_eval(1 == copy.y); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(copy.x); // expected-warning{{UNKNOWN}}
+
+  auto ptr = new UDMI{};
+  // FIXME: should be TRUE and undefined
+  clang_analyzer_eval(1 == ptr->y); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(ptr->x); // expected-warning{{UNKNOWN}}
+
+  UDMI slot;
+  auto place = new (&slot) UDMI{};
+  // FIXME: should be TRUE and undefined
+  clang_analyzer_eval(1 == place->y); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(place->x); // expected-warning{{UNKNOWN}}
+}
+
+struct ArrElt {
+  int a = 3;
+};
+ArrElt const sarr[2] = {};
+void array_list_init_aggregates_default_member_initializers() {
+  int i = 1;
+  // Should this not cause a split?
+  clang_analyzer_eval(3 == sarr[i].a); // expected-warning{{TRUE}} expected-warning{{FALSE}}
+}
+} // CXX14_default_member_initializers
+
+namespace CXX14_same_or_derived_class {
+struct T {
+  int x;
+};
+struct ...
[truncated]

``````````

</details>


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


More information about the cfe-commits mailing list