diff options
author | Marek Polacek <polacek@redhat.com> | 2020-10-28 19:02:29 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2020-10-29 14:06:13 -0400 |
commit | 79991e2348a864ace6ea2bf108a7502862f1129f (patch) | |
tree | a1208522e1a5783776514985cc2371947e4be5dc | |
parent | e1344fe7b6a96966281c78e46e777b456d5c2e19 (diff) | |
download | gcc-79991e2348a864ace6ea2bf108a7502862f1129f.zip gcc-79991e2348a864ace6ea2bf108a7502862f1129f.tar.gz gcc-79991e2348a864ace6ea2bf108a7502862f1129f.tar.bz2 |
c++: Reject float <=> enum.
As [depr.arith.conv.enum] says, these are ill-formed.
gcc/cp/ChangeLog:
* typeck.c (do_warn_enum_conversions): Don't warn for SPACESHIP_EXPR.
(cp_build_binary_op): Reject float <=> enum or enum <=> float. Use
CP_INTEGRAL_TYPE_P instead of INTEGRAL_OR_ENUMERATION_TYPE_P.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/enum-conv1.C: Remove unused code.
* g++.dg/cpp2a/spaceship-err5.C: New test.
-rw-r--r-- | gcc/cp/typeck.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/enum-conv1.C | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C | 23 |
3 files changed, 34 insertions, 5 deletions
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 7305310..d3b7016 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4512,6 +4512,9 @@ do_warn_enum_conversions (location_t loc, enum tree_code code, tree type0, "with enumeration type %qT is deprecated", type0, type1); return; + case SPACESHIP_EXPR: + /* This is invalid, don't warn. */ + return; default: if (enum_first_p) warning_at (loc, opt, "arithmetic between enumeration type %qT " @@ -5584,6 +5587,12 @@ cp_build_binary_op (const op_location_t &location, arithmetic conversions are applied to the operands." So we don't do arithmetic conversions if the operands both have enumeral type. */ result_type = NULL_TREE; + else if ((orig_code0 == ENUMERAL_TYPE && orig_code1 == REAL_TYPE) + || (orig_code0 == REAL_TYPE && orig_code1 == ENUMERAL_TYPE)) + /* [depr.arith.conv.enum]: Three-way comparisons between such operands + [where one is of enumeration type and the other is of a different + enumeration type or a floating-point type] are ill-formed. */ + result_type = NULL_TREE; if (result_type) { @@ -5598,12 +5607,12 @@ cp_build_binary_op (const op_location_t &location, type to a floating point type, the program is ill-formed. */ bool ok = true; if (TREE_CODE (result_type) == REAL_TYPE - && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op0))) + && CP_INTEGRAL_TYPE_P (orig_type0)) /* OK */; else if (!check_narrowing (result_type, orig_op0, complain)) ok = false; if (TREE_CODE (result_type) == REAL_TYPE - && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (orig_op1))) + && CP_INTEGRAL_TYPE_P (orig_type1)) /* OK */; else if (!check_narrowing (result_type, orig_op1, complain)) ok = false; diff --git a/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C b/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C index d4960f3..4571b5e 100644 --- a/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C +++ b/gcc/testsuite/g++.dg/cpp2a/enum-conv1.C @@ -110,9 +110,6 @@ enum_float (bool b) 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; diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C new file mode 100644 index 0000000..3dc2a0f --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-err5.C @@ -0,0 +1,23 @@ +// { dg-do compile { target c++20 } } +// Test [depr.arith.conv.enum] for <=>. + +#include <compare> + +enum E1 { e } e1; +enum E2 { f } e2; +static double d; + +void +g () +{ + void(e1 <=> e); + e1 <=> d; // { dg-error "invalid operands of types .E1. and .double." } + d <=> e1; // { dg-error "invalid operands of types .double. and .E1." } + e <=> d; // { dg-error "invalid operands of types .E1. and .double." } + d <=> e; // { dg-error "invalid operands of types .double. and .E1." } + + e <=> f; // { dg-error "invalid operands of types .E1. and .E2." } + f <=> e; // { dg-error "invalid operands of types .E2. and .E1." } + e1 <=> e2; // { dg-error "invalid operands of types .E1. and .E2." } + e2 <=> e1; // { dg-error "invalid operands of types .E2. and .E1." } +} |