diff mbox series

C++ PATCH for CWG 2096, constraints on literal unions

Message ID 20190513220747.GH20687@redhat.com
State New
Headers show
Series C++ PATCH for CWG 2096, constraints on literal unions | expand

Commit Message

Marek Polacek May 13, 2019, 10:07 p.m. UTC
This patch implements CWG 2096 which relaxes the constraints for literal unions.

[basic.types]/p10 now says: A type is a literal type if...
-- it is a union, at least one of its non-static data members is of non-volatile literal type,
[...]

check_field_decls is called with CLASSTYPE_LITERAL_P set to true, so we can
re-set it after we've processed all fields.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2019-05-13  Marek Polacek  <polacek@redhat.com>

	CWG 2096 - constraints on literal unions.
	* class.c (check_field_decls): Initialize booleans directly.  A union
	is literal if at least one of its non-static data members is of
	non-volatile literal type.

	* g++.dg/cpp0x/literal-type1.C: New test.

Comments

Jason Merrill May 15, 2019, 8:38 p.m. UTC | #1
On 5/13/19 6:07 PM, Marek Polacek wrote:
> This patch implements CWG 2096 which relaxes the constraints for literal unions.
> 
> [basic.types]/p10 now says: A type is a literal type if...
> -- it is a union, at least one of its non-static data members is of non-volatile literal type,
> [...]
> 
> check_field_decls is called with CLASSTYPE_LITERAL_P set to true, so we can
> re-set it after we've processed all fields.
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
> 
> 2019-05-13  Marek Polacek  <polacek@redhat.com>
> 
> 	CWG 2096 - constraints on literal unions.
> 	* class.c (check_field_decls): Initialize booleans directly.  A union
> 	is literal if at least one of its non-static data members is of
> 	non-volatile literal type.

OK, thanks.

Jason
diff mbox series

Patch

diff --git gcc/cp/class.c gcc/cp/class.c
index a47777cdd9e..ed885a5a2c1 100644
--- gcc/cp/class.c
+++ gcc/cp/class.c
@@ -3403,18 +3403,19 @@  check_field_decls (tree t, tree *access_decls,
 {
   tree *field;
   tree *next;
-  bool has_pointers;
-  bool any_default_members;
   int cant_pack = 0;
   int field_access = -1;
 
   /* Assume there are no access declarations.  */
   *access_decls = NULL_TREE;
   /* Assume this class has no pointer members.  */
-  has_pointers = false;
+  bool has_pointers = false;
   /* Assume none of the members of this class have default
      initializations.  */
-  any_default_members = false;
+  bool any_default_members = false;
+  /* Assume none of the non-static data members are of non-volatile literal
+     type.  */
+  bool found_nv_literal_p = false;
 
   for (field = &TYPE_FIELDS (t); *field; field = next)
     {
@@ -3498,13 +3499,19 @@  check_field_decls (tree t, tree *access_decls,
       if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
 	CLASSTYPE_NON_AGGREGATE (t) = 1;
 
-      /* If at least one non-static data member is non-literal, the whole
-         class becomes non-literal.  Per Core/1453, volatile non-static
-	 data members and base classes are also not allowed.
+      /* If it is not a union and at least one non-static data member is
+	 non-literal, the whole class becomes non-literal.  Per Core/1453,
+	 volatile non-static data members and base classes are also not allowed.
+	 If it is a union, we might set CLASSTYPE_LITERAL_P after we've seen all
+	 members.
 	 Note: if the type is incomplete we will complain later on.  */
-      if (COMPLETE_TYPE_P (type)
-	  && (!literal_type_p (type) || CP_TYPE_VOLATILE_P (type))) 
-        CLASSTYPE_LITERAL_P (t) = false;
+      if (COMPLETE_TYPE_P (type))
+	{
+	  if (!literal_type_p (type) || CP_TYPE_VOLATILE_P (type))
+	    CLASSTYPE_LITERAL_P (t) = false;
+	  else
+	    found_nv_literal_p = true;
+	}
 
       /* A standard-layout class is a class that:
 	 ...
@@ -3677,6 +3684,11 @@  check_field_decls (tree t, tree *access_decls,
 		   "field %q#D with same name as class", x);
     }
 
+  /* Per CWG 2096, a type is a literal type if it is a union, and at least
+     one of its non-static data members is of non-volatile literal type.  */
+  if (TREE_CODE (t) == UNION_TYPE && found_nv_literal_p)
+    CLASSTYPE_LITERAL_P (t) = true;
+
   /* Effective C++ rule 11: if a class has dynamic memory held by pointers,
      it should also define a copy constructor and an assignment operator to
      implement the correct copy semantic (deep vs shallow, etc.). As it is
diff --git gcc/testsuite/g++.dg/cpp0x/literal-type1.C gcc/testsuite/g++.dg/cpp0x/literal-type1.C
new file mode 100644
index 00000000000..7b5d4288923
--- /dev/null
+++ gcc/testsuite/g++.dg/cpp0x/literal-type1.C
@@ -0,0 +1,54 @@ 
+// CWG 2096 - constraints on literal unions.
+// { dg-do compile { target c++11 } }
+
+struct literal { };
+typedef volatile int nonliteral_v;
+struct nonliteral {
+  nonliteral() {}
+};
+
+union U {
+  literal l;
+  nonliteral n;
+
+  constexpr U() : l{} {}
+};
+
+constexpr U u{};
+
+union U2 {
+  nonliteral n;
+  literal l;
+
+  constexpr U2() : l{} {}
+};
+
+constexpr U2 u2{};
+
+union U3 { // { dg-message "not literal" }
+  nonliteral_v n; // { dg-message "volatile type" }
+
+  constexpr U3() : n{} {}
+};
+
+constexpr U3 u3{}; // { dg-error "not literal" }
+
+union U4 {
+  nonliteral n;
+  nonliteral_v n2;
+  literal l;
+  nonliteral n3;
+
+  constexpr U4() : l{} {}
+};
+
+constexpr U4 u4{};
+
+union U5 {
+  nonliteral_v n;
+  literal l;
+
+  constexpr U5() : n{} {}
+};
+
+constexpr U5 u5{};