Bug 91363

Summary: Implement P0960R3: Parenthesized initialization of aggregates
Product: gcc Reporter: Marek Polacek <mpolacek>
Component: c++Assignee: Marek Polacek <mpolacek>
Status: RESOLVED FIXED    
Severity: normal CC: jakub, webrown.cpp
Priority: P3 Keywords: patch
Version: 10.0   
Target Milestone: 10.0   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2019-08-05 00:00:00
Bug Depends on:    
Bug Blocks: 88323    

Comment 1 Marek Polacek 2019-10-16 22:14:13 UTC
Working on it.  This test now runs fine with -std=c++2a with my WIP patch:

struct A {
  int i;
  int j;
  int k; // value-init
};

int i;
A a(1, 2);
A a2(1.0, 2);
A a3(++i, ++i); // left-to-right eval

int
main ()
{
  if (a.i != 1 || a.j != 2 || a.k != 0)
    __builtin_abort ();
  if (a2.i != 1 || a2.j != 2 || a.k != 0)
    __builtin_abort ();
  if (a3.i != 1 || a3.j != 2 || a.k != 0)
    __builtin_abort ();
}
Comment 3 Jakub Jelinek 2019-11-06 15:21:14 UTC
What's the status of this?
Comment 4 Marek Polacek 2019-11-06 15:32:38 UTC
Need to respond to Jason's feedback:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00034.html

But there's very little time left for stage1 and I've been trying to get P1327 done, and then hopefully also P1331.
Comment 5 Marek Polacek 2019-12-03 16:00:24 UTC
Author: mpolacek
Date: Tue Dec  3 15:59:40 2019
New Revision: 278939

URL: https://gcc.gnu.org/viewcvs?rev=278939&root=gcc&view=rev
Log:
	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.

Added:
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init1.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init10.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init11.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init12.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init13.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init14.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init15.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init16.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init17.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init18.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init19.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init2.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init3.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init4.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init5.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init6.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init7.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init8.C
    trunk/gcc/testsuite/g++.dg/cpp2a/paren-init9.C
Modified:
    trunk/gcc/c-family/ChangeLog
    trunk/gcc/c-family/c-cppbuiltin.c
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/call.c
    trunk/gcc/cp/cp-tree.h
    trunk/gcc/cp/decl.c
    trunk/gcc/cp/tree.c
    trunk/gcc/cp/typeck2.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/g++.dg/cpp0x/constexpr-99.C
    trunk/gcc/testsuite/g++.dg/cpp0x/explicit7.C
    trunk/gcc/testsuite/g++.dg/cpp0x/initlist12.C
    trunk/gcc/testsuite/g++.dg/cpp0x/pr31437.C
    trunk/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
    trunk/gcc/testsuite/g++.dg/ext/desig10.C
    trunk/gcc/testsuite/g++.dg/template/crash107.C
    trunk/gcc/testsuite/g++.dg/template/crash95.C
    trunk/gcc/testsuite/g++.old-deja/g++.jason/crash3.C
    trunk/gcc/testsuite/g++.old-deja/g++.law/ctors11.C
    trunk/gcc/testsuite/g++.old-deja/g++.law/ctors9.C
    trunk/gcc/testsuite/g++.old-deja/g++.mike/net22.C
    trunk/gcc/testsuite/g++.old-deja/g++.niklas/t128.C
Comment 6 Marek Polacek 2019-12-03 16:03:37 UTC
Implemented for GCC 10.