diff options
author | Marek Polacek <polacek@redhat.com> | 2019-12-03 15:59:40 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2019-12-03 15:59:40 +0000 |
commit | 43aae289866f5ea55d187444520412554aa2e171 (patch) | |
tree | a3a517242014a3db820710f763749398c1d1e0f0 /gcc/cp/cp-tree.h | |
parent | 577f4a0e5e7f7ef9b5729a3eed79e523cba9dfa9 (diff) | |
download | gcc-43aae289866f5ea55d187444520412554aa2e171.zip gcc-43aae289866f5ea55d187444520412554aa2e171.tar.gz gcc-43aae289866f5ea55d187444520412554aa2e171.tar.bz2 |
PR c++/91363 - P0960R3: Parenthesized initialization of aggregates.
This patch implements C++20 P0960R3: Parenthesized initialization of aggregates
(<wg21.link/p0960>; see R0 for more background info). Essentially, if you have
an aggregate, you can now initialize it by (x, y), similarly to {x, y}. E.g.
struct A {
int x, y;
// no A(int, int) ctor (see paren-init14.C for = delete; case)
};
A a(1, 2);
The difference between ()-init and {}-init is that narrowing conversions are
permitted, designators are not permitted, a temporary object bound to
a reference does not have its lifetime extended, and there is no brace elision.
Further, things like
int a[](1, 2, 3); // will deduce the array size
const A& r(1, 2.3, 3); // narrowing is OK
int (&&rr)[](1, 2, 3);
int b[3](1, 2); // b[2] will be value-initialized
now work as expected. Note that
char f[]("fluff");
has always worked and this patch keeps it that way. Also note that A a((1, 2))
is not the same as A a{{1,2}}; the inner (1, 2) remains a COMPOUND_EXPR.
The approach I took was to handle (1, 2) similarly to {1, 2} -- conjure up
a CONSTRUCTOR, and introduce LOOKUP_AGGREGATE_PAREN_INIT to distinguish
between the two. This kind of initialization is only supported in C++20;
I've made no attempt to support it in earlier standards, like we don't
support CTAD pre-C++17, for instance.
* c-cppbuiltin.c (c_cpp_builtins): Predefine
__cpp_aggregate_paren_init=201902 for -std=c++2a.
* call.c (build_new_method_call_1): Handle parenthesized initialization
of aggregates by building up a CONSTRUCTOR.
(extend_ref_init_temps): Do nothing for CONSTRUCTOR_IS_PAREN_INIT.
* cp-tree.h (CONSTRUCTOR_IS_PAREN_INIT, LOOKUP_AGGREGATE_PAREN_INIT):
Define.
* decl.c (grok_reference_init): Handle aggregate initialization from
a parenthesized list of values.
(reshape_init): Do nothing for CONSTRUCTOR_IS_PAREN_INIT.
(check_initializer): Handle initialization of an array from a
parenthesized list of values. Use NULL_TREE instead of NULL.
* tree.c (build_cplus_new): Handle BRACE_ENCLOSED_INITIALIZER_P.
* typeck2.c (digest_init_r): Set LOOKUP_AGGREGATE_PAREN_INIT if it
receives a CONSTRUCTOR with CONSTRUCTOR_IS_PAREN_INIT set. Allow
narrowing when LOOKUP_AGGREGATE_PAREN_INIT.
(massage_init_elt): Don't lose LOOKUP_AGGREGATE_PAREN_INIT when passing
flags to digest_init_r.
* g++.dg/cpp0x/constexpr-99.C: Only expect an error in C++17 and
lesser.
* g++.dg/cpp0x/explicit7.C: Likewise.
* g++.dg/cpp0x/initlist12.C: Adjust dg-error.
* g++.dg/cpp0x/pr31437.C: Likewise.
* g++.dg/cpp2a/feat-cxx2a.C: Add __cpp_aggregate_paren_init test.
* g++.dg/cpp2a/paren-init1.C: New test.
* g++.dg/cpp2a/paren-init10.C: New test.
* g++.dg/cpp2a/paren-init11.C: New test.
* g++.dg/cpp2a/paren-init12.C: New test.
* g++.dg/cpp2a/paren-init13.C: New test.
* g++.dg/cpp2a/paren-init14.C: New test.
* g++.dg/cpp2a/paren-init15.C: New test.
* g++.dg/cpp2a/paren-init16.C: New test.
* g++.dg/cpp2a/paren-init17.C: New test.
* g++.dg/cpp2a/paren-init18.C: New test.
* g++.dg/cpp2a/paren-init19.C: New test.
* g++.dg/cpp2a/paren-init2.C: New test.
* g++.dg/cpp2a/paren-init3.C: New test.
* g++.dg/cpp2a/paren-init4.C: New test.
* g++.dg/cpp2a/paren-init5.C: New test.
* g++.dg/cpp2a/paren-init6.C: New test.
* g++.dg/cpp2a/paren-init7.C: New test.
* g++.dg/cpp2a/paren-init8.C: New test.
* g++.dg/cpp2a/paren-init9.C: New test.
* g++.dg/ext/desig10.C: Adjust dg-error.
* g++.dg/template/crash107.C: Likewise.
* g++.dg/template/crash95.C: Likewise.
* g++.old-deja/g++.jason/crash3.C: Likewise.
* g++.old-deja/g++.law/ctors11.C: Likewise.
* g++.old-deja/g++.law/ctors9.C: Likewise.
* g++.old-deja/g++.mike/net22.C: Likewise.
* g++.old-deja/g++.niklas/t128.C: Likewise.
From-SVN: r278939
Diffstat (limited to 'gcc/cp/cp-tree.h')
-rw-r--r-- | gcc/cp/cp-tree.h | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7e810b8..4af18b0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4325,6 +4325,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define CONSTRUCTOR_IS_DESIGNATED_INIT(NODE) \ (TREE_LANG_FLAG_6 (CONSTRUCTOR_CHECK (NODE))) +/* True if this CONSTRUCTOR comes from a parenthesized list of values, e.g. + A(1, 2, 3). */ +#define CONSTRUCTOR_IS_PAREN_INIT(NODE) \ + (CONSTRUCTOR_CHECK(NODE)->base.private_flag) + /* True if NODE represents a conversion for direct-initialization in a template. Set by perform_implicit_conversion_flags. */ #define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \ @@ -5583,6 +5588,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; args), then we swap the conversions back in build_new_op_1 (so they correspond to the order of the args in the candidate). */ #define LOOKUP_REVERSED (LOOKUP_REWRITTEN << 1) +/* We're initializing an aggregate from a parenthesized list of values. */ +#define LOOKUP_AGGREGATE_PAREN_INIT (LOOKUP_REVERSED << 1) #define LOOKUP_NAMESPACES_ONLY(F) \ (((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES)) |