Patchwork C++ PATCH for c++/52796 (missed value-initialization with variadic templates)

login
register
mail settings
Submitter Jason Merrill
Date April 3, 2012, 10:49 p.m.
Message ID <4F7B7E82.9090808@redhat.com>
Download mbox | patch
Permalink /patch/150567/
State New
Headers show

Comments

Jason Merrill - April 3, 2012, 10:49 p.m.
A parenthesized initializer containing a pack expansion that expands to 
0 elements is treated as value-initialization.  We were handling that 
properly for variable initializers, but not for mem-initializers in 
constructors.

Tested x86_64-pc-linux-gnu, applying to trunk, 4.7 and 4.6.

Patch

commit 58c6706693964e81e846905cdd747a4aec015d09
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Apr 3 15:31:39 2012 -0400

    	PR c++/52796
    	* pt.c (tsubst_initializer_list): A pack expansion with no elements
    	means value-initialization.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index aabe477..03acd5b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19470,6 +19470,7 @@  tsubst_initializer_list (tree t, tree argvec)
             }
           else
             {
+	      tree tmp;
               decl = tsubst_copy (TREE_PURPOSE (t), argvec, 
                                   tf_warning_or_error, NULL_TREE);
 
@@ -19478,10 +19479,17 @@  tsubst_initializer_list (tree t, tree argvec)
                 in_base_initializer = 1;
 
 	      init = TREE_VALUE (t);
+	      tmp = init;
 	      if (init != void_type_node)
 		init = tsubst_expr (init, argvec,
 				    tf_warning_or_error, NULL_TREE,
 				    /*integral_constant_expression_p=*/false);
+	      if (init == NULL_TREE && tmp != NULL_TREE)
+		/* If we had an initializer but it instantiated to nothing,
+		   value-initialize the object.  This will only occur when
+		   the initializer was a pack expansion where the parameter
+		   packs used in that expansion were of length zero.  */
+		init = void_type_node;
               in_base_initializer = 0;
             }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-value1.C b/gcc/testsuite/g++.dg/cpp0x/variadic-value1.C
new file mode 100644
index 0000000..179919a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-value1.C
@@ -0,0 +1,24 @@ 
+// PR c++/52796
+// { dg-do run { target c++11 } }
+
+inline void *operator new(__SIZE_TYPE__ s, void *p) { return p; }
+
+struct A
+{
+  int i;
+  template<class... Ts>
+  A(Ts&&... ts): i(ts...) { }
+};
+
+static union {
+  unsigned char c[sizeof(A)];
+  int i;
+};
+
+int main()
+{
+  i = 0xdeadbeef;
+  new(c) A;
+  if (i != 0)
+    __builtin_abort();
+}