diff options
author | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-08-07 19:51:28 +0000 |
---|---|---|
committer | paolo <paolo@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-08-07 19:51:28 +0000 |
commit | 392214f61bf5995eee9480d8f54cc32093f0aee5 (patch) | |
tree | f8d388592ee3f6aa02f7d7dfeb975b4d0305f9a0 | |
parent | 1a4c5f5599fa06efd06698551395c8dcae82f493 (diff) | |
download | gcc-392214f61bf5995eee9480d8f54cc32093f0aee5.tar.gz |
/cp
2014-08-07 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/51312
* decl.c (build_enumerator): Handle class types with conversion
operators via perform_implicit_conversion_flags and
build_expr_type_conversion.
* cvt.c (build_expr_type_conversion): Replace pair of errors
with error + inform.
/testsuite
2014-08-07 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/51312
* g++.dg/cpp0x/enum29.C: New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@213736 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/cvt.c | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 30 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/enum29.C | 58 |
5 files changed, 100 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 38e8daefc06..0e70c5f7129 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2014-08-07 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/51312 + * decl.c (build_enumerator): Handle class types with conversion + operators via perform_implicit_conversion_flags and + build_expr_type_conversion. + + * cvt.c (build_expr_type_conversion): Replace pair of errors + with error + inform. + 2014-08-07 Jason Merrill <jason@redhat.com> PR c++/62043 diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 1dec9cc7f0e..7be4f311a35 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1658,8 +1658,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain) { error ("ambiguous default type conversion from %qT", basetype); - error (" candidate conversions include %qD and %qD", - winner, cand); + inform (input_location, + " candidate conversions include %qD and %qD", + winner, cand); } return error_mark_node; } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index acc1192eacf..bb6135b631f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -12966,14 +12966,32 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc) /* Validate and default VALUE. */ if (value != NULL_TREE) { - value = cxx_constant_value (value); + if (!ENUM_UNDERLYING_TYPE (enumtype)) + { + tree tmp_value = build_expr_type_conversion (WANT_INT | WANT_ENUM, + value, true); + if (tmp_value) + value = tmp_value; + } + else if (! INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value))) + value = perform_implicit_conversion_flags + (ENUM_UNDERLYING_TYPE (enumtype), value, tf_warning_or_error, + LOOKUP_IMPLICIT | LOOKUP_NO_NARROWING); - if (TREE_CODE (value) != INTEGER_CST - || ! INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value))) + if (value == error_mark_node) + value = NULL_TREE; + + if (value != NULL_TREE) { - error ("enumerator value for %qD is not an integer constant", - name); - value = NULL_TREE; + value = cxx_constant_value (value); + + if (TREE_CODE (value) != INTEGER_CST + || ! INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (value))) + { + error ("enumerator value for %qD is not an integer constant", + name); + value = NULL_TREE; + } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 7f1be38d154..16956b781ab 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-08-07 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/51312 + * g++.dg/cpp0x/enum29.C: New. + 2014-08-07 John David Anglin <danglin@gcc.gnu.org> * gcc.dg/atomic/c11-atomic-exec-4.c: Undefine _POSIX_C_SOURCE before diff --git a/gcc/testsuite/g++.dg/cpp0x/enum29.C b/gcc/testsuite/g++.dg/cpp0x/enum29.C new file mode 100644 index 00000000000..43a99aee673 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/enum29.C @@ -0,0 +1,58 @@ +// PR c++/51312 +// { dg-do compile { target c++11 } } + +struct X0 +{ + constexpr operator int() const { return 1; } +}; + +struct X1 +{ + enum RE1 { re1 = 1 }; + constexpr operator RE1() const { return re1; } +}; + +struct X2 +{ + constexpr operator int() const { return __INT_MAX__; } +}; + +struct X3 +{ + enum RE3 { re3 = __INT_MAX__ }; + constexpr operator RE3() const { return re3; } +}; + +struct X4 +{ + constexpr operator double() const { return 1.0; } +}; + +struct X5 +{ + constexpr operator int() const { return __INT_MAX__; } + constexpr operator unsigned() const { return __INT_MAX__ * 2U + 1; } +}; + +enum E0 { e0 = X0() }; +enum E1 { e1 = X1() }; +enum E2 { e2 = X2() }; +enum E3 { e3 = X3() }; +enum E4 { e4 = X4() }; // { dg-error "integer constant" } +enum E5 { e5 = X5() }; // { dg-error "ambiguous" } + +enum F0 : int { f0 = X0() }; +enum F1 : int { f1 = X1() }; +enum F2 : int { f2 = X2() }; +enum F3 : int { f3 = X3() }; +enum F4 : int { f4 = X4() }; // { dg-error "narrowing" } +enum F5 : int { f5 = X5() }; + +enum G0 : signed char { g0 = X0() }; +enum G1 : signed char { g1 = X1() }; +enum G2 : signed char { g2 = X2() }; // { dg-error "narrowing" } +// { dg-warning "overflow" "" { target *-*-* } 53 } +enum G3 : signed char { g3 = X3() }; // { dg-error "narrowing" } +// { dg-warning "overflow" "" { target *-*-* } 55 } +enum G4 : signed char { g4 = X4() }; // { dg-error "narrowing" } +enum G5 : signed char { g5 = X5() }; // { dg-error "ambiguous" } |