diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index a38b99ff8e075..ba95d6aff619b 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -424,6 +424,12 @@ features cannot lower the translation-unit ABI level; copy so the union's object representation is copied, matching the defaulted union copy constructor. +- Fixed a miscompile where C++20 parenthesized aggregate initialization generated + invalid LLVM IR. (GH#213284) + +- Fixed a crash when compiling C++20 parenthesized aggregate initialization in + template constructor member initializers. (GH#189005) + #### Bug Fixes to AST Handling - Fixed a non-deterministic ordering of unused local typedefs that made diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 47b01b913b428..9e142fb79889a 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4657,6 +4657,9 @@ Sema::BuildMemberInitializer(ValueDecl *Member, Expr *Init, Args = MultiExprArg(ParenList->getExprs(), ParenList->getNumExprs()); } else if (InitListExpr *InitList = dyn_cast(Init)) { Args = MultiExprArg(InitList->getInits(), InitList->getNumInits()); + } else if (CXXParenListInitExpr *CXXInitList = + dyn_cast(Init)) { + Args = CXXInitList->getInitExprs(); } else { // Template instantiation doesn't reconstruct ParenListExprs for us. Args = Init; diff --git a/clang/test/CodeGen/gh189005.cpp b/clang/test/CodeGen/gh189005.cpp new file mode 100644 index 0000000000000..1252e803ad394 --- /dev/null +++ b/clang/test/CodeGen/gh189005.cpp @@ -0,0 +1,99 @@ +// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -o - + +namespace std { + +template +struct pair { + T1 first; + T2 second; + + // Constructor needed so this reproduces the std::array + // initialization from the original report. + constexpr + pair(const T1& a, const T2& b) + : first(a), second(b) + {} +}; + +template +struct array { + T elems[N]; +}; +} // namespace std + +// Nested aggregate containing an array of aggregates. +struct Inner { + int x; +}; + +struct Outer { + Inner arr[2]; +}; + +template +struct S { + S() : m({{1}, {2}}) {} + Outer m; +}; + +template struct S; + +// std::array-style initialization. +template +struct S2 { + S2() : a({{1, 2}}) {} + std::array, 1> a; +}; + +template struct S2; + +// Designated initializer. +struct Point { + int x; + int y; +}; + +struct Config { + Point x; +}; + +template +struct Designated { + Designated() : cfg({.x = 10, .y = 5}) {} + Config cfg; +}; + +template struct Designated; + +// String literal initializer. +// Not affected by this fix, but kept as a regression +// for another aggregate initialization path. +struct Buffer { + char data[10]; +}; + +template +struct String { + String() : buf("hello") {} + Buffer buf; +}; + +template struct String; + +// Parenthesized aggregate with multiple arguments. +struct First { + int x; +}; + +struct Second { + First a; + int y; +}; + +template +struct Nested { + Nested() : sec({1}, 2) {} + Second sec; +}; + +template struct Nested; diff --git a/clang/test/CodeGen/gh213284.cpp b/clang/test/CodeGen/gh213284.cpp new file mode 100644 index 0000000000000..7e875bb9d616e --- /dev/null +++ b/clang/test/CodeGen/gh213284.cpp @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 -std=c++20 %s -emit-llvm -triple x86_64-unknown-linux-gnu -o - | FileCheck %s + +struct Ref { + unsigned long long bits; +}; + +template +struct Result { + Result() : thing(0) {} + Ref thing; +}; + +Result construct() { + return Result(); +} +// CHECK-LABEL: define {{.*}}construct +// CHECK: store i64 0