diff mbox

C++ PATCH for c++/51675 (DR 1359, constexpr union)

Message ID 4F01EEC8.6030807@redhat.com
State New
Headers show

Commit Message

Jason Merrill Jan. 2, 2012, 5:52 p.m. UTC
DR 1359 points out that the rules for constexpr constructors require all 
data members to be initialized, which is wrong for unions.  This patch 
implements the obvious resolution.

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

Patch

commit 82927de9eb3327c2e65be4f56aec991e36c44fa9
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Jan 2 00:40:02 2012 -0500

    	PR c++/51675
    	* method.c (walk_field_subobs): Don't check for uninitialized
    	fields in a union.
    	(synthesized_method_walk): Check here.

diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 8101f8a..cf2a713 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1063,7 +1063,8 @@  walk_field_subobs (tree fields, tree fnname, special_function_kind sfk,
 	  /* For an implicitly-defined default constructor to be constexpr,
 	     every member must have a user-provided default constructor or
 	     an explicit initializer.  */
-	  if (constexpr_p && !CLASS_TYPE_P (mem_type))
+	  if (constexpr_p && !CLASS_TYPE_P (mem_type)
+	      && TREE_CODE (DECL_CONTEXT (field)) != UNION_TYPE)
 	    {
 	      *constexpr_p = false;
 	      if (msg)
@@ -1208,12 +1209,19 @@  synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
      resolution, so a constructor can be trivial even if it would otherwise
      call a non-trivial constructor.  */
   if (expected_trivial
-      && !diag
       && (!copy_arg_p || cxx_dialect < cxx0x))
     {
       if (constexpr_p && sfk == sfk_constructor)
-	*constexpr_p = trivial_default_constructor_is_constexpr (ctype);
-      return;
+	{
+	  bool cx = trivial_default_constructor_is_constexpr (ctype);
+	  *constexpr_p = cx;
+	  if (diag && !cx && TREE_CODE (ctype) == UNION_TYPE)
+	    /* A trivial constructor doesn't have any NSDMI.  */
+	    inform (input_location, "defaulted default constructor does "
+		    "not initialize any non-static data member");
+	}
+      if (!diag)
+	return;
     }
 
   ++cp_unevaluated_operand;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C
new file mode 100644
index 0000000..0bf2aa7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union2.C
@@ -0,0 +1,18 @@ 
+// PR c++/51675
+// { dg-options -std=c++0x }
+
+union foo
+{
+  int x = 0;
+  short y;
+
+  constexpr foo() = default;
+};
+
+union bar
+{
+  int x;
+  short y;
+
+  constexpr bar() = default;	// { dg-error "constexpr" }
+};