SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_volatile,
cxx_dialect >= cxx20 && warn_deprecated);
+ /* -Wdeprecated-enum-enum-conversion is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_enum_enum_conv,
+ cxx_dialect >= cxx20 && warn_deprecated);
+
+ /* -Wdeprecated-enum-float-conversion is enabled by default in C++20. */
+ SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+ warn_deprecated_enum_float_conv,
+ cxx_dialect >= cxx20 && warn_deprecated);
+
/* Declone C++ 'structors if -Os. */
if (flag_declone_ctor_dtor == -1)
flag_declone_ctor_dtor = optimize_size;
Mark implicitly-declared copy operations as deprecated if the class has a
user-provided copy operation or destructor.
+Wdeprecated-enum-enum-conversion
+C++ ObjC++ Var(warn_deprecated_enum_enum_conv) Warning
+Warn about deprecated arithmetic conversions on operands of enumeration types.
+
+Wdeprecated-enum-float-conversion
+C++ ObjC++ Var(warn_deprecated_enum_float_conv) Warning
+Warn about deprecated arithmetic conversions on operands where one is of enumeration
+type and the other is of a floating-point type.
+
Wdesignated-init
C ObjC Var(warn_designated_init) Init(1) Warning
Warn about positional initialization of structs requiring designated initializers.
Warn about comparison of different enum types.
Wenum-conversion
-C ObjC Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C ObjC,Wextra)
+C ObjC C++ ObjC++ Var(warn_enum_conversion) Init(0) Warning LangEnabledBy(C ObjC,Wextra)
Warn about implicit conversion of enum types.
Werror
"in conditional expression: %qT vs %qT",
arg2_type, arg3_type);
}
- else if (extra_warnings
+ else if ((complain & tf_warning)
+ && warn_deprecated_enum_float_conv
+ && ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
+ && TREE_CODE (arg3_type) == REAL_TYPE)
+ || (TREE_CODE (arg2_type) == REAL_TYPE
+ && TREE_CODE (arg3_type) == ENUMERAL_TYPE)))
+ {
+ if (TREE_CODE (arg2_type) == ENUMERAL_TYPE)
+ warning_at (loc, OPT_Wdeprecated_enum_float_conversion,
+ "conditional expression between enumeration type "
+ "%qT and floating-point type %qT is deprecated",
+ arg2_type, arg3_type);
+ else
+ warning_at (loc, OPT_Wdeprecated_enum_float_conversion,
+ "conditional expression between floating-point "
+ "type %qT and enumeration type %qT is deprecated",
+ arg2_type, arg3_type);
+ }
+ else if ((extra_warnings || warn_enum_conversion)
&& ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& !same_type_p (arg3_type, type_promotes_to (arg2_type)))
|| (TREE_CODE (arg3_type) == ENUMERAL_TYPE
&& !same_type_p (arg2_type,
type_promotes_to (arg3_type)))))
- {
- if (complain & tf_warning)
- warning_at (loc, OPT_Wextra, "enumerated and non-enumerated "
- "type in conditional expression");
- }
+ {
+ if (complain & tf_warning)
+ {
+ enum opt_code opt = (warn_enum_conversion
+ ? OPT_Wenum_conversion
+ : OPT_Wextra);
+ warning_at (loc, opt, "enumerated and "
+ "non-enumerated type in conditional expression");
+ }
+ }
arg2 = perform_implicit_conversion (result_type, arg2, complain);
arg3 = perform_implicit_conversion (result_type, arg3, complain);
}
}
+/* Warn about [expr.arith.conv]/2: If one operand is of enumeration type and
+ the other operand is of a different enumeration type or a floating-point
+ type, this behavior is deprecated ([depr.arith.conv.enum]). CODE is the
+ code of the binary operation, TYPE0 and TYPE1 are the types of the operands,
+ and LOC is the location for the whole binary expression.
+ TODO: Consider combining this with -Wenum-compare in build_new_op_1. */
+
+static void
+do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0,
+ tree type1)
+{
+ if (TREE_CODE (type0) == ENUMERAL_TYPE
+ && TREE_CODE (type1) == ENUMERAL_TYPE
+ && TYPE_MAIN_VARIANT (type0) != TYPE_MAIN_VARIANT (type1))
+ {
+ /* In C++20, -Wdeprecated-enum-enum-conversion is on by default.
+ Otherwise, warn if -Wenum-conversion is on. */
+ enum opt_code opt;
+ if (warn_deprecated_enum_enum_conv)
+ opt = OPT_Wdeprecated_enum_enum_conversion;
+ else if (warn_enum_conversion)
+ opt = OPT_Wenum_conversion;
+ else
+ return;
+
+ switch (code)
+ {
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ /* Comparisons are handled by -Wenum-compare. */
+ return;
+ case SPACESHIP_EXPR:
+ /* This is invalid, don't warn. */
+ return;
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ warning_at (loc, opt, "bitwise operation between different "
+ "enumeration types %qT and %qT is deprecated",
+ type0, type1);
+ return;
+ default:
+ warning_at (loc, opt, "arithmetic between different enumeration "
+ "types %qT and %qT is deprecated", type0, type1);
+ return;
+ }
+ }
+ else if ((TREE_CODE (type0) == ENUMERAL_TYPE
+ && TREE_CODE (type1) == REAL_TYPE)
+ || (TREE_CODE (type0) == REAL_TYPE
+ && TREE_CODE (type1) == ENUMERAL_TYPE))
+ {
+ const bool enum_first_p = TREE_CODE (type0) == ENUMERAL_TYPE;
+ /* In C++20, -Wdeprecated-enum-float-conversion is on by default.
+ Otherwise, warn if -Wenum-conversion is on. */
+ enum opt_code opt;
+ if (warn_deprecated_enum_float_conv)
+ opt = OPT_Wdeprecated_enum_float_conversion;
+ else if (warn_enum_conversion)
+ opt = OPT_Wenum_conversion;
+ else
+ return;
+
+ switch (code)
+ {
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ if (enum_first_p)
+ warning_at (loc, opt, "comparison of enumeration type %qT with "
+ "floating-point type %qT is deprecated",
+ type0, type1);
+ else
+ warning_at (loc, opt, "comparison of floating-point type %qT "
+ "with enumeration type %qT is deprecated",
+ type0, type1);
+ return;
+ default:
+ if (enum_first_p)
+ warning_at (loc, opt, "arithmetic between enumeration type %qT "
+ "and floating-point type %qT is deprecated",
+ type0, type1);
+ else
+ warning_at (loc, opt, "arithmetic between floating-point type %qT "
+ "and enumeration type %qT is deprecated",
+ type0, type1);
+ return;
+ }
+ }
+}
+
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
LOCATION is the location_t of the operator in the source code.
{
result_type = cp_common_type (type0, type1);
if (complain & tf_warning)
- do_warn_double_promotion (result_type, type0, type1,
- "implicit conversion from %qH to %qI "
- "to match other operand of binary "
- "expression",
- location);
+ {
+ do_warn_double_promotion (result_type, type0, type1,
+ "implicit conversion from %qH to %qI "
+ "to match other operand of binary "
+ "expression",
+ location);
+ do_warn_enum_conversions (location, code, TREE_TYPE (orig_op0),
+ TREE_TYPE (orig_op1));
+ }
}
if (code == SPACESHIP_EXPR)
-Wno-conversion-null -Wctad-maybe-unsupported @gol
-Wctor-dtor-privacy -Wno-delete-incomplete @gol
-Wdelete-non-virtual-dtor -Wdeprecated-copy -Wdeprecated-copy-dtor @gol
+-Wno-deprecated-enum-enum-conversion -Wno-deprecated-enum-float-conversion @gol
-Weffc++ -Wextra-semi -Wno-inaccessible-base @gol
-Wno-inherited-variadic-ctor -Wno-init-list-lifetime @gol
-Wno-invalid-offsetof -Wno-literal-suffix -Wmismatched-tags @gol
@option{-Wdeprecated-copy-dtor}, also deprecate if the class has a
user-provided destructor.
+@item -Wno-deprecated-enum-enum-conversion @r{(C++ and Objective-C++ only)}
+@opindex Wdeprecated-enum-enum-conversion
+@opindex Wno-deprecated-enum-enum-conversion
+Disable the warning about the case when the usual arithmetic conversions
+are applied on operands where one is of enumeration type and the other is
+of a different enumeration type. This conversion was deprecated in C++20.
+For example:
+
+@smallexample
+enum E1 @{ e @};
+enum E2 @{ f @};
+int k = f - e;
+@end smallexample
+
+@option{-Wdeprecated-enum-enum-conversion} is enabled by default with
+@option{-std=c++20}. In pre-C++20 dialects, this warning can be enabled
+by @option{-Wenum-conversion}.
+
+@item -Wno-deprecated-enum-float-conversion @r{(C++ and Objective-C++ only)}
+@opindex Wdeprecated-enum-float-conversion
+@opindex Wno-deprecated-enum-float-conversion
+Disable the warning about the case when the usual arithmetic conversions
+are applied on operands where one is of enumeration type and the other is
+of a floating-point type. This conversion was deprecated in C++20. For
+example:
+
+@smallexample
+enum E1 @{ e @};
+enum E2 @{ f @};
+bool b = e <= 3.7;
+@end smallexample
+
+@option{-Wdeprecated-enum-float-conversion} is enabled by default with
+@option{-std=c++20}. In pre-C++20 dialects, this warning can be enabled
+by @option{-Wenum-conversion}.
+
@item -Wno-init-list-lifetime @r{(C++ and Objective-C++ only)}
@opindex Winit-list-lifetime
@opindex Wno-init-list-lifetime
-Wcomment @gol
-Wduplicate-decl-specifier @r{(C and Objective-C only)} @gol
-Wenum-compare @r{(in C/ObjC; this is on by default in C++)} @gol
--Wenum-conversion @r{in C/ObjC;} @gol
-Wformat @gol
-Wformat-overflow @gol
-Wformat-truncation @gol
-Wcast-function-type @gol
-Wdeprecated-copy @r{(C++ only)} @gol
-Wempty-body @gol
+-Wenum-conversion @r{(C only)} @gol
-Wignored-qualifiers @gol
-Wimplicit-fallthrough=3 @gol
-Wmissing-field-initializers @gol
diagnosed and the warning is enabled by default. In C this warning is
enabled by @option{-Wall}.
-@item -Wenum-conversion @r{(C, Objective-C only)}
+@item -Wenum-conversion
@opindex Wenum-conversion
@opindex Wno-enum-conversion
Warn when a value of enumerated type is implicitly converted to a
-different enumerated type. This warning is enabled by @option{-Wextra}.
+different enumerated type. This warning is enabled by @option{-Wextra}
+in C@.
@item -Wjump-misses-init @r{(C, Objective-C only)}
@opindex Wjump-misses-init
ba.g(a); // OK
ba.h(a); // error, B<T>::h never defined
i(ba, a); // OK
- e1+e2+e3;
+ e1+e2+e3; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } }
}
--- /dev/null
+// PR c++/97573
+// { dg-do compile }
+// No special options. In C++20 (only), we should get the deprecated warnings
+// by default. -Wenum-compare is enabled by default so some of them will be
+// printed even pre-C++20.
+
+enum E1 { e } e1;
+enum E2 { f } e2;
+__extension__ static enum { } u1;
+__extension__ static enum { } u2;
+static double d;
+
+void
+conv ()
+{
+ bool b1 = e == e1;
+ bool b2 = e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ bool b3 = e == 0.0; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } }
+ bool b4 = 0.0 == f; // { dg-warning "comparison of floating-point type .double. with enumeration type .E2." "" { target c++20 } }
+ int n1 = true ? e : f; // { dg-warning "enumerated mismatch" }
+ int n2 = true ? e : 0.0; // { dg-warning "conditional expression between" "" { target c++20 } }
+}
+
+int
+enum_enum (bool b)
+{
+ int r = 0;
+ const E1 e1c = e;
+
+ r += e - e;
+ r += e - e1;
+ r += e - f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += f - e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } }
+
+ r += f + f;
+ r += f + e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } }
+ r += e + f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } }
+
+ r += e1 - e2; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += e1 - e1c;
+ r += e1c - e1;
+
+ r += e * f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += f * e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." "" { target c++20 } }
+ r += e * e;
+
+ r += e1 < e1c;
+ r += e < e1;
+ r += e1 < e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += e < f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += f < e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+
+ r += e1 == e1c;
+ r += e == e1;
+ r += e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += f == e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+ r += e1 == e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += e2 == e1; // { dg-warning "comparison between .enum E2. and .enum E1." }
+
+ r += b ? e1 : e1c;
+ r += b ? e1 : e;
+ r += b ? f : e; // { dg-warning "enumerated mismatch in conditional expression: .E2. vs .E1." }
+ r += b ? e1 : e2; // { dg-warning "enumerated mismatch in conditional expression: .E1. vs .E2." }
+
+ r += e | f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += e ^ f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += e & f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." "" { target c++20 } }
+ r += !e;
+ r += e1 | e;
+
+ r += e << f;
+ r += e >> f;
+ r += e || f;
+ r += e && f;
+ e1 = e1c;
+
+ // Anonymous enum.
+ r += u1 - u1;
+ r += u1 + u2; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } }
+ r += u1 * u2; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } }
+ r += u1 == u2; // { dg-warning "comparison between" }
+ r += u1 & u2; // { dg-warning "bitwise operation between different enumeration types" "" { target c++20 } }
+
+ return r;
+}
+
+double
+enum_float (bool b)
+{
+ double r = 0.0;
+
+ r += e1 - d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } }
+ r += d - e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ r += e1 + d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } }
+ r += d + e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ r += e1 * d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." "" { target c++20 } }
+ r += d * e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ r += u1 * d; // { dg-warning "arithmetic between enumeration type" "" { target c++20 } }
+ r += d * u1; // { dg-warning "arithmetic between floating-point type" "" { target c++20 } }
+
+ r += e1 < d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } }
+ r += d < e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." "" { target c++20 } }
+ r += d == e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." "" { target c++20 } }
+ r += e1 == d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." "" { target c++20 } }
+ r += u1 == d; // { dg-warning "comparison of enumeration type" "" { target c++20 } }
+ r += d == u1; // { dg-warning "comparison of floating-point type" "" { target c++20 } }
+
+ r += b ? e1 : d; // { dg-warning "conditional expression between enumeration type .E1. and floating-point type .double." "" { target c++20 } }
+ r += b ? d : e1; // { dg-warning "conditional expression between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ r += b ? d : u1; // { dg-warning "conditional expression between" "" { target c++20 } }
+ r += b ? u1 : d; // { dg-warning "conditional expression between" "" { target c++20 } }
+
+ // FIXME should be error
+ // e1 <=> d;
+
+ d += e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." "" { target c++20 } }
+ d = e1;
+
+ return r;
+}
--- /dev/null
+// PR c++/97573
+// { dg-do compile { target c++20 } }
+// { dg-options "-Wno-deprecated -Wno-enum-compare" }
+
+enum E1 { e } e1;
+enum E2 { f } e2;
+__extension__ static enum { } u1;
+__extension__ static enum { } u2;
+static double d;
+
+void
+conv ()
+{
+ bool b1 = e == e1;
+ bool b2 = e == f;
+ bool b3 = e == 0.0;
+ bool b4 = 0.0 == f;
+ int n1 = true ? e : f;
+ int n2 = true ? e : 0.0;
+}
+
+int
+enum_enum (bool b)
+{
+ int r = 0;
+ const E1 e1c = e;
+
+ r += e - e;
+ r += e - e1;
+ r += e - f;
+ r += f - e;
+
+ r += f + f;
+ r += f + e;
+ r += e + f;
+
+ r += e1 - e2;
+ r += e1 - e1c;
+ r += e1c - e1;
+
+ r += e * f;
+ r += f * e;
+ r += e * e;
+
+ r += e1 < e1c;
+ r += e < e1;
+ r += e1 < e2;
+ r += e < f;
+ r += f < e;
+
+ r += e1 == e1c;
+ r += e == e1;
+ r += e == f;
+ r += f == e;
+ r += e1 == e2;
+ r += e2 == e1;
+
+ r += b ? e1 : e1c;
+ r += b ? e1 : e;
+ r += b ? f : e;
+ r += b ? e1 : e2;
+
+ r += e | f;
+ r += e ^ f;
+ r += e & f;
+ r += !e;
+ r += e1 | e;
+
+ r += e << f;
+ r += e >> f;
+ r += e || f;
+ r += e && f;
+ e1 = e1c;
+
+ // Anonymous enum.
+ r += u1 - u1;
+ r += u1 + u2;
+ r += u1 * u2;
+ r += u1 == u2;
+ r += u1 & u2;
+
+ return r;
+}
+
+double
+enum_float (bool b)
+{
+ double r = 0.0;
+
+ r += e1 - d;
+ r += d - e1;
+ r += e1 + d;
+ r += d + e1;
+ r += e1 * d;
+ r += d * e1;
+ r += u1 * d;
+ r += d * u1;
+
+ r += e1 < d;
+ r += d < e1;
+ r += d == e1;
+ r += e1 == d;
+ r += u1 == d;
+ r += d == u1;
+
+ r += b ? e1 : d;
+ r += b ? d : e1;
+ r += b ? d : u1;
+ r += b ? u1 : d;
+
+ d += e1;
+ d = e1;
+
+ return r;
+}
--- /dev/null
+// PR c++/97573
+// { dg-do compile { target { c++17_down } } }
+// { dg-options "-Wenum-conversion" }
+
+enum E1 { e } e1;
+enum E2 { f } e2;
+__extension__ static enum { } u1;
+__extension__ static enum { } u2;
+static double d;
+
+void
+conv ()
+{
+ bool b1 = e == e1;
+ bool b2 = e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ bool b3 = e == 0.0; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." }
+ bool b4 = 0.0 == f; // { dg-warning "comparison of floating-point type .double. with enumeration type .E2." }
+ int n1 = true ? e : f; // { dg-warning "enumerated mismatch" }
+ int n2 = true ? e : 0.0; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+}
+
+int
+enum_enum (bool b)
+{
+ int r = 0;
+ const E1 e1c = e;
+
+ r += e - e;
+ r += e - e1;
+ r += e - f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." }
+ r += f - e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." }
+
+ r += f + f;
+ r += f + e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." }
+ r += e + f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." }
+
+ r += e1 - e2; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." }
+ r += e1 - e1c;
+ r += e1c - e1;
+
+ r += e * f; // { dg-warning "arithmetic between different enumeration types .E1. and .E2." }
+ r += f * e; // { dg-warning "arithmetic between different enumeration types .E2. and .E1." }
+ r += e * e;
+
+ r += e1 < e1c;
+ r += e < e1;
+ r += e1 < e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += e < f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += f < e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+
+ r += e1 == e1c;
+ r += e == e1;
+ r += e == f; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += f == e; // { dg-warning "comparison between .enum E2. and .enum E1." }
+ r += e1 == e2; // { dg-warning "comparison between .enum E1. and .enum E2." }
+ r += e2 == e1; // { dg-warning "comparison between .enum E2. and .enum E1." }
+
+ r += b ? e1 : e1c;
+ r += b ? e1 : e;
+ r += b ? f : e; // { dg-warning "enumerated mismatch in conditional expression: .E2. vs .E1." }
+ r += b ? e1 : e2; // { dg-warning "enumerated mismatch in conditional expression: .E1. vs .E2." }
+
+ r += e | f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." }
+ r += e ^ f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." }
+ r += e & f; // { dg-warning "bitwise operation between different enumeration types .E1. and .E2." }
+ r += !e;
+ r += e1 | e;
+
+ r += e << f;
+ r += e >> f;
+ r += e || f;
+ r += e && f;
+ e1 = e1c;
+
+ // Anonymous enum.
+ r += u1 - u1;
+ r += u1 + u2; // { dg-warning "arithmetic between different enumeration types" }
+ r += u1 * u2; // { dg-warning "arithmetic between different enumeration types" }
+ r += u1 == u2; // { dg-warning "comparison between" }
+ r += u1 & u2; // { dg-warning "bitwise operation between different enumeration types" }
+
+ return r;
+}
+
+double
+enum_float (bool b)
+{
+ double r = 0.0;
+
+ r += e1 - d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." }
+ r += d - e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." }
+ r += e1 + d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." }
+ r += d + e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." }
+ r += e1 * d; // { dg-warning "arithmetic between enumeration type .E1. and floating-point type .double." }
+ r += d * e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." }
+ r += u1 * d; // { dg-warning "arithmetic between enumeration type" }
+ r += d * u1; // { dg-warning "arithmetic between floating-point type" }
+
+ r += e1 < d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." }
+ r += d < e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." }
+ r += d == e1; // { dg-warning "comparison of floating-point type .double. with enumeration type .E1." }
+ r += e1 == d; // { dg-warning "comparison of enumeration type .E1. with floating-point type .double." }
+ r += u1 == d; // { dg-warning "comparison of enumeration type" }
+ r += d == u1; // { dg-warning "comparison of floating-point type" }
+
+ r += b ? e1 : d; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+ r += b ? d : e1; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+ r += b ? d : u1; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+ r += b ? u1 : d; // { dg-warning "enumerated and non-enumerated type in conditional expression" }
+
+ d += e1; // { dg-warning "arithmetic between floating-point type .double. and enumeration type .E1." }
+ d = e1;
+
+ return r;
+}
S::F y; // { dg-warning "'F' is deprecated" }
y = S::f;
- return x + y;
+ return x + y; // { dg-warning "arithmetic between different enumeration types" "" { target c++20 } }
}