aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-05-25 19:01:02 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-05-25 19:01:02 -0400
commit550a799d5383a73b52192b71b9234c3efb8be6a9 (patch)
tree583bc6fb72a9ca524446f8aa253888d047949f48 /gcc
parent85057983ac31039dff4e0963b789ee6684351868 (diff)
downloadgcc-550a799d5383a73b52192b71b9234c3efb8be6a9.zip
gcc-550a799d5383a73b52192b71b9234c3efb8be6a9.tar.gz
gcc-550a799d5383a73b52192b71b9234c3efb8be6a9.tar.bz2
re PR c++/38064 ([c++0x] operator== doesn't work for enum classes)
PR c++/38064 * typeck.c (cp_build_binary_op): Allow ENUMERAL_TYPE in arithmetic comparisons. (cp_common_type): Handle scoped enums. * call.c (promoted_arithmetic_type_p): Don't use INTEGRAL_TYPE_P. (add_builtin_candidate, add_builtin_candidates): Likewise. (convert_like_real): Likewise. * class.c (check_bitfield_decl): Likewise. * decl.c (check_static_variable_definition): Likewise. (compute_array_index_type): Likewise. * decl2.c (grokbitfield): Likewise. * init.c (build_new_1): Likewise. * pt.c (convert_nontype_argument): Likewise. (current_instantiation): Likewise. * tree.c (pod_type_p): Likewise. * typeck.c (build_static_cast_1): Likewise. (build_reinterpret_cast_1): Likewise. From-SVN: r147854
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog21
-rw-r--r--gcc/cp/call.c25
-rw-r--r--gcc/cp/class.c2
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/cp/pt.c6
-rw-r--r--gcc/cp/tree.c2
-rw-r--r--gcc/cp/typeck.c36
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum3.C17
11 files changed, 89 insertions, 33 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index aeab9a1..7e22a4f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,24 @@
+2009-05-22 Jason Merrill <jason@redhat.com>
+
+ PR c++/38064
+ * typeck.c (cp_build_binary_op): Allow ENUMERAL_TYPE in
+ arithmetic comparisons.
+ (cp_common_type): Handle scoped enums.
+
+ * call.c (promoted_arithmetic_type_p): Don't use INTEGRAL_TYPE_P.
+ (add_builtin_candidate, add_builtin_candidates): Likewise.
+ (convert_like_real): Likewise.
+ * class.c (check_bitfield_decl): Likewise.
+ * decl.c (check_static_variable_definition): Likewise.
+ (compute_array_index_type): Likewise.
+ * decl2.c (grokbitfield): Likewise.
+ * init.c (build_new_1): Likewise.
+ * pt.c (convert_nontype_argument): Likewise.
+ (current_instantiation): Likewise.
+ * tree.c (pod_type_p): Likewise.
+ * typeck.c (build_static_cast_1): Likewise.
+ (build_reinterpret_cast_1): Likewise.
+
2009-05-22 Richard Guenther <rguenther@suse.de>
PR middle-end/38964
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 0d5ae6a..a9c0367 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1781,7 +1781,7 @@ promoted_arithmetic_type_p (tree type)
(including e.g. int and long but excluding e.g. char).
Similarly, the term promoted arithmetic type refers to promoted
integral types plus floating types. */
- return ((INTEGRAL_TYPE_P (type)
+ return ((CP_INTEGRAL_TYPE_P (type)
&& same_type_p (type_promotes_to (type), type))
|| TREE_CODE (type) == REAL_TYPE);
}
@@ -1883,7 +1883,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
T operator~(T); */
case BIT_NOT_EXPR:
- if (INTEGRAL_TYPE_P (type1))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1))
break;
return;
@@ -1953,7 +1953,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
case MINUS_EXPR:
if (TYPE_PTROB_P (type1) && TYPE_PTROB_P (type2))
break;
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1)
+ && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
@@ -2013,12 +2014,12 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
case ARRAY_REF:
- if (INTEGRAL_TYPE_P (type1) && TYPE_PTROB_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && TYPE_PTROB_P (type2))
{
type1 = ptrdiff_type_node;
break;
}
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
@@ -2042,7 +2043,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
case BIT_XOR_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
- if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
break;
return;
@@ -2087,7 +2088,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
{
case PLUS_EXPR:
case MINUS_EXPR:
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
@@ -2104,7 +2105,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
case BIT_XOR_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
- if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
break;
return;
@@ -2329,7 +2330,7 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
type = TYPE_MAIN_VARIANT (type_decays_to (type));
if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
types[i] = tree_cons (NULL_TREE, type, types[i]);
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
}
@@ -2346,9 +2347,9 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
if (i != 0 || ! ref1)
{
type = TYPE_MAIN_VARIANT (type_decays_to (type));
- if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
+ if (enum_p && UNSCOPED_ENUM_P (type))
types[i] = tree_cons (NULL_TREE, type, types[i]);
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
}
types[i] = tree_cons (NULL_TREE, type, types[i]);
@@ -4755,7 +4756,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (inner >= 0)
{
expr = decl_constant_value (expr);
- if (expr == null_node && INTEGRAL_TYPE_P (totype))
+ if (expr == null_node && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype))
/* If __null has been converted to an integer type, we do not
want to warn about uses of EXPR as an integer, rather than
as a pointer. */
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 049e980..20ceb65 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2705,7 +2705,7 @@ check_bitfield_decl (tree field)
DECL_INITIAL (field) = NULL_TREE;
/* Detect invalid bit-field type. */
- if (!INTEGRAL_TYPE_P (type))
+ if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
error ("bit-field %q+#D with non-integral type", field);
w = error_mark_node;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 433d089..a626a71 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7154,7 +7154,7 @@ check_static_variable_definition (tree decl, tree type)
error ("ISO C++ forbids in-class initialization of non-const "
"static member %qD",
decl);
- else if (!INTEGRAL_TYPE_P (type))
+ else if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
pedwarn (input_location, OPT_pedantic, "ISO C++ forbids initialization of member constant "
"%qD of non-integral type %qT", decl, type);
@@ -7177,7 +7177,7 @@ compute_array_index_type (tree name, tree size)
type = TREE_TYPE (size);
/* The array bound must be an integer type. */
- if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
+ if (!dependent_type_p (type) && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
{
if (name)
error ("size of array %qD has non-integral type %qT", name, type);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 1b8aa49..d368ea8 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -964,7 +964,7 @@ grokbitfield (const cp_declarator *declarator,
if (TREE_CODE (value) == VOID_TYPE)
return void_type_node;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
+ if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value))
&& (POINTER_TYPE_P (value)
|| !dependent_type_p (TREE_TYPE (value))))
{
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 25cfd52..a99983e 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1963,7 +1963,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
{
tree placement_arg = CALL_EXPR_ARG (alloc_call, 1);
- if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))
|| VOID_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg))))
{
placement_expr = get_target_expr (placement_first);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ed6b031..f8a6e7e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -4415,9 +4415,9 @@ convert_nontype_argument (tree type, tree expr)
For a non-type template-parameter of integral or enumeration type,
integral promotions (_conv.prom_) and integral conversions
(_conv.integral_) are applied. */
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
- if (!INTEGRAL_TYPE_P (expr_type))
+ if (!INTEGRAL_OR_ENUMERATION_TYPE_P (expr_type))
return error_mark_node;
expr = fold_decl_constant_value (expr);
@@ -16153,7 +16153,7 @@ current_instantiation (void)
static int
invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
{
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
return 0;
else if (POINTER_TYPE_P (type))
return 0;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8c51e0b..dece159 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2156,7 +2156,7 @@ pod_type_p (const_tree t)
if (t == error_mark_node)
return 1;
- if (INTEGRAL_TYPE_P (t))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (t))
return 1; /* integral, character or enumeral type */
if (FLOAT_TYPE_P (t))
return 1;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 074d619..d7fddb1 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -260,6 +260,19 @@ cp_common_type (tree t1, tree t2)
enum tree_code code2 = TREE_CODE (t2);
tree attributes;
+ /* In what follows, we slightly generalize the rules given in [expr] so
+ as to deal with `long long' and `complex'. First, merge the
+ attributes. */
+ attributes = (*targetm.merge_type_attributes) (t1, t2);
+
+ if (SCOPED_ENUM_P (t1) || SCOPED_ENUM_P (t2))
+ {
+ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ return build_type_attribute_variant (t1, attributes);
+ else
+ return NULL_TREE;
+ }
+
/* FIXME: Attributes. */
gcc_assert (ARITHMETIC_TYPE_P (t1)
|| TREE_CODE (t1) == VECTOR_TYPE
@@ -268,11 +281,6 @@ cp_common_type (tree t1, tree t2)
|| TREE_CODE (t2) == VECTOR_TYPE
|| UNSCOPED_ENUM_P (t2));
- /* In what follows, we slightly generalize the rules given in [expr] so
- as to deal with `long long' and `complex'. First, merge the
- attributes. */
- attributes = (*targetm.merge_type_attributes) (t1, t2);
-
/* If one type is complex, form the common type of the non-complex
components, then make that complex. Use T1 or T2 if it is the
required type. */
@@ -3636,9 +3644,9 @@ cp_build_binary_op (location_t location,
build_type = boolean_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE || code0 == ENUMERAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE))
short_compare = 1;
else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE)
|| (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1)))
@@ -3910,9 +3918,10 @@ cp_build_binary_op (location_t location,
break;
}
- if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+ || code0 == ENUMERAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE)))
+ || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE)))
arithmetic_types_p = 1;
else
{
@@ -5348,8 +5357,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
/* The effect of all that is that any conversion between any two
types which are integral, floating, or enumeration types can be
performed. */
- if ((INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type))
- && (INTEGRAL_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype)))
+ if ((INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ || SCALAR_FLOAT_TYPE_P (type))
+ && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
+ || SCALAR_FLOAT_TYPE_P (intype)))
{
expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
@@ -5649,7 +5660,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
}
else if (TREE_CODE (type) == VECTOR_TYPE)
return fold_if_not_in_template (convert_to_vector (type, expr));
- else if (TREE_CODE (intype) == VECTOR_TYPE && INTEGRAL_TYPE_P (type))
+ else if (TREE_CODE (intype) == VECTOR_TYPE
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
return fold_if_not_in_template (convert_to_integer (type, expr));
else
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 578bbee..03aa116 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-05-25 Jason Merrill <jason@redhat.com>
+
+ PR c++/38064
+ * g++.dg/cpp0x/enum3.C: New test.
+
2009-05-25 Richard Guenther <rguenther@suse.de>
PR tree-optimization/36327
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum3.C b/gcc/testsuite/g++.dg/cpp0x/enum3.C
new file mode 100644
index 0000000..5555ab2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum3.C
@@ -0,0 +1,17 @@
+// PR c++/38064
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+enum class E { elem };
+
+template <class T>
+void f (T t);
+
+bool f (bool b) { return b; }
+
+int main()
+{
+ E e = E::elem;
+ if (!f (e == E::elem))
+ return 1;
+}