Hi all, Jason,
thus, per the notes I left on the audit trail some time ago, this seems
to me a possible approach to reject this kind of invalid code. What do
you think?
Booted & tested x86_64-linux.
Thanks,
Paolo.
//////////////////////
Index: cp/call.c
===================================================================
--- cp/call.c (revision 201731)
+++ cp/call.c (working copy)
@@ -1314,7 +1314,8 @@ standard_conversion (tree to, tree from, tree expr
/* As an extension, allow conversion to complex type. */
else if (ARITHMETIC_TYPE_P (to))
{
- if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE)
+ if (! (INTEGRAL_CODE_P (fcode)
+ || (fcode == REAL_TYPE && !(flags & LOOKUP_NO_NON_INTEGRAL)))
|| SCOPED_ENUM_P (from))
return NULL;
conv = build_conv (ck_std, to, conv);
@@ -1681,7 +1682,7 @@ implicit_conversion (tree to, tree from, tree expr
resolution, or after we've chosen one. */
flags &= (LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION|LOOKUP_COPY_PARM
|LOOKUP_NO_TEMP_BIND|LOOKUP_NO_RVAL_BIND|LOOKUP_PREFER_RVALUE
- |LOOKUP_NO_NARROWING|LOOKUP_PROTECT);
+ |LOOKUP_NO_NARROWING|LOOKUP_PROTECT|LOOKUP_NO_NON_INTEGRAL);
/* FIXME: actually we don't want warnings either, but we can't just
have 'complain &= ~(tf_warning|tf_error)' because it would cause
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h (revision 201731)
+++ cp/cp-tree.h (working copy)
@@ -4510,6 +4510,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T
#define LOOKUP_EXPLICIT_TMPL_ARGS (LOOKUP_ALREADY_DIGESTED << 1)
/* Like LOOKUP_NO_TEMP_BIND, but also prevent binding to xvalues. */
#define LOOKUP_NO_RVAL_BIND (LOOKUP_EXPLICIT_TMPL_ARGS << 1)
+/* Used in case_conversion. */
+#define LOOKUP_NO_NON_INTEGRAL (LOOKUP_NO_RVAL_BIND << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
Index: cp/decl.c
===================================================================
--- cp/decl.c (revision 201731)
+++ cp/decl.c (working copy)
@@ -3103,7 +3103,9 @@ case_conversion (tree type, tree value)
{
if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
- value = perform_implicit_conversion (type, value, tf_warning_or_error);
+ value = (perform_implicit_conversion_flags
+ (type, value, tf_warning_or_error,
+ LOOKUP_IMPLICIT | LOOKUP_NO_NON_INTEGRAL));
}
return cxx_constant_value (value);
}
Index: testsuite/g++.dg/cpp0x/enum15.C
===================================================================
--- testsuite/g++.dg/cpp0x/enum15.C (revision 201726)
+++ testsuite/g++.dg/cpp0x/enum15.C (working copy)
@@ -15,6 +15,6 @@ void foo (A a, int i)
{
case A::Val0: break; // { dg-error "" }
case 1: break;
- case 2.0: break;
+ case 2.0: break; // { dg-error "" }
}
}
Index: testsuite/g++.dg/cpp0x/enum28.C
===================================================================
--- testsuite/g++.dg/cpp0x/enum28.C (revision 0)
+++ testsuite/g++.dg/cpp0x/enum28.C (working copy)
@@ -0,0 +1,17 @@
+// PR c++/51912
+// { dg-do compile { target c++11 } }
+
+constexpr double g() { return 2.0; }
+
+void f(int i)
+{
+ switch (i)
+ {
+ case 1.0:; // { dg-error "could not convert" }
+ }
+
+ switch (i)
+ {
+ case g():; // { dg-error "could not convert" }
+ }
+}