re PR c/13519 (typeof(nonconst+const) is const)
PR c/13519 * c-typeck.c (composite_type, common_pointer_type): New functions. (common_type): Split parts into composite_type and common_pointer_type. Ensure that arithmetic operations return unqualified types without attributes. Don't make composite type of signed enum and compatible integer be unsigned. (build_conditional_expr, build_binary_op): Use common_pointer_type. * c-decl.c (merge_decls): Use composite_type. * c-tree.h (composite_type): Declare. testsuite: * gcc.c-torture/enum-3.c, gcc.dg/pr13519-1.c: New tests. From-SVN: r82671
This commit is contained in:
parent
ff24b82044
commit
10bc1b1bec
7 changed files with 296 additions and 140 deletions
|
@ -1,3 +1,16 @@
|
|||
2004-06-06 Joseph S. Myers <jsm@polyomino.org.uk>
|
||||
|
||||
PR c/13519
|
||||
* c-typeck.c (composite_type, common_pointer_type): New functions.
|
||||
(common_type): Split parts into composite_type and
|
||||
common_pointer_type. Ensure that arithmetic operations return
|
||||
unqualified types without attributes. Don't make composite type
|
||||
of signed enum and compatible integer be unsigned.
|
||||
(build_conditional_expr, build_binary_op): Use
|
||||
common_pointer_type.
|
||||
* c-decl.c (merge_decls): Use composite_type.
|
||||
* c-tree.h (composite_type): Declare.
|
||||
|
||||
2004-06-06 Stephane Carrez <stcarrez@nerim.fr>
|
||||
|
||||
PR target/14457
|
||||
|
|
|
@ -1452,7 +1452,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
|
|||
/* Merge the data types specified in the two decls. */
|
||||
TREE_TYPE (newdecl)
|
||||
= TREE_TYPE (olddecl)
|
||||
= common_type (newtype, oldtype);
|
||||
= composite_type (newtype, oldtype);
|
||||
|
||||
/* Lay the type out, unless already done. */
|
||||
if (oldtype != TREE_TYPE (newdecl))
|
||||
|
|
|
@ -226,6 +226,7 @@ extern tree c_size_in_bytes (tree);
|
|||
extern bool c_mark_addressable (tree);
|
||||
extern void c_incomplete_type_error (tree, tree);
|
||||
extern tree c_type_promotes_to (tree);
|
||||
extern tree composite_type (tree, tree);
|
||||
extern tree build_component_ref (tree, tree);
|
||||
extern tree build_indirect_ref (tree, const char *);
|
||||
extern tree build_array_ref (tree, tree);
|
||||
|
|
344
gcc/c-typeck.c
344
gcc/c-typeck.c
|
@ -199,19 +199,14 @@ qualify_type (tree type, tree like)
|
|||
TYPE_QUALS (type) | TYPE_QUALS (like));
|
||||
}
|
||||
|
||||
/* Return the composite type of two compatible types, or the common
|
||||
type for two arithmetic types under the usual arithmetic
|
||||
conversions.
|
||||
/* Return the composite type of two compatible types.
|
||||
|
||||
Unless both types are arithmetic types, we assume that comptypes
|
||||
has already been done and returned 1; if that isn't so, this may
|
||||
crash. In particular, we assume that qualifiers match.
|
||||
|
||||
This is the type for the result of most arithmetic operations
|
||||
if the operands have the given two types. */
|
||||
We assume that comptypes has already been done and returned
|
||||
nonzero; if that isn't so, this may crash. In particular, we
|
||||
assume that qualifiers match. */
|
||||
|
||||
tree
|
||||
common_type (tree t1, tree t2)
|
||||
composite_type (tree t1, tree t2)
|
||||
{
|
||||
enum tree_code code1;
|
||||
enum tree_code code2;
|
||||
|
@ -227,145 +222,40 @@ common_type (tree t1, tree t2)
|
|||
if (t2 == error_mark_node)
|
||||
return t1;
|
||||
|
||||
/* Merge the attributes. */
|
||||
attributes = targetm.merge_type_attributes (t1, t2);
|
||||
|
||||
/* Treat an enum type as the unsigned integer type of the same width. */
|
||||
|
||||
if (TREE_CODE (t1) == ENUMERAL_TYPE)
|
||||
t1 = c_common_type_for_size (TYPE_PRECISION (t1), 1);
|
||||
if (TREE_CODE (t2) == ENUMERAL_TYPE)
|
||||
t2 = c_common_type_for_size (TYPE_PRECISION (t2), 1);
|
||||
|
||||
code1 = TREE_CODE (t1);
|
||||
code2 = TREE_CODE (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. */
|
||||
if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
|
||||
{
|
||||
tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
|
||||
tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
|
||||
tree subtype = common_type (subtype1, subtype2);
|
||||
/* Merge the attributes. */
|
||||
attributes = targetm.merge_type_attributes (t1, t2);
|
||||
|
||||
if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
|
||||
return build_type_attribute_variant (t2, attributes);
|
||||
else
|
||||
return build_type_attribute_variant (build_complex_type (subtype),
|
||||
attributes);
|
||||
}
|
||||
/* If one is an enumerated type and the other is the compatible
|
||||
integer type, the composite type might be either of the two
|
||||
(DR#013 question 3). For consistency, use the enumerated type as
|
||||
the composite type. */
|
||||
|
||||
if (code1 == ENUMERAL_TYPE && code2 == INTEGER_TYPE)
|
||||
return t1;
|
||||
if (code2 == ENUMERAL_TYPE && code1 == INTEGER_TYPE)
|
||||
return t2;
|
||||
|
||||
if (code1 != code2)
|
||||
abort ();
|
||||
|
||||
switch (code1)
|
||||
{
|
||||
case INTEGER_TYPE:
|
||||
case REAL_TYPE:
|
||||
/* If only one is real, use it as the result. */
|
||||
|
||||
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
|
||||
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
|
||||
return build_type_attribute_variant (t2, attributes);
|
||||
|
||||
/* Both real or both integers; use the one with greater precision. */
|
||||
|
||||
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
|
||||
return build_type_attribute_variant (t2, attributes);
|
||||
|
||||
/* Same precision. Prefer long longs to longs to ints when the
|
||||
same precision, following the C99 rules on integer type rank
|
||||
(which are equivalent to the C90 rules for C90 types).
|
||||
Make sure that we don't lose the type qualifications when
|
||||
creating the new variant. */
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
|
||||
{
|
||||
t1 = build_qualified_type (long_long_unsigned_type_node,
|
||||
TYPE_QUALS (t1));
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
}
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
|
||||
{
|
||||
tree ntype;
|
||||
|
||||
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
|
||||
ntype = long_long_unsigned_type_node;
|
||||
else
|
||||
ntype = long_long_integer_type_node;
|
||||
|
||||
ntype = build_qualified_type (ntype, TYPE_QUALS (t1));
|
||||
return build_type_attribute_variant (ntype, attributes);
|
||||
}
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
|
||||
{
|
||||
t1 = build_qualified_type (long_unsigned_type_node,
|
||||
TYPE_QUALS (t1));
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
}
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
|
||||
{
|
||||
tree ntype;
|
||||
|
||||
/* But preserve unsignedness from the other type,
|
||||
since long cannot hold all the values of an unsigned int. */
|
||||
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
|
||||
ntype = long_unsigned_type_node;
|
||||
else
|
||||
ntype = long_integer_type_node;
|
||||
|
||||
ntype = build_qualified_type (ntype, TYPE_QUALS (t1));
|
||||
return build_type_attribute_variant (ntype, attributes);
|
||||
}
|
||||
|
||||
/* Likewise, prefer long double to double even if same size. */
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_double_type_node)
|
||||
{
|
||||
t1 = build_qualified_type (long_double_type_node,
|
||||
TYPE_QUALS (t1));
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
}
|
||||
|
||||
/* Otherwise prefer the unsigned one. */
|
||||
|
||||
if (TYPE_UNSIGNED (t1))
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
else
|
||||
return build_type_attribute_variant (t2, attributes);
|
||||
|
||||
case POINTER_TYPE:
|
||||
/* For two pointers, do this recursively on the target type,
|
||||
and combine the qualifiers of the two types' targets. */
|
||||
/* This code was turned off; I don't know why.
|
||||
But ANSI C specifies doing this with the qualifiers.
|
||||
So I turned it on again. */
|
||||
/* For two pointers, do this recursively on the target type. */
|
||||
{
|
||||
tree pointed_to_1 = TREE_TYPE (t1);
|
||||
tree pointed_to_2 = TREE_TYPE (t2);
|
||||
tree target = common_type (TYPE_MAIN_VARIANT (pointed_to_1),
|
||||
TYPE_MAIN_VARIANT (pointed_to_2));
|
||||
t1 = build_pointer_type (c_build_qualified_type
|
||||
(target,
|
||||
TYPE_QUALS (pointed_to_1) |
|
||||
TYPE_QUALS (pointed_to_2)));
|
||||
tree target = composite_type (pointed_to_1, pointed_to_2);
|
||||
t1 = build_pointer_type (target);
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
}
|
||||
|
||||
case ARRAY_TYPE:
|
||||
{
|
||||
tree elt = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
|
||||
tree elt = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
|
||||
/* Save space: see if the result is identical to one of the args. */
|
||||
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1))
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
|
@ -380,7 +270,7 @@ common_type (tree t1, tree t2)
|
|||
/* Function types: prefer the one that specified arg types.
|
||||
If both do, merge the arg types. Also merge the return types. */
|
||||
{
|
||||
tree valtype = common_type (TREE_TYPE (t1), TREE_TYPE (t2));
|
||||
tree valtype = composite_type (TREE_TYPE (t1), TREE_TYPE (t2));
|
||||
tree p1 = TYPE_ARG_TYPES (t1);
|
||||
tree p2 = TYPE_ARG_TYPES (t2);
|
||||
int len;
|
||||
|
@ -468,7 +358,7 @@ common_type (tree t1, tree t2)
|
|||
goto parm_done;
|
||||
}
|
||||
}
|
||||
TREE_VALUE (n) = common_type (TREE_VALUE (p1), TREE_VALUE (p2));
|
||||
TREE_VALUE (n) = composite_type (TREE_VALUE (p1), TREE_VALUE (p2));
|
||||
parm_done: ;
|
||||
}
|
||||
|
||||
|
@ -482,6 +372,182 @@ common_type (tree t1, tree t2)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/* Return the type of a conditional expression between pointers to
|
||||
possibly differently qualified versions of compatible types.
|
||||
|
||||
We assume that comp_target_types has already been done and returned
|
||||
nonzero; if that isn't so, this may crash. */
|
||||
|
||||
static tree
|
||||
common_pointer_type (tree t1, tree t2)
|
||||
{
|
||||
tree attributes;
|
||||
tree pointed_to_1;
|
||||
tree pointed_to_2;
|
||||
tree target;
|
||||
|
||||
/* Save time if the two types are the same. */
|
||||
|
||||
if (t1 == t2) return t1;
|
||||
|
||||
/* If one type is nonsense, use the other. */
|
||||
if (t1 == error_mark_node)
|
||||
return t2;
|
||||
if (t2 == error_mark_node)
|
||||
return t1;
|
||||
|
||||
if (TREE_CODE (t1) != POINTER_TYPE || TREE_CODE (t2) != POINTER_TYPE)
|
||||
abort ();
|
||||
|
||||
/* Merge the attributes. */
|
||||
attributes = targetm.merge_type_attributes (t1, t2);
|
||||
|
||||
/* Find the composite type of the target types, and combine the
|
||||
qualifiers of the two types' targets. */
|
||||
pointed_to_1 = TREE_TYPE (t1);
|
||||
pointed_to_2 = TREE_TYPE (t2);
|
||||
target = composite_type (TYPE_MAIN_VARIANT (pointed_to_1),
|
||||
TYPE_MAIN_VARIANT (pointed_to_2));
|
||||
t1 = build_pointer_type (c_build_qualified_type
|
||||
(target,
|
||||
TYPE_QUALS (pointed_to_1) |
|
||||
TYPE_QUALS (pointed_to_2)));
|
||||
return build_type_attribute_variant (t1, attributes);
|
||||
}
|
||||
|
||||
/* Return the common type for two arithmetic types under the usual
|
||||
arithmetic conversions. The default conversions have already been
|
||||
applied, and enumerated types converted to their compatible integer
|
||||
types. The resulting type is unqualified and has no attributes.
|
||||
|
||||
This is the type for the result of most arithmetic operations
|
||||
if the operands have the given two types. */
|
||||
|
||||
tree
|
||||
common_type (tree t1, tree t2)
|
||||
{
|
||||
enum tree_code code1;
|
||||
enum tree_code code2;
|
||||
|
||||
/* If one type is nonsense, use the other. */
|
||||
if (t1 == error_mark_node)
|
||||
return t2;
|
||||
if (t2 == error_mark_node)
|
||||
return t1;
|
||||
|
||||
if (TYPE_QUALS (t1) != TYPE_UNQUALIFIED)
|
||||
t1 = TYPE_MAIN_VARIANT (t1);
|
||||
|
||||
if (TYPE_QUALS (t2) != TYPE_UNQUALIFIED)
|
||||
t2 = TYPE_MAIN_VARIANT (t2);
|
||||
|
||||
if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
|
||||
t1 = build_type_attribute_variant (t1, NULL_TREE);
|
||||
|
||||
if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
|
||||
t2 = build_type_attribute_variant (t2, NULL_TREE);
|
||||
|
||||
/* Save time if the two types are the same. */
|
||||
|
||||
if (t1 == t2) return t1;
|
||||
|
||||
code1 = TREE_CODE (t1);
|
||||
code2 = TREE_CODE (t2);
|
||||
|
||||
if (code1 != VECTOR_TYPE && code1 != COMPLEX_TYPE
|
||||
&& code1 != REAL_TYPE && code1 != INTEGER_TYPE)
|
||||
abort ();
|
||||
|
||||
if (code2 != VECTOR_TYPE && code2 != COMPLEX_TYPE
|
||||
&& code2 != REAL_TYPE && code2 != INTEGER_TYPE)
|
||||
abort ();
|
||||
|
||||
/* If one type is a vector type, return that type. (How the usual
|
||||
arithmetic conversions apply to the vector types extension is not
|
||||
precisely specified.) */
|
||||
if (code1 == VECTOR_TYPE)
|
||||
return t1;
|
||||
|
||||
if (code2 == VECTOR_TYPE)
|
||||
return 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. */
|
||||
if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE)
|
||||
{
|
||||
tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1;
|
||||
tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2;
|
||||
tree subtype = common_type (subtype1, subtype2);
|
||||
|
||||
if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype)
|
||||
return t1;
|
||||
else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype)
|
||||
return t2;
|
||||
else
|
||||
return build_complex_type (subtype);
|
||||
}
|
||||
|
||||
/* If only one is real, use it as the result. */
|
||||
|
||||
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
|
||||
return t1;
|
||||
|
||||
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
|
||||
return t2;
|
||||
|
||||
/* Both real or both integers; use the one with greater precision. */
|
||||
|
||||
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
|
||||
return t1;
|
||||
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
|
||||
return t2;
|
||||
|
||||
/* Same precision. Prefer long longs to longs to ints when the
|
||||
same precision, following the C99 rules on integer type rank
|
||||
(which are equivalent to the C90 rules for C90 types). */
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_long_unsigned_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_long_unsigned_type_node)
|
||||
return long_long_unsigned_type_node;
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_long_integer_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_long_integer_type_node)
|
||||
{
|
||||
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
|
||||
return long_long_unsigned_type_node;
|
||||
else
|
||||
return long_long_integer_type_node;
|
||||
}
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
|
||||
return long_unsigned_type_node;
|
||||
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
|
||||
{
|
||||
/* But preserve unsignedness from the other type,
|
||||
since long cannot hold all the values of an unsigned int. */
|
||||
if (TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
|
||||
return long_unsigned_type_node;
|
||||
else
|
||||
return long_integer_type_node;
|
||||
}
|
||||
|
||||
/* Likewise, prefer long double to double even if same size. */
|
||||
if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
|
||||
|| TYPE_MAIN_VARIANT (t2) == long_double_type_node)
|
||||
return long_double_type_node;
|
||||
|
||||
/* Otherwise prefer the unsigned one. */
|
||||
|
||||
if (TYPE_UNSIGNED (t1))
|
||||
return t1;
|
||||
else
|
||||
return t2;
|
||||
}
|
||||
|
||||
/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
|
||||
or various other operations. Return 2 if they are compatible
|
||||
|
@ -2760,7 +2826,7 @@ build_conditional_expr (tree ifexp, tree op1, tree op2)
|
|||
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
|
||||
{
|
||||
if (comp_target_types (type1, type2, 1))
|
||||
result_type = common_type (type1, type2);
|
||||
result_type = common_pointer_type (type1, type2);
|
||||
else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node
|
||||
&& TREE_CODE (orig_op1) != NOP_EXPR)
|
||||
result_type = qualify_type (type2, type1);
|
||||
|
@ -6704,7 +6770,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
Otherwise, the targets must be compatible
|
||||
and both must be object or both incomplete. */
|
||||
if (comp_target_types (type0, type1, 1))
|
||||
result_type = common_type (type0, type1);
|
||||
result_type = common_pointer_type (type0, type1);
|
||||
else if (VOID_TYPE_P (tt0))
|
||||
{
|
||||
/* op0 != orig_op0 detects the case of something
|
||||
|
@ -6752,7 +6818,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
{
|
||||
if (comp_target_types (type0, type1, 1))
|
||||
{
|
||||
result_type = common_type (type0, type1);
|
||||
result_type = common_pointer_type (type0, type1);
|
||||
if (pedantic
|
||||
&& TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
|
||||
pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
|
||||
|
@ -6777,7 +6843,7 @@ build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
|
|||
{
|
||||
if (comp_target_types (type0, type1, 1))
|
||||
{
|
||||
result_type = common_type (type0, type1);
|
||||
result_type = common_pointer_type (type0, type1);
|
||||
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
|
||||
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
|
||||
pedwarn ("comparison of complete and incomplete pointers");
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2004-06-06 Joseph S. Myers <jsm@polyomino.org.uk>
|
||||
|
||||
PR c/13519
|
||||
* gcc.c-torture/enum-3.c, gcc.dg/pr13519-1.c: New tests.
|
||||
|
||||
2004-06-06 Giovanni Bajo <giovannibajo@gcc.gnu.org>
|
||||
|
||||
PR c++/15503
|
||||
|
|
24
gcc/testsuite/gcc.c-torture/execute/enum-3.c
Normal file
24
gcc/testsuite/gcc.c-torture/execute/enum-3.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/* The composite type of int and an enum compatible with int might be
|
||||
either of the two types, but it isn't an unsigned type. */
|
||||
/* Origin: Joseph Myers <jsm@polyomino.org.uk> */
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
extern void abort (void);
|
||||
extern void exit (int);
|
||||
|
||||
enum e { a = INT_MIN };
|
||||
|
||||
int *p;
|
||||
enum e *q;
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
enum e x = a;
|
||||
q = &x;
|
||||
if (*(1 ? q : p) > 0)
|
||||
abort ();
|
||||
exit (0);
|
||||
}
|
47
gcc/testsuite/gcc.dg/pr13519-1.c
Normal file
47
gcc/testsuite/gcc.dg/pr13519-1.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* typeof applied to const+nonconst should be nonconst, as should
|
||||
typeof applied to other arithmetic expressions. Bug 13519. */
|
||||
/* Origin: Debian bug report 208981
|
||||
from Kalle Olavi Niemitalo <kon@iki.fi>, adapted to a testcase by
|
||||
Joseph Myers <jsm@polyomino.org.uk>. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "" } */
|
||||
|
||||
void fn(void)
|
||||
{
|
||||
int n;
|
||||
const int c;
|
||||
|
||||
{ __typeof__(n) a1; a1=0; }
|
||||
{ __typeof__(c) a2; a2=0; } /* { dg-error "read-only" "correct error" } */
|
||||
{ __typeof__((int)n) a3; a3=0; }
|
||||
{ __typeof__((int)c) a4; a4=0; } /* { dg-bogus "read-only" "bogus error" { xfail *-*-* } } */
|
||||
{ __typeof__((const int)n) a5; a5=0; } /* { dg-error "read-only" "correct error" { xfail *-*-* } } */
|
||||
{ __typeof__((const int)c) a6; a6=0; } /* { dg-error "read-only" "correct error" } */
|
||||
{ __typeof__(0) a7; a7=0; }
|
||||
{ __typeof__(1) a8; a8=0; }
|
||||
|
||||
{ __typeof__(n+n) b0; b0=0; }
|
||||
{ __typeof__(n+c) b1; b1=0; }
|
||||
{ __typeof__(c+n) b2; b2=0; }
|
||||
{ __typeof__(c+c) b3; b3=0; }
|
||||
|
||||
{ __typeof__(0+n) c0; c0=0; }
|
||||
{ __typeof__(0+c) c1; c1=0; }
|
||||
{ __typeof__(n+0) c2; c2=0; }
|
||||
{ __typeof__(c+0) c3; c3=0; }
|
||||
|
||||
{ __typeof__(1+n) d0; d0=0; }
|
||||
{ __typeof__(1+c) d1; d1=0; }
|
||||
{ __typeof__(n+1) d2; d2=0; }
|
||||
{ __typeof__(c+1) d3; d3=0; }
|
||||
|
||||
{ __typeof__(((int)n)+((int)n)) e0; e0=0; }
|
||||
{ __typeof__(((int)n)+((int)c)) e1; e1=0; }
|
||||
{ __typeof__(((int)c)+((int)n)) e2; e2=0; }
|
||||
{ __typeof__(((int)c)+((int)c)) e3; e3=0; }
|
||||
|
||||
{ __typeof__(((const int)n)+((const int)n)) f0; f0=0; }
|
||||
{ __typeof__(((const int)n)+((const int)c)) f1; f1=0; }
|
||||
{ __typeof__(((const int)c)+((const int)n)) f2; f2=0; }
|
||||
{ __typeof__(((const int)c)+((const int)c)) f3; f3=0; }
|
||||
}
|
Loading…
Add table
Reference in a new issue