aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-05-23 18:55:46 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-05-23 18:55:46 -0400
commit828fb3ba9958f3117680efb9ade199fc7e98f462 (patch)
tree4dab37634bd240e1a80cbc953bd868d0db79d860
parent0f6e664b85c971f7550db62f490ea7e261d40307 (diff)
downloadgcc-828fb3ba9958f3117680efb9ade199fc7e98f462.zip
gcc-828fb3ba9958f3117680efb9ade199fc7e98f462.tar.gz
gcc-828fb3ba9958f3117680efb9ade199fc7e98f462.tar.bz2
re PR c++/48106 ([C++0x] ICE with scoped enum with fixed underlying type)
PR c++/48106 * c-common.c (c_common_get_narrower): New. (shorten_binary_op, shorten_compare, warn_for_sign_compare): Use it. From-SVN: r174091
-rw-r--r--gcc/c-family/ChangeLog6
-rw-r--r--gcc/c-family/c-common.c41
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum14.C12
4 files changed, 54 insertions, 9 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 5044c07..593086e 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,9 @@
+2011-05-23 Jason Merrill <jason@redhat.com>
+
+ PR c++/48106
+ * c-common.c (c_common_get_narrower): New.
+ (shorten_binary_op, shorten_compare, warn_for_sign_compare): Use it.
+
2011-05-23 Nathan Froyd <froydnj@codesourcery.com>
* c-common.h (check_function_arguments): Tweak prototype of
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index fef8ded..b822553 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -1765,6 +1765,28 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
return false;
}
+/* Like tree.c:get_narrower, but retain conversion from C++0x scoped enum
+ to integral type. */
+
+static tree
+c_common_get_narrower (tree op, int *unsignedp_ptr)
+{
+ op = get_narrower (op, unsignedp_ptr);
+
+ if (TREE_CODE (TREE_TYPE (op)) == ENUMERAL_TYPE
+ && ENUM_IS_SCOPED (TREE_TYPE (op)))
+ {
+ /* C++0x scoped enumerations don't implicitly convert to integral
+ type; if we stripped an explicit conversion to a larger type we
+ need to replace it so common_type will still work. */
+ tree type = (lang_hooks.types.type_for_size
+ (TYPE_PRECISION (TREE_TYPE (op)),
+ TYPE_UNSIGNED (TREE_TYPE (op))));
+ op = fold_convert (type, op);
+ }
+ return op;
+}
+
/* This is a helper function of build_binary_op.
For certain operations if both args were extended from the same
@@ -1777,7 +1799,8 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
Eg, (short)-1 | (unsigned short)-1 is (int)-1
but calculated in (unsigned short) it would be (unsigned short)-1.
*/
-tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
+tree
+shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
{
int unsigned0, unsigned1;
tree arg0, arg1;
@@ -1803,8 +1826,8 @@ tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
op0 = convert (result_type, op0);
op1 = convert (result_type, op1);
- arg0 = get_narrower (op0, &unsigned0);
- arg1 = get_narrower (op1, &unsigned1);
+ arg0 = c_common_get_narrower (op0, &unsigned0);
+ arg1 = c_common_get_narrower (op1, &unsigned1);
/* UNS is 1 if the operation to be done is an unsigned one. */
uns = TYPE_UNSIGNED (result_type);
@@ -3301,8 +3324,8 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
/* Throw away any conversions to wider types
already present in the operands. */
- primop0 = get_narrower (op0, &unsignedp0);
- primop1 = get_narrower (op1, &unsignedp1);
+ primop0 = c_common_get_narrower (op0, &unsignedp0);
+ primop1 = c_common_get_narrower (op1, &unsignedp1);
/* If primopN is first sign-extended from primopN's precision to opN's
precision, then zero-extended from opN's precision to
@@ -9371,16 +9394,16 @@ warn_for_sign_compare (location_t location,
have all bits set that are set in the ~ operand when it is
extended. */
- op0 = get_narrower (op0, &unsignedp0);
- op1 = get_narrower (op1, &unsignedp1);
+ op0 = c_common_get_narrower (op0, &unsignedp0);
+ op1 = c_common_get_narrower (op1, &unsignedp1);
if ((TREE_CODE (op0) == BIT_NOT_EXPR)
^ (TREE_CODE (op1) == BIT_NOT_EXPR))
{
if (TREE_CODE (op0) == BIT_NOT_EXPR)
- op0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
+ op0 = c_common_get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
if (TREE_CODE (op1) == BIT_NOT_EXPR)
- op1 = get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
+ op1 = c_common_get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
if (host_integerp (op0, 0) || host_integerp (op1, 0))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 39225a3e..8c1fc39 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-05-23 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/enum14.C: New.
+
2011-05-23 Jakub Jelinek <jakub@redhat.com>
PR lto/49123
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum14.C b/gcc/testsuite/g++.dg/cpp0x/enum14.C
new file mode 100644
index 0000000..709b201
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum14.C
@@ -0,0 +1,12 @@
+// PR c++/48106
+// { dg-options -std=c++0x }
+
+enum class E : char
+{
+ e
+};
+
+bool operator&(E e, char m)
+{
+ return static_cast<int>(e) & m;
+}