https://github.com/Flandini updated https://github.com/llvm/llvm-project/pull/127702
>From 12791f2c89f7e42bd261ac573c2497857c42b6f3 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Tue, 18 Feb 2025 15:56:13 -0600 Subject: [PATCH 01/17] [analyzer] Do list initialization for CXXNewExpr with initializer list arg --- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 18 +- clang/test/Analysis/initializer.cpp | 185 ++++++++++++++++++ 2 files changed, 194 insertions(+), 9 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index d01b6ae55f611..e376b84f8219f 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2425,6 +2425,15 @@ RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) { const MemRegion *R = MemRegVal->getRegion(); + // Binding directly to a symbolic region should be treated as binding + // to element 0. + if (const auto *SymReg = dyn_cast<SymbolicRegion>(R)) { + QualType Ty = SymReg->getPointeeStaticType(); + if (Ty->isVoidType()) + Ty = StateMgr.getContext().CharTy; + R = GetElementZeroRegion(SymReg, Ty); + } + // Check if the region is a struct region. if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) { QualType Ty = TR->getValueType(); @@ -2438,15 +2447,6 @@ RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) { return bindAggregate(B, TR, V); } - // Binding directly to a symbolic region should be treated as binding - // to element 0. - if (const auto *SymReg = dyn_cast<SymbolicRegion>(R)) { - QualType Ty = SymReg->getPointeeStaticType(); - if (Ty->isVoidType()) - Ty = StateMgr.getContext().CharTy; - R = GetElementZeroRegion(SymReg, Ty); - } - assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) && "'this' pointer is not an l-value and is not assignable"); diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index f50afff25d245..edc41d29e1df1 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -254,6 +254,191 @@ 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; +} + +class PubClass { +public: + int foo; + int bar; +}; +void public_class_designated_initializers() { + 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; +} + +union UnionTestTy { + int x; + char y; +}; +void new_expr_aggr_init_union_no_designator() { + UnionTestTy *u = new UnionTestTy{}; + clang_analyzer_eval(0 == u->x); // expected-warning{{UNKNOWN}} TODO: should be TRUE + clang_analyzer_eval(u->y); // expected-warning{{UNKNOWN}} TODO: should be undefined, warning + delete u; +} +void new_expr_aggr_init_union_designated_first_field() { + UnionTestTy *u = new UnionTestTy{ .x = 14 }; + clang_analyzer_eval(14 == u->x); // expected-warning{{UNKNOWN}} TODO: should be TRUE + clang_analyzer_eval(u->y); // expected-warning{{UNKNOWN}} TODO: should be undefined, warning + delete u; +} +void new_expr_aggr_init_union_designated_non_first_field() { + UnionTestTy *u = new UnionTestTy{ .y = 3 }; + clang_analyzer_eval(3 == u->y); // expected-warning{{UNKNOWN}} TODO: should be TRUE + clang_analyzer_eval(u->x); // expected-warning{{UNKNOWN}} TODO: should be undefined, warning + delete u; +} + +union UnionTestTyWithDefaultMemberInit { + int x; + char y = 14; +}; +void union_with_default_member_init_empty_init_list() { + auto U = new UnionTestTyWithDefaultMemberInit{}; + // clang_analyzer_eval(14 == U->y); // TODO: Should be true + clang_analyzer_eval(U->x); // expected-warning{{UNKNOWN}} TODO: should be undefined, warning + delete U; +} + +struct Inner { + int bar; +}; +struct Nested { + int foo; + Inner inner; + int baz; +}; +void nested_aggregates() { + auto N = new Nested{}; + clang_analyzer_eval(0 == N->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N->baz); // expected-warning{{TRUE}} + + auto N1 = new Nested{1}; + clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N1->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N1->baz); // expected-warning{{TRUE}} + + auto N2 = new Nested{.baz = 14}; + clang_analyzer_eval(0 == N->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(14 == N->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + + auto N3 = new Nested{1,2,3}; + clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(2 == N1->inner.bar); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(3 == N1->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + + auto N4 = new Nested{1, {}, 3}; + clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N1->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(3 == N1->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + + auto N5 = new Nested{{},{},{}}; + clang_analyzer_eval(0 == N1->foo); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(0 == N1->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N1->baz); // expected-warning{{TRUE}} + + auto N6 = new Nested{1, {.bar = 2}, 3}; + clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(2 == N1->inner.bar); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(3 == N1->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + + auto N7 = new Nested{1, {2}, 3}; + clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(2 == N1->inner.bar); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(3 == N1->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + + delete N; + delete N1; + delete N2; + delete N3; + delete N4; + delete N5; + delete N6; + delete N7; +} +} // namespace newexpr_init_list_initialization + namespace CXX17_transparent_init_list_exprs { class A {}; >From 6bab1c73e104a69c3a1d6bc145ee722b9bffdeb5 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Tue, 18 Feb 2025 23:38:52 -0600 Subject: [PATCH 02/17] Fix bugs in nested_aggregates added testcases --- clang/test/Analysis/initializer.cpp | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index edc41d29e1df1..206fa4c364aef 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -399,34 +399,34 @@ void nested_aggregates() { clang_analyzer_eval(0 == N1->baz); // expected-warning{{TRUE}} auto N2 = new Nested{.baz = 14}; - clang_analyzer_eval(0 == N->foo); // expected-warning{{TRUE}} - clang_analyzer_eval(0 == N->inner.bar); // expected-warning{{TRUE}} - clang_analyzer_eval(14 == N->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(0 == N2->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N2->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(14 == N2->baz); // expected-warning{{TRUE}} auto N3 = new Nested{1,2,3}; - clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} - clang_analyzer_eval(2 == N1->inner.bar); // expected-warning{{FALSE}} TODO: Should be TRUE - clang_analyzer_eval(3 == N1->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(1 == N3->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(2 == N3->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(3 == N3->baz); // expected-warning{{TRUE}} auto N4 = new Nested{1, {}, 3}; - clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} - clang_analyzer_eval(0 == N1->inner.bar); // expected-warning{{TRUE}} - clang_analyzer_eval(3 == N1->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(1 == N4->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N4->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(3 == N4->baz); // expected-warning{{TRUE}} auto N5 = new Nested{{},{},{}}; - clang_analyzer_eval(0 == N1->foo); // expected-warning{{FALSE}} TODO: Should be TRUE - clang_analyzer_eval(0 == N1->inner.bar); // expected-warning{{TRUE}} - clang_analyzer_eval(0 == N1->baz); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N5->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N5->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(0 == N5->baz); // expected-warning{{TRUE}} auto N6 = new Nested{1, {.bar = 2}, 3}; - clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} - clang_analyzer_eval(2 == N1->inner.bar); // expected-warning{{FALSE}} TODO: Should be TRUE - clang_analyzer_eval(3 == N1->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(1 == N6->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(2 == N6->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(3 == N6->baz); // expected-warning{{TRUE}} auto N7 = new Nested{1, {2}, 3}; - clang_analyzer_eval(1 == N1->foo); // expected-warning{{TRUE}} - clang_analyzer_eval(2 == N1->inner.bar); // expected-warning{{FALSE}} TODO: Should be TRUE - clang_analyzer_eval(3 == N1->baz); // expected-warning{{FALSE}} TODO: Should be TRUE + clang_analyzer_eval(1 == N7->foo); // expected-warning{{TRUE}} + clang_analyzer_eval(2 == N7->inner.bar); // expected-warning{{TRUE}} + clang_analyzer_eval(3 == N7->baz); // expected-warning{{TRUE}} delete N; delete N1; >From e590bfcc5d142016120119acf2f82ec74582e917 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Tue, 18 Feb 2025 23:47:36 -0600 Subject: [PATCH 03/17] switch TODO to FIXME --- clang/test/Analysis/initializer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index 206fa4c364aef..8d582658d85b2 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -351,20 +351,20 @@ union UnionTestTy { }; void new_expr_aggr_init_union_no_designator() { UnionTestTy *u = new UnionTestTy{}; - clang_analyzer_eval(0 == u->x); // expected-warning{{UNKNOWN}} TODO: should be TRUE - clang_analyzer_eval(u->y); // expected-warning{{UNKNOWN}} TODO: should be undefined, warning + clang_analyzer_eval(0 == u->x); // expected-warning{{UNKNOWN}} FIXME: should be TRUE + clang_analyzer_eval(u->y); // expected-warning{{UNKNOWN}} FIXME: should be undefined, warning delete u; } void new_expr_aggr_init_union_designated_first_field() { UnionTestTy *u = new UnionTestTy{ .x = 14 }; - clang_analyzer_eval(14 == u->x); // expected-warning{{UNKNOWN}} TODO: should be TRUE - clang_analyzer_eval(u->y); // expected-warning{{UNKNOWN}} TODO: should be undefined, warning + clang_analyzer_eval(14 == u->x); // expected-warning{{UNKNOWN}} FIXME: should be TRUE + clang_analyzer_eval(u->y); // expected-warning{{UNKNOWN}} FIXME: should be undefined, warning delete u; } void new_expr_aggr_init_union_designated_non_first_field() { UnionTestTy *u = new UnionTestTy{ .y = 3 }; - clang_analyzer_eval(3 == u->y); // expected-warning{{UNKNOWN}} TODO: should be TRUE - clang_analyzer_eval(u->x); // expected-warning{{UNKNOWN}} TODO: should be undefined, warning + clang_analyzer_eval(3 == u->y); // expected-warning{{UNKNOWN}} FIXME: should be TRUE + clang_analyzer_eval(u->x); // expected-warning{{UNKNOWN}} FIXME: should be undefined, warning delete u; } @@ -374,8 +374,8 @@ union UnionTestTyWithDefaultMemberInit { }; void union_with_default_member_init_empty_init_list() { auto U = new UnionTestTyWithDefaultMemberInit{}; - // clang_analyzer_eval(14 == U->y); // TODO: Should be true - clang_analyzer_eval(U->x); // expected-warning{{UNKNOWN}} TODO: should be undefined, warning + // clang_analyzer_eval(14 == U->y); // FIXME: Should be true + clang_analyzer_eval(U->x); // expected-warning{{UNKNOWN}} FIXME: should be undefined, warning delete U; } >From 6b86a042318b8cc0ea45b830b5b67dc8bbf3e0f7 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Tue, 18 Feb 2025 23:48:11 -0600 Subject: [PATCH 04/17] add user defined new test cpp --- clang/test/Analysis/new-user-defined.cpp | 38 ++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 clang/test/Analysis/new-user-defined.cpp diff --git a/clang/test/Analysis/new-user-defined.cpp b/clang/test/Analysis/new-user-defined.cpp new file mode 100644 index 0000000000000..f071c5c9bd27b --- /dev/null +++ b/clang/test/Analysis/new-user-defined.cpp @@ -0,0 +1,38 @@ +// RUN: %clang_analyze_cc1 -w -verify %s\ +// RUN: -analyzer-checker=core\ +// RUN: -analyzer-checker=debug.ExprInspection -std=c++17 +// RUN: %clang_analyze_cc1 -w -verify %s\ +// RUN: -analyzer-checker=core\ +// RUN: -analyzer-checker=debug.ExprInspection -std=c++11\ +// RUN: -DTEST_INLINABLE_ALLOCATORS +// RUN: %clang_analyze_cc1 -w -verify %s\ +// RUN: -analyzer-checker=core,\ +// RUN: -analyzer-checker=debug.ExprInspection -std=c++17\ +// RUN: -DTEST_INLINABLE_ALLOCATORS + +void clang_analyzer_eval(bool); + +typedef __typeof(sizeof(int)) size_t; + +namespace CustomClassType { +struct S { + int x; + static void* operator new(size_t size) { + return ::operator new(size); + } +}; +void F() { + S *s = new S; + clang_analyzer_eval(s->x); // expected-warning{{UNKNOWN}} FIXME: should be an undefined warning + + S *s2 = new S{}; + clang_analyzer_eval(0 == s2->x); // expected-warning{{TRUE}} + + S *s3 = new S{1}; + clang_analyzer_eval(1 == s3->x); // expected-warning{{TRUE}} +} + +struct WithPlacementNew { +}; + +} // namespace CustomClassType >From f6d743d97d5c257f84340a308c8456cc3147d31f Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Wed, 19 Feb 2025 00:13:07 -0600 Subject: [PATCH 05/17] add commented out enum new expr list initialization test --- clang/test/Analysis/initializer.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index 8d582658d85b2..5ee6ba4e1d600 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -330,6 +330,15 @@ void considered_fields_initd() { 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; +} + class PubClass { public: int foo; >From 56a90a8cb630dd8787fb2653ac9ea5a8ff81d373 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Wed, 19 Feb 2025 10:42:35 -0600 Subject: [PATCH 06/17] remove stray comma in new test RUN: flag --- clang/test/Analysis/new-user-defined.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Analysis/new-user-defined.cpp b/clang/test/Analysis/new-user-defined.cpp index f071c5c9bd27b..1be7af05d6f1b 100644 --- a/clang/test/Analysis/new-user-defined.cpp +++ b/clang/test/Analysis/new-user-defined.cpp @@ -6,7 +6,7 @@ // RUN: -analyzer-checker=debug.ExprInspection -std=c++11\ // RUN: -DTEST_INLINABLE_ALLOCATORS // RUN: %clang_analyze_cc1 -w -verify %s\ -// RUN: -analyzer-checker=core,\ +// RUN: -analyzer-checker=core\ // RUN: -analyzer-checker=debug.ExprInspection -std=c++17\ // RUN: -DTEST_INLINABLE_ALLOCATORS >From de1efa75a899e107bf64f174e074b352ec4d19af Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Thu, 20 Feb 2025 09:05:07 -0600 Subject: [PATCH 07/17] Use decltype and using alias instead of typedef,__typeof Co-authored-by: Balazs Benics <benicsbal...@gmail.com> --- clang/test/Analysis/new-user-defined.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/Analysis/new-user-defined.cpp b/clang/test/Analysis/new-user-defined.cpp index 1be7af05d6f1b..b690644f87794 100644 --- a/clang/test/Analysis/new-user-defined.cpp +++ b/clang/test/Analysis/new-user-defined.cpp @@ -12,7 +12,7 @@ void clang_analyzer_eval(bool); -typedef __typeof(sizeof(int)) size_t; +using size_t = decltype(sizeof(int)); namespace CustomClassType { struct S { >From fa6c4926fd69be4dab5314aa949edbe91762adef Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Thu, 20 Feb 2025 09:10:00 -0600 Subject: [PATCH 08/17] Remove empty unused test struct --- clang/test/Analysis/new-user-defined.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/clang/test/Analysis/new-user-defined.cpp b/clang/test/Analysis/new-user-defined.cpp index b690644f87794..2e6c82fa5d58a 100644 --- a/clang/test/Analysis/new-user-defined.cpp +++ b/clang/test/Analysis/new-user-defined.cpp @@ -31,8 +31,4 @@ void F() { S *s3 = new S{1}; clang_analyzer_eval(1 == s3->x); // expected-warning{{TRUE}} } - -struct WithPlacementNew { -}; - } // namespace CustomClassType >From 959866ac0cf05e3cc0789d5156b077f81cc4cf04 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Thu, 20 Feb 2025 09:14:59 -0600 Subject: [PATCH 09/17] Remove unnecessary RUN lines in new-user-defined.cpp --- clang/test/Analysis/new-user-defined.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/clang/test/Analysis/new-user-defined.cpp b/clang/test/Analysis/new-user-defined.cpp index 2e6c82fa5d58a..6296e8969f13e 100644 --- a/clang/test/Analysis/new-user-defined.cpp +++ b/clang/test/Analysis/new-user-defined.cpp @@ -1,14 +1,5 @@ -// RUN: %clang_analyze_cc1 -w -verify %s\ -// RUN: -analyzer-checker=core\ -// RUN: -analyzer-checker=debug.ExprInspection -std=c++17 -// RUN: %clang_analyze_cc1 -w -verify %s\ -// RUN: -analyzer-checker=core\ -// RUN: -analyzer-checker=debug.ExprInspection -std=c++11\ -// RUN: -DTEST_INLINABLE_ALLOCATORS -// RUN: %clang_analyze_cc1 -w -verify %s\ -// RUN: -analyzer-checker=core\ -// RUN: -analyzer-checker=debug.ExprInspection -std=c++17\ -// RUN: -DTEST_INLINABLE_ALLOCATORS +// RUN: %clang_analyze_cc1 -verify %s\ +// RUN: -analyzer-checker=core,debug.ExprInspection void clang_analyzer_eval(bool); >From ea8260bb4e95cb5a896aa288317393216181e673 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Fri, 21 Feb 2025 13:41:58 -0600 Subject: [PATCH 10/17] add escape templated function, guard enum list initialization for >= C++17 --- clang/test/Analysis/initializer.cpp | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index 5ee6ba4e1d600..ab03f396bec83 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -255,6 +255,9 @@ void foo() { } // namespace CXX17_aggregate_construction namespace newexpr_init_list_initialization { +template <class FirstT, class... Rest> +void escape(FirstT first, Rest... args); + struct S { int foo; int bar; @@ -330,14 +333,16 @@ void considered_fields_initd() { delete S; } +#if __cplusplus >= 201703L 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; + Enum *E = new Enum{53}; + clang_analyzer_eval(53 == *E); // expected-warning{{TRUE}} + delete E; } +#endif // __cplusplus >= 201703L class PubClass { public: @@ -437,14 +442,7 @@ void nested_aggregates() { clang_analyzer_eval(2 == N7->inner.bar); // expected-warning{{TRUE}} clang_analyzer_eval(3 == N7->baz); // expected-warning{{TRUE}} - delete N; - delete N1; - delete N2; - delete N3; - delete N4; - delete N5; - delete N6; - delete N7; + escape(N,N1,N2,N3,N4,N5,N6,N7); } } // namespace newexpr_init_list_initialization >From 740a2725a61049e274b840092ddc7c482dc069ec Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Fri, 21 Feb 2025 14:14:19 -0600 Subject: [PATCH 11/17] remove stale FIXME --- clang/test/Analysis/initializer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index ab03f396bec83..67589c249c853 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -336,7 +336,6 @@ void considered_fields_initd() { #if __cplusplus >= 201703L 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); // expected-warning{{TRUE}} >From 0a9bc4c391ee52170b3126cb3b380a8ec0905870 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Fri, 21 Feb 2025 14:17:10 -0600 Subject: [PATCH 12/17] Add escape to new-user-defined.cpp tests also --- clang/test/Analysis/new-user-defined.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/test/Analysis/new-user-defined.cpp b/clang/test/Analysis/new-user-defined.cpp index 6296e8969f13e..8987ac078bf2c 100644 --- a/clang/test/Analysis/new-user-defined.cpp +++ b/clang/test/Analysis/new-user-defined.cpp @@ -5,6 +5,9 @@ void clang_analyzer_eval(bool); using size_t = decltype(sizeof(int)); +template <class FirstT, class... Rest> +void escape(FirstT first, Rest... args); + namespace CustomClassType { struct S { int x; @@ -21,5 +24,7 @@ void F() { S *s3 = new S{1}; clang_analyzer_eval(1 == s3->x); // expected-warning{{TRUE}} + + escape(s, s2, s3); } } // namespace CustomClassType >From e14945beae6714d5d0dfb312b33d806a59980af1 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Fri, 21 Feb 2025 14:30:19 -0600 Subject: [PATCH 13/17] Add placement new list initializer argument tests --- clang/test/Analysis/initializer.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index 67589c249c853..320d38ffb8d03 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -445,6 +445,25 @@ void nested_aggregates() { } } // namespace newexpr_init_list_initialization +namespace initializer_list_arg { +struct S { + int x; +}; +void aggregate_struct() { + S s; + ::new (&s) S{1}; + clang_analyzer_eval(1 == s.x); // expected-warning{{TRUE}} + + S vi; + ::new (&vi) S{}; + clang_analyzer_eval(0 == vi.x); // expected-warning{{TRUE}} + + S di; + ::new (&di) S; + int z = di.x + 1; // expected-warning{{The left operand of '+' is a garbage value}} +} +} // namespace initializer_list_arg + namespace CXX17_transparent_init_list_exprs { class A {}; >From c21d6cffe086f4f72c4f08b492cead5a994e0f3d Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Fri, 21 Feb 2025 14:34:55 -0600 Subject: [PATCH 14/17] Add xazax-hun's placement new tests --- clang/test/Analysis/initializer.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index 320d38ffb8d03..1f8975cff88fd 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -462,6 +462,14 @@ void aggregate_struct() { ::new (&di) S; int z = di.x + 1; // expected-warning{{The left operand of '+' is a garbage value}} } +void initialize_non_zeroth_element(S arr[2]) { + new (&arr[1]) S{1}; + clang_analyzer_eval(1 == arr[1].x); // expected-warning{{TRUE}} +} +void initialize_non_zeroth_argument_pointers(S *arr[2]) { + arr[1] = new (arr[1]) S{1}; + clang_analyzer_eval(1 == arr[1]->x); // expected-warning{{TRUE}} +} } // namespace initializer_list_arg namespace CXX17_transparent_init_list_exprs { >From 2f186c918057bec66480f45838bf7f49e0095dfd Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Fri, 21 Feb 2025 14:37:44 -0600 Subject: [PATCH 15/17] Remove unnecessary ::new qualifier --- clang/test/Analysis/initializer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index 1f8975cff88fd..fdcbc7753f352 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -451,15 +451,15 @@ struct S { }; void aggregate_struct() { S s; - ::new (&s) S{1}; + new (&s) S{1}; clang_analyzer_eval(1 == s.x); // expected-warning{{TRUE}} S vi; - ::new (&vi) S{}; + new (&vi) S{}; clang_analyzer_eval(0 == vi.x); // expected-warning{{TRUE}} S di; - ::new (&di) S; + new (&di) S; int z = di.x + 1; // expected-warning{{The left operand of '+' is a garbage value}} } void initialize_non_zeroth_element(S arr[2]) { >From 35a8d828f4cb15c799ec391e8b5aa04cec3f4f97 Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Fri, 21 Feb 2025 14:38:47 -0600 Subject: [PATCH 16/17] Clarify namespace name after moving to initializer.cpp --- clang/test/Analysis/initializer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index fdcbc7753f352..9432fb59d0634 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -445,7 +445,7 @@ void nested_aggregates() { } } // namespace newexpr_init_list_initialization -namespace initializer_list_arg { +namespace placement_new_initializer_list_arg { struct S { int x; }; @@ -470,7 +470,7 @@ void initialize_non_zeroth_argument_pointers(S *arr[2]) { arr[1] = new (arr[1]) S{1}; clang_analyzer_eval(1 == arr[1]->x); // expected-warning{{TRUE}} } -} // namespace initializer_list_arg +} // namespace placement_new_initializer_list_arg namespace CXX17_transparent_init_list_exprs { class A {}; >From 4c3e1ca0d6cf085ecd330c2fa3e66b134294473a Mon Sep 17 00:00:00 2001 From: Michael Flanders <flanders.micha...@gmail.com> Date: Fri, 21 Feb 2025 14:52:33 -0600 Subject: [PATCH 17/17] Use pointer returned by placement new instead --- clang/test/Analysis/initializer.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/clang/test/Analysis/initializer.cpp b/clang/test/Analysis/initializer.cpp index 9432fb59d0634..713e121168571 100644 --- a/clang/test/Analysis/initializer.cpp +++ b/clang/test/Analysis/initializer.cpp @@ -451,20 +451,20 @@ struct S { }; void aggregate_struct() { S s; - new (&s) S{1}; - clang_analyzer_eval(1 == s.x); // expected-warning{{TRUE}} + S *s_ptr = new (&s) S{1}; + clang_analyzer_eval(1 == s_ptr->x); // expected-warning{{TRUE}} S vi; - new (&vi) S{}; - clang_analyzer_eval(0 == vi.x); // expected-warning{{TRUE}} + S *vi_ptr = new (&vi) S{}; + clang_analyzer_eval(0 == vi_ptr->x); // expected-warning{{TRUE}} S di; - new (&di) S; - int z = di.x + 1; // expected-warning{{The left operand of '+' is a garbage value}} + S *di_ptr = new (&di) S; + int z = di_ptr->x + 1; // expected-warning{{The left operand of '+' is a garbage value}} } void initialize_non_zeroth_element(S arr[2]) { - new (&arr[1]) S{1}; - clang_analyzer_eval(1 == arr[1].x); // expected-warning{{TRUE}} + S *s = new (&arr[1]) S{1}; + clang_analyzer_eval(1 == s->x); // expected-warning{{TRUE}} } void initialize_non_zeroth_argument_pointers(S *arr[2]) { arr[1] = new (arr[1]) S{1}; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits