Implement P0138R2, C++17 construction rules for enum class values
authorJakub Jelinek <jakub@redhat.com>
Fri, 23 Sep 2016 17:38:29 +0000 (19:38 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Fri, 23 Sep 2016 17:38:29 +0000 (19:38 +0200)
Implement P0138R2, C++17 construction rules for enum class values
* cp-tree.h (is_direct_enum_init): Declare.
* decl.c (is_direct_enum_init): New function.
(reshape_init): Use it.
* typeck.c (convert_for_assignment): Likewise.

* g++.dg/cpp1z/direct-enum-init1.C: New test.

From-SVN: r240449

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C [new file with mode: 0644]

index 7109684c21bfb971dee1001cd09e48da76e4021c..a3430bf3ad50531cdb8aee2ecb6a752e19af117c 100644 (file)
@@ -1,5 +1,11 @@
 2016-09-23  Jakub Jelinek  <jakub@redhat.com>
 
+       Implement P0138R2, C++17 construction rules for enum class values
+       * cp-tree.h (is_direct_enum_init): Declare.
+       * decl.c (is_direct_enum_init): New function.
+       (reshape_init): Use it.
+       * typeck.c (convert_for_assignment): Likewise.
+
        * Make-lang.in (check-c++1z): Pass RUNTESTFLAGS down to
        make check-g++.
 
index f40334092a081a91b59b8d6820a354d00c1ce12d..c7a38faa10f7dfb6f8eeecbf442c7996ab64d627 100644 (file)
@@ -5829,6 +5829,7 @@ extern tree check_elaborated_type_specifier       (enum tag_types, tree, bool);
 extern void warn_extern_redeclared_static      (tree, tree);
 extern tree cxx_comdat_group                   (tree);
 extern bool cp_missing_noreturn_ok_p           (tree);
+extern bool is_direct_enum_init                        (tree, tree);
 extern void initialize_artificial_var          (tree, vec<constructor_elt, va_gc> *);
 extern tree check_var_type                     (tree, tree);
 extern tree reshape_init                        (tree, tree, tsubst_flags_t);
index 24f71ce4f7236fcc14030e87e2034a94f4bc0448..3dfa0423522722d9d3adc35390cb4cfdd3cac85c 100644 (file)
@@ -5581,6 +5581,22 @@ next_initializable_field (tree field)
   return field;
 }
 
+/* Return true for [dcl.init.list] direct-list-initialization from
+   single element of enumeration with a fixed underlying type.  */
+
+bool
+is_direct_enum_init (tree type, tree init)
+{
+  if (cxx_dialect >= cxx1z
+      && TREE_CODE (type) == ENUMERAL_TYPE
+      && ENUM_FIXED_UNDERLYING_TYPE_P (type)
+      && TREE_CODE (init) == CONSTRUCTOR
+      && CONSTRUCTOR_IS_DIRECT_INIT (init)
+      && CONSTRUCTOR_NELTS (init) == 1)
+    return true;
+  return false;
+}
+
 /* Subroutine of reshape_init_array and reshape_init_vector, which does
    the actual work. ELT_TYPE is the element type of the array. MAX_INDEX is an
    INTEGER_CST representing the size of the array minus one (the maximum index),
@@ -6026,6 +6042,17 @@ reshape_init (tree type, tree init, tsubst_flags_t complain)
   if (vec_safe_is_empty (v))
     return init;
 
+  /* Handle [dcl.init.list] direct-list-initialization from
+     single element of enumeration with a fixed underlying type.  */
+  if (is_direct_enum_init (type, init))
+    {
+      tree elt = CONSTRUCTOR_ELT (init, 0)->value;
+      if (check_narrowing (ENUM_UNDERLYING_TYPE (type), elt, complain))
+       return cp_build_c_cast (type, elt, tf_warning_or_error);
+      else
+       return error_mark_node;
+    }
+
   /* Recurse on this CONSTRUCTOR.  */
   d.cur = &(*v)[0];
   d.end = d.cur + v->length ();
index c53a85a16e0ef678e32ab48521aedfa68ecf798c..b2af615d89e74a30d5bdcf0f70c302c743cf4591 100644 (file)
@@ -8266,6 +8266,17 @@ convert_for_assignment (tree type, tree rhs,
   if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
 
+  /* Handle [dcl.init.list] direct-list-initialization from
+     single element of enumeration with a fixed underlying type.  */
+  if (is_direct_enum_init (type, rhs))
+    {
+      tree elt = CONSTRUCTOR_ELT (rhs, 0)->value;
+      if (check_narrowing (ENUM_UNDERLYING_TYPE (type), elt, complain))
+       rhs = cp_build_c_cast (type, elt, complain);
+      else
+       rhs = error_mark_node;
+    }
+
   rhstype = TREE_TYPE (rhs);
   coder = TREE_CODE (rhstype);
 
index 7a853dc33e0b8c9c29ca589b7579de4f3a98375d..080e55604ec7b640e2e3a7b4569c26cba0a8ab5e 100644 (file)
@@ -1,3 +1,8 @@
+2016-09-23  Jakub Jelinek  <jakub@redhat.com>
+
+       Implement P0138R2, C++17 construction rules for enum class values
+       * g++.dg/cpp1z/direct-enum-init1.C: New test.
+
 2016-09-23  David Malcolm  <dmalcolm@redhat.com>
 
        PR preprocessor/77672
diff --git a/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C b/gcc/testsuite/g++.dg/cpp1z/direct-enum-init1.C
new file mode 100644 (file)
index 0000000..b473ed5
--- /dev/null
@@ -0,0 +1,237 @@
+// P0138R2 - direct-list-initialization of enums
+// { dg-do compile { target c++11 } }
+
+enum A { G = 26 };
+enum B : short {};
+enum class C {};
+enum struct D : long {};
+enum class E : unsigned char { e = 7 };
+struct S { operator C () { return C (s); } int s; } s;
+struct T { operator long () { return t; } long t; } t;
+struct V { E v; };
+long l;
+long long ll;
+short c;
+void bar (E);
+
+void
+foo ()
+{
+  A a1 { 5 };          // { dg-error "invalid conversion from 'int' to 'A'" }
+  B b1 { 7 };          // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+  C c1 { s };
+  D d1 { D(t) };       // { dg-error "invalid cast from type 'T' to type 'D'" }
+  D d2 { t };          // { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+                       // { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+  D d3 { 9 };          // { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+  D d4 { l };          // { dg-error "cannot convert 'long int' to 'D' in initialization" "" { target c++14_down } }
+  D d5 { D(l) };
+  D d6 { G };          // { dg-error "cannot convert 'A' to 'D' in initialization" "" { target c++14_down } }
+  E e1 { 5 };          // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  E e2 { -1 };         // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  E e3 { 5.0 };                // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  E e4 { 5.2 };                // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  B b2 = { 7 };                // { dg-error "invalid conversion from 'int' to 'B'" }
+  C c2 = { C { 8 } };  // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
+
+  D *d7 = new D { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
+  E *e5 = new E { -4 };        // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  bar ({ 10 });                // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+  bar (E { 9 });       // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  V v1 = { { 11 } };   // { dg-error "braces around scalar initializer for type 'E'" }
+  V v2 = { E { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  V v3 = { E { 5.0 } };        // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  V v4 = { 13 };       // { dg-error "cannot convert 'int' to 'E' in initialization" }
+  if (B b3 { 5 })      // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+    ;
+  if (B b4 { 4.0 })    // { dg-error "cannot convert 'double' to 'B' in initialization" "" { target c++14_down } }
+    ;                  // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1 }
+  C c3 { 8L };         // { dg-error "cannot convert 'long int' to 'C' in initialization" "" { target c++14_down } }
+  B b4 {short (c + 5)};        // { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
+  B b5 {c + 5};                // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
+  C c4 { ll };         // { dg-error "cannot convert 'long long int' to 'C' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
+  C c5 {short (c + 5)};        // { dg-error "cannot convert 'short int' to 'C' in initialization" "" { target c++14_down } }
+  C c6 {c + 5};                // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
+}
+
+struct U
+{
+  U () : e { 5 } {}    // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+  U (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  U (float) : e({ 6 }) {}// { dg-error "list-initializer for non-class type must not be parenthesized" }
+                       // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target *-*-* } .-1 }
+  E e;
+};
+
+struct W
+{
+  A a { 5 };           // { dg-error "invalid conversion from 'int' to 'A'" }
+  B b { 6 };           // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+  C c { 3.0f };                // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-1 }
+  D d = { 7 };         // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" }
+};
+
+template <int N>
+void
+foo2 ()
+{
+  A a1 { 5 };          // { dg-error "invalid conversion from 'int' to 'A'" }
+  B b1 { 7 };          // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+  C c1 { s };
+  D d1 { D(t) };       // { dg-error "invalid cast from type 'T' to type 'D'" }
+  D d2 { t };          // { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+                       // { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+  D d3 { 9 };          // { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+  D d4 { l };          // { dg-error "cannot convert 'long int' to 'D' in initialization" "" { target c++14_down } }
+  D d5 { D(l) };
+  D d6 { G };          // { dg-error "cannot convert 'A' to 'D' in initialization" "" { target c++14_down } }
+  E e1 { 5 };          // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  E e2 { -1 };         // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  E e3 { 5.0 };                // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  E e4 { 5.2 };                // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  B b2 = { 7 };                // { dg-error "invalid conversion from 'int' to 'B'" }
+  C c2 = { C { 8 } };  // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
+  D *d7 = new D { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
+  E *e5 = new E { -4 };        // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  bar ({ 10 });                // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+  bar (E { 9 });       // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  V v1 = { { 11 } };   // { dg-error "braces around scalar initializer for type 'E'" }
+  V v2 = { E { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  V v3 = { E { 5.0 } };        // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  V v4 = { 13 };       // { dg-error "cannot convert 'int' to 'E' in initialization" }
+  if (B b3 { 5 })      // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+    ;
+  if (B b4 { 4.0 })    // { dg-error "cannot convert 'double' to 'B' in initialization" "" { target c++14_down } }
+    ;                  // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1 }
+  C c3 { 8L };         // { dg-error "cannot convert 'long int' to 'C' in initialization" "" { target c++14_down } }
+  B b4 {short (c + 5)};        // { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
+  B b5 {c + 5};                // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
+  C c4 { ll };         // { dg-error "cannot convert 'long long int' to 'C' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
+  C c5 {short (c + 5)};        // { dg-error "cannot convert 'short int' to 'C' in initialization" "" { target c++14_down } }
+  C c6 {c + 5};                // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
+}
+
+template <int N>
+struct U2
+{
+  U2 () : e { 5 } {}   // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+  U2 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  U2 (float) : e({ 6 }) {}
+  E e;
+};
+
+template <int N>
+struct W2
+{
+  A a { 5 };           // { dg-error "invalid conversion from 'int' to 'A'" "" { target *-*-* } .-2 }
+  B b { 6 };           // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-3 }
+  C c { 3.0f };                // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } .-4 }
+                       // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-5 }
+  D d = { 7 };         // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } .-6 }
+};
+
+template <typename H, typename I, typename J, typename K, typename L, typename M>
+void
+foo3 ()
+{
+  void bar3 (L);
+  H a1 { 5 };          // { dg-error "invalid conversion from 'int' to 'A'" }
+  I b1 { 7 };          // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+  J c1 { s };
+  K d1 { K(t) };       // { dg-error "invalid cast from type 'T' to type 'D'" }
+  K d2 { t };          // { dg-error "cannot convert 'T' to 'D' in initialization" "" { target c++14_down } }
+                       // { dg-error "invalid cast from type 'T' to type 'D'" "" { target c++1z } .-1 }
+  K d3 { 9 };          // { dg-error "cannot convert 'int' to 'D' in initialization" "" { target c++14_down } }
+  K d4 { l };          // { dg-error "cannot convert 'long int' to 'D' in initialization" "" { target c++14_down } }
+  K d5 { K(l) };
+  K d6 { G };          // { dg-error "cannot convert 'A' to 'D' in initialization" "" { target c++14_down } }
+  L e1 { 5 };          // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  L e2 { -1 };         // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '-1' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  L e3 { 5.0 };                // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  L e4 { 5.2 };                // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.\[0-9]*e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  I b2 = { 7 };                // { dg-error "invalid conversion from 'int' to 'B'" }
+  J c2 = { J { 8 } };  // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
+  K *d7 = new K { 9 }; // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target c++14_down } }
+  L *e5 = new L { -4 };        // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '-4' from 'int' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  bar3 ({ 10 });       // { dg-error "cannot convert \[^\n\r]* to 'E' for argument" }
+  bar3 (E { 9 });      // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  M v1 = { { 11 } };   // { dg-error "braces around scalar initializer for type 'E'" }
+  M v2 = { L { 12 } }; // { dg-error "cannot convert 'int' to 'E' in initialization" "" { target c++14_down } }
+  M v3 = { L { 5.0 } };        // { dg-error "cannot convert 'double' to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  M v4 = { 13 };       // { dg-error "cannot convert 'int' to 'E' in initialization" }
+  if (I b3 { 5 })      // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+    ;
+  if (I b4 { 4.0 })    // { dg-error "cannot convert 'double' to 'B' in initialization" "" { target c++14_down } }
+    ;                  // { dg-error "narrowing conversion of '4.0e.0' from 'double' to 'short int' inside" "" { target c++1z } .-1 }
+  J c3 { 8L };         // { dg-error "cannot convert 'long int' to 'C' in initialization" "" { target c++14_down } }
+  I b4 {short (c + 5)};        // { dg-error "invalid conversion from 'short int' to 'B'" "" { target c++14_down } }
+  I b5 {c + 5};                // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of \[^\n\r]* from 'int' to 'short int' inside" "" { target c++1z } .-1 }
+  J c4 { ll };         // { dg-error "cannot convert 'long long int' to 'C' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of 'll' from 'long long int' to 'int' inside" "" { target c++1z } .-1 }
+  J c5 {short (c + 5)};        // { dg-error "cannot convert 'short int' to 'C' in initialization" "" { target c++14_down } }
+  J c6 {c + 5};                // { dg-error "cannot convert 'int' to 'C' in initialization" "" { target c++14_down } }
+}
+
+template <typename L>
+struct U3
+{
+  U3 () : e { 5 } {}   // { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+  U3 (int) : e { 5.0 } {}// { dg-error "cannot convert \[^\n\r]* to 'E' in initialization" "" { target c++14_down } }
+                       // { dg-error "narrowing conversion of '5.0e.0' from 'double' to 'unsigned char' inside" "" { target c++1z } .-1 }
+  U3 (float) : e({ 6 }) {}
+  L e;
+};
+
+template <typename H, typename I, typename J, typename K>
+struct W3
+{
+  H a { 5 };           // { dg-error "invalid conversion from 'int' to 'A'" "" { target *-*-* } .-2 }
+  I b { 6 };           // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-3 }
+  J c { 3.0f };                // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } .-4 }
+                       // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-5 }
+  K d = { 7 };         // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } .-6 }
+};
+
+void
+test ()
+{
+  foo2<0> ();
+  U2<0> u20;
+  U2<1> u21 (5);
+  W2<0> w2;            // { dg-error "invalid conversion from 'int' to 'A'" }
+                       // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-1 }
+                       // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } .-2 }
+                       // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-3 }
+                       // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } .-4 }
+  foo3<A, B, C, D, E, V> ();
+  U3<E> u30;
+  U3<E> u31 (5);
+  W3<A, B, C, D> w3;   // { dg-error "invalid conversion from 'int' to 'A'" }
+                       // { dg-error "invalid conversion from 'int' to 'B'" "" { target c++14_down } .-1 }
+                       // { dg-error "cannot convert \[^\n\r]* to 'C' in initialization" "" { target c++14_down } .-2 }
+                       // { dg-error "narrowing conversion of '3.0e.0f' from 'float' to 'int' inside" "" { target c++1z } .-3 }
+                       // { dg-error "cannot convert \[^\n\r]* to 'D' in initialization" "" { target *-*-* } .-4 }
+}