Patchwork C++ PATCHes to list-value-initialization

login
register
mail settings
Submitter Jason Merrill
Date June 29, 2011, 2:08 p.m.
Message ID <4E0B31DA.4030308@redhat.com>
Download mbox | patch
Permalink /patch/102607/
State New
Headers show

Comments

Jason Merrill - June 29, 2011, 2:08 p.m.
The first patch implements the resolution of DR 990, which clarifies 
that {} means value-initialization if the type has a default constructor.

The second patch fixes a bug in the standard I noticed while looking at 
related issues: it says that if a class has any user-provided 
constructor, we just call the default constructor.  This wording should 
have been adjusted when we added defaulted functions; I've raised the 
issue with the committee, but am also applying the obvious fix to the 
compiler, namely to only consider the user-providedness of the default 
constructor when deciding whether or not to zero-initialize first.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 900881b6124897c0384ee970fde989785ddaf49e
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Jun 28 17:25:40 2011 -0400

    	* init.c (build_value_init): Decide whether or not to zero-initialize
    	based on user-providedness of default ctor, not any ctor.
    	(build_value_init_noctor): Adjust assert.

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1719339..ac2b733 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -334,14 +334,20 @@  build_value_init (tree type, tsubst_flags_t complain)
 
   if (CLASS_TYPE_P (type))
     {
-      if (type_has_user_provided_constructor (type))
+      /* Instead of the above, only consider the user-providedness of the
+	 default constructor itself so value-initializing a class with an
+	 explicitly defaulted default constructor and another user-provided
+	 constructor works properly (c++std-core-19883).  */
+      if (type_has_user_provided_default_constructor (type)
+	  || (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)
+	      && type_has_user_provided_constructor (type)))
 	return build_aggr_init_expr
 	  (type,
 	   build_special_member_call (NULL_TREE, complete_ctor_identifier,
 				      NULL, type, LOOKUP_NORMAL,
 				      complain),
 	   complain);
-      else if (type_build_ctor_call (type))
+      else if (TYPE_HAS_COMPLEX_DFLT (type))
 	{
 	  /* This is a class that needs constructing, but doesn't have
 	     a user-provided constructor.  So we need to zero-initialize
@@ -371,7 +377,7 @@  build_value_init_noctor (tree type, tsubst_flags_t complain)
      SFINAE-enabled.  */
   if (CLASS_TYPE_P (type))
     {
-      gcc_assert (!type_build_ctor_call (type));
+      gcc_assert (!TYPE_HAS_COMPLEX_DFLT (type));
 	
       if (TREE_CODE (type) != UNION_TYPE)
 	{
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C b/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C
new file mode 100644
index 0000000..2b78241
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-value2.C
@@ -0,0 +1,20 @@ 
+// Test that we properly value-initialize a class with a user-provided
+// constructor but defaulted default constructor.  The FDIS got this
+// wrong; see c++std-core-19883.
+
+// { dg-options -std=c++0x }
+// { dg-do run }
+
+struct A
+{
+  int i;
+  A() = default;
+  A(int);
+};
+
+int main()
+{
+  A a{};
+  if (a.i != 0)
+    return 1;
+}