Skip to content

Commit 77abc73

Browse files
committed
"Reapply "[Sema] Fix crash on invalid code with parenthesized aggregate initialization" (llvm#76272)""
With updates the libc++ tests. This reverts commit 2205d23 and relands 86dc6e1 and 7ab16fb. Original commit was reverted because of failing libc++ tests, see llvm#76232 for the discussion. The errors in the tests are spurious in the first place (coming from initialization of invalid classes), so update the tests to match new behavior that does not show those errors.
1 parent cba217a commit 77abc73

File tree

5 files changed

+37
-17
lines changed

5 files changed

+37
-17
lines changed

clang/lib/Sema/SemaInit.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5512,6 +5512,14 @@ static void TryOrBuildParenListInitialization(
55125512
} else if (auto *RT = Entity.getType()->getAs<RecordType>()) {
55135513
bool IsUnion = RT->isUnionType();
55145514
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
5515+
if (RD->isInvalidDecl()) {
5516+
// Exit early to avoid confusion when processing members.
5517+
// We do the same for braced list initialization in
5518+
// `CheckStructUnionTypes`.
5519+
Sequence.SetFailed(
5520+
clang::InitializationSequence::FK_ParenthesizedListInitFailed);
5521+
return;
5522+
}
55155523

55165524
if (!IsUnion) {
55175525
for (const CXXBaseSpecifier &Base : RD->bases()) {

clang/test/SemaCXX/crash-GH76228.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// RUN: %clang_cc1 -std=c++20 -verify %s
2+
// Check we don't crash on incomplete members and bases when handling parenthesized initialization.
3+
class incomplete; // expected-note@-0 3 {{forward declaration of 'incomplete'}}
4+
struct foo {
5+
int a;
6+
incomplete b;
7+
// expected-error@-1 {{incomplete type}}
8+
};
9+
foo a1(0);
10+
11+
struct one_int {
12+
int a;
13+
};
14+
struct bar : one_int, incomplete {};
15+
// expected-error@-1 {{incomplete type}}
16+
bar a2(0);
17+
18+
incomplete a3[3](1,2,3);
19+
// expected-error@-1 {{incomplete type}}
20+
21+
struct qux : foo {
22+
};
23+
qux a4(0);
24+
25+
struct fred {
26+
foo a[3];
27+
};
28+
fred a5(0);

clang/test/SemaCXX/paren-list-agg-init.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ int test() {
289289
// used to crash
290290
S a(0, 1);
291291
S b(0);
292-
S c(0, 0, 1); // beforecxx20-warning {{aggregate initialization of type 'S' from a parenthesized list of values is a C++20 extension}}
292+
S c(0, 0, 1);
293293

294294
S d {0, 1};
295295
S e {0};

libcxx/test/libcxx/utilities/expected/expected.expected/transform_error.mandates.verify.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,39 +46,31 @@ void test() {
4646
{
4747
std::expected<int, int> e;
4848
e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
49-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
5049
// expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
5150

5251
e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
53-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
5452
// expected-error-re@*:* {{static assertion failed {{.*}}[expected.object.general] A program that instantiates the definition of template expected<T, E> for {{.*}} is ill-formed.}}
5553
}
5654

5755
// Test const& overload
5856
{
5957
const std::expected<int, int> e;
6058
e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
61-
// expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
6259
e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
63-
// expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
6460
}
6561

6662
// Test && overload
6763
{
6864
std::expected<int, int> e;
6965
std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
70-
// expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
7166
std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
72-
// expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
7367
}
7468

7569
// Test const&& overload
7670
{
7771
const std::expected<int, int> e;
7872
std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
79-
// expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
8073
std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
81-
// expected-error-re@*:* 2 {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
8274
}
8375
}
8476
// clang-format on

libcxx/test/libcxx/utilities/expected/expected.void/transform_error.mandates.verify.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,39 +46,31 @@ void test() {
4646
{
4747
std::expected<void, int> e;
4848
e.transform_error(return_unexpected<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
49-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
5049
// expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
5150

5251
e.transform_error(return_no_object<int&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
53-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
5452
// expected-error-re@*:* {{static assertion failed {{.*}}A program that instantiates expected<T, E> with a E that is not a valid argument for unexpected<E> is ill-formed}}
5553
}
5654

5755
// Test const& overload
5856
{
5957
const std::expected<void, int> e;
6058
e.transform_error(return_unexpected<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
61-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
6259
e.transform_error(return_no_object<const int &>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
63-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
6460
}
6561

6662
// Test && overload
6763
{
6864
std::expected<void, int> e;
6965
std::move(e).transform_error(return_unexpected<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
70-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
7166
std::move(e).transform_error(return_no_object<int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
72-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
7367
}
7468

7569
// Test const&& overload
7670
{
7771
const std::expected<void, int> e;
7872
std::move(e).transform_error(return_unexpected<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
79-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
8073
std::move(e).transform_error(return_no_object<const int&&>); // expected-error-re@*:* {{static assertion failed {{.*}}The result of {{.*}} must be a valid template argument for unexpected}}
81-
// expected-error-re@*:* {{{{(excess elements in struct initializer|no matching constructor for initialization of)}}{{.*}}}}
8274
}
8375
}
8476
// clang-format on

0 commit comments

Comments
 (0)