-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[analyzer] Add more C++ list initializer tests and regroup #129182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[analyzer] Add more C++ list initializer tests and regroup #129182
Conversation
@llvm/pr-subscribers-clang-static-analyzer-1 @llvm/pr-subscribers-clang Author: Michael Flanders (Flandini) ChangesRelated 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 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 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:
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]
|
Due to the size of this PR, and the fact the other PR is already approved, I'd suggest merging that first, and then deal with this later to have fewer pending PRs. I can't tell when can I back to this PR. Ping me if my review is expected (and missing) in a week. |
b6e6f55
to
de3329e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you annotate the removed hunks with notes where are they tested now?
I want to double check that no tests disappear.
Yes, I won't have time for it until probably this weekend or after though, so it will be a bit. |
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.