Hi,

following up to a short off-line exchange with Nathan, I'm sending a reworked patch which - among other things - avoids regressing on the second testcase (cpp0x/enum36.C). Tested x86_64-linux.

Thanks,
Paolo.

////////////////////
/cp
2017-10-23  Mukesh Kapoor  <mukesh.kap...@oracle.com>
            Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/82307
        * cvt.c (type_promotes_to): Implement C++17, 7.6/4, about unscoped
        enumeration type whose underlying type is fixed.

/testsuite
2017-10-23  Mukesh Kapoor  <mukesh.kap...@oracle.com>
            Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/82307
        * g++.dg/cpp0x/enum35.C: New.
        * g++.dg/cpp0x/enum36.C: Likewise.
Index: cp/cvt.c
===================================================================
--- cp/cvt.c    (revision 254005)
+++ cp/cvt.c    (working copy)
@@ -1834,12 +1834,27 @@ type_promotes_to (tree type)
           || type == char32_type_node
           || type == wchar_type_node)
     {
+      tree prom = type;
+
+      if (TREE_CODE (type) == ENUMERAL_TYPE)
+       {
+         prom = ENUM_UNDERLYING_TYPE (prom);
+         if (!ENUM_IS_SCOPED (type)
+             && ENUM_FIXED_UNDERLYING_TYPE_P (type))
+           {
+             /* ISO C++17, 7.6/4.  A prvalue of an unscoped enumeration type
+                whose underlying type is fixed (10.2) can be converted to a
+                prvalue of its underlying type. Moreover, if integral promotion
+                can be applied to its underlying type, a prvalue of an unscoped
+                enumeration type whose underlying type is fixed can also be 
+                converted to a prvalue of the promoted underlying type.  */
+             return type_promotes_to (prom);
+           }
+       }
+
       int precision = MAX (TYPE_PRECISION (type),
                           TYPE_PRECISION (integer_type_node));
       tree totype = c_common_type_for_size (precision, 0);
-      tree prom = type;
-      if (TREE_CODE (prom) == ENUMERAL_TYPE)
-       prom = ENUM_UNDERLYING_TYPE (prom);
       if (TYPE_UNSIGNED (prom)
          && ! int_fits_type_p (TYPE_MAX_VALUE (prom), totype))
        prom = c_common_type_for_size (precision, 1);
Index: testsuite/g++.dg/cpp0x/enum35.C
===================================================================
--- testsuite/g++.dg/cpp0x/enum35.C     (nonexistent)
+++ testsuite/g++.dg/cpp0x/enum35.C     (working copy)
@@ -0,0 +1,14 @@
+// PR c++/82307
+// { dg-do run { target c++11 } }
+
+#include <cassert>
+
+enum : unsigned long long { VAL };
+
+bool foo (unsigned long long) { return true; }
+bool foo (int) { return false; }
+
+int main()
+{
+  assert (foo(VAL));
+}
Index: testsuite/g++.dg/cpp0x/enum36.C
===================================================================
--- testsuite/g++.dg/cpp0x/enum36.C     (nonexistent)
+++ testsuite/g++.dg/cpp0x/enum36.C     (working copy)
@@ -0,0 +1,14 @@
+// PR c++/82307
+// { dg-do run { target c++11 } }
+
+#include <cassert>
+
+enum : short { VAL };
+
+bool foo (int) { return true; }
+bool foo (unsigned long long) { return false; }
+
+int main()
+{
+  assert (foo (VAL));
+}

Reply via email to