-
Notifications
You must be signed in to change notification settings - Fork 12k
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
Clang C++20 Feature: P0960R3 -Allow initializing aggregates from a parenthesized list of values #54040
Comments
@llvm/issue-subscribers-c-20 |
@llvm/issue-subscribers-clang-frontend |
Candidate patch : https://reviews.llvm.org/D129531 |
llvm/llvm-project#54040 has been resolved!
Thank you for working on this. One thing that was not fixed is templated classes. https://godbolt.org/z/6a6Ws674o The following works in GCC and MSVC but not on Clang trunk yet: struct S {
int i;
float j;
};
template <class T>
struct ST {
T t;
};
int main() {
auto s = S(1, 2.f); // works
auto st = ST(1); // no work
} |
llvm/llvm-project#54040 has resolved the issue unless the class members are template typed.
Thanks, one more thing I ran into: A destructor breaks the aggregate init for Clang, though not for MSVC and GCC. https://godbolt.org/z/sbj8hTKWb struct Raii final {
~Raii() {}
int i;
};
int main() {
auto r = Raii(2);
}
|
llvm/llvm-project#54040 has resolved the issue of aggregates requiring an explicit constructor for parenthesis initialization. But there's some more cases where aggregate init fails on Clang. * If there's a destructor present, the aggregate constructor appears to not be generated. I believe this is still llvm/llvm-project#54040. * If the class is a template, CTAD fails to apply and aggregate initialization breaks as a result. This is llvm/llvm-project#54050.
Another issue is caused somehow by a concept-guarded conversion operator on the type of the aggregate's member. https://godbolt.org/z/sMY7WfGhx #include <concepts>
struct i32 {
int i = 0;
template <std::same_as<int> T>
operator T() const { return i; } // breaks init of S()
};
int main() {
struct S {
i32 i;
};
auto s1 = S(i32(2));
}
|
llvm/llvm-project#54040 has resolved the issue of aggregates requiring an explicit constructor for parenthesis initialization. But there's some more cases where aggregate init fails on Clang. * If there's a destructor present, the aggregate constructor appears to not be generated. I believe this is still llvm/llvm-project#54040. * If the class is a template, CTAD fails to apply and aggregate initialization breaks as a result. This is llvm/llvm-project#54050.
llvm/llvm-project#54040 has resolved the issue of aggregates requiring an explicit constructor for parenthesis initialization. But there's some more cases where aggregate init fails on Clang. * If there's a destructor present, the aggregate constructor appears to not be generated. I believe this is still llvm/llvm-project#54040. * If the class is a template, CTAD fails to apply and aggregate initialization breaks as a result. This is llvm/llvm-project#54050.
llvm/llvm-project#54040 has resolved the issue of aggregates requiring an explicit constructor for parenthesis initialization. But there's some more cases where aggregate init fails on Clang. * If there's a destructor present, the aggregate constructor appears to not be generated. I believe this is still llvm/llvm-project#54040. * If the class is a template, CTAD fails to apply and aggregate initialization breaks as a result. This is llvm/llvm-project#54050.
llvm/llvm-project#54040 has resolved the issue of aggregates requiring an explicit constructor for parenthesis initialization. But there's some more cases where aggregate init fails on Clang. * If there's a destructor present, the aggregate constructor appears to not be generated. I believe this is still llvm/llvm-project#54040. * If the class is a template, CTAD fails to apply and aggregate initialization breaks as a result. This is llvm/llvm-project#54050.
llvm/llvm-project#54040 has resolved the issue of aggregates requiring an explicit constructor for parenthesis initialization. But there's some more cases where aggregate init fails on Clang. * If there's a destructor present, the aggregate constructor appears to not be generated. I believe this is still llvm/llvm-project#54040. * If the class is a template, CTAD fails to apply and aggregate initialization breaks as a result. This is llvm/llvm-project#54050.
The previous two issues should be resolved by https://reviews.llvm.org/D140327 |
Awesome, thank you |
Previously, we would only attempt to perform a parenthesized aggregate initialization if constructor initialization failed for only the default constructor, default copy constructor, and default move constructor. The original intent of this logic was to reject initializing objects that have failed resolving a user-defined constructor. However, this check is redundant because we check for isAggregate() before attempting to perform a parenthesized aggregate initialization, and classes that have user-defined or user-declared constructors are not aggregates. Furthermore, this check is too restrictive - the following valid examples fail: * Aggregate class with user-defined destructor - fails because default move constructors are not generated for classes with user-defined destructors (#54040 (comment)) * Concept-guarded conversion operator on an aggregate's member: (#54040 (comment)) The solution therefore is to remove this logic; existing tests still pass, and the previously failing examples now compile. Reviewed By: ilya-biryukov Differential Revision: https://reviews.llvm.org/D140327
Previously, we would only attempt to perform a parenthesized aggregate initialization if constructor initialization failed for only the default constructor, default copy constructor, and default move constructor. The original intent of this logic was to reject initializing objects that have failed resolving a user-defined constructor. However, this check is redundant because we check for isAggregate() before attempting to perform a parenthesized aggregate initialization, and classes that have user-defined or user-declared constructors are not aggregates. Furthermore, this check is too restrictive - the following valid examples fail: * Aggregate class with user-defined destructor - fails because default move constructors are not generated for classes with user-defined destructors (llvm/llvm-project#54040 (comment)) * Concept-guarded conversion operator on an aggregate's member: (llvm/llvm-project#54040 (comment)) The solution therefore is to remove this logic; existing tests still pass, and the previously failing examples now compile. Reviewed By: ilya-biryukov Differential Revision: https://reviews.llvm.org/D140327
…ort (chromium#121) llvm/llvm-project#54040 has been reverted due to a compiler crash, so we must restore all our workaround constructors for it.
…ort (chromium#121) llvm/llvm-project#54040 has been reverted due to a compiler crash, so we must restore all our workaround constructors for it.
…ort (#121) llvm/llvm-project#54040 has been reverted due to a compiler crash, so we must restore all our workaround constructors for it.
This commit relands the patches for implementing P0960R3 and P1975R0, which describe initializing aggregates via a parenthesized list. The relanded commits are: * 40c5215 - P0960R3 and P1975R0: Allow initializing aggregates from a parenthesized list of values * c77a91b - Remove overly restrictive aggregate paren init logic * 32d7aae - Fix a clang crash on invalid code in C++20 mode This patch also fixes a crash in the original implementation. Previously, if the input tried to call an implicitly deleted copy or move constructor of a union, we would then try to initialize the union by initializing it's first element with a reference to a union. This behavior is incorrect (we should fail to initialize) and if the type of the first element has a constructor with a single template typename parameter, then Clang will explode. This patch fixes that issue by checking that constructor overload resolution did not result in a deleted function before attempting parenthesized aggregate initialization. Additionally, this patch also includes D140159, which contains some minor fixes made in response to code review comments in the original implementation that were made after that patch was submitted. Co-authored-by: Sheng <ox59616e@gmail.com> Fixes llvm#54040, Fixes llvm#59675 Reviewed By: ilya-biryukov Differential Revision: https://reviews.llvm.org/D141546 (cherry picked from commit 95a4c0c)
Previously, we would only attempt to perform a parenthesized aggregate initialization if constructor initialization failed for only the default constructor, default copy constructor, and default move constructor. The original intent of this logic was to reject initializing objects that have failed resolving a user-defined constructor. However, this check is redundant because we check for isAggregate() before attempting to perform a parenthesized aggregate initialization, and classes that have user-defined or user-declared constructors are not aggregates. Furthermore, this check is too restrictive - the following valid examples fail: * Aggregate class with user-defined destructor - fails because default move constructors are not generated for classes with user-defined destructors (llvm/llvm-project#54040 (comment)) * Concept-guarded conversion operator on an aggregate's member: (llvm/llvm-project#54040 (comment)) The solution therefore is to remove this logic; existing tests still pass, and the previously failing examples now compile. Reviewed By: ilya-biryukov Differential Revision: https://reviews.llvm.org/D140327
Blocks #46701
id: P0960R3
paper: https://wg21.link/p0960r3
The text was updated successfully, but these errors were encountered: