Commit dc5027f4 by Joseph Myers Committed by Joseph Myers

c-decl.c (diagnose_mismatched_decls): Give error for duplicate typedefs with…

c-decl.c (diagnose_mismatched_decls): Give error for duplicate typedefs with different but compatible types.

	* c-decl.c (diagnose_mismatched_decls): Give error for duplicate
	typedefs with different but compatible types.  Allow duplicate
	typedefs with the same type except for pedantic non-C1X, but give
	warning for variably modified types.
	* c-typeck.c (tagged_types_tu_compatible_p,
	function_types_compatible_p, type_lists_compatible_p,
	comptypes_internal): Add parameter different_types_p; set
	*different_types_p for different but compatible types.  All
	callers changed.
	(comptypes_check_different_types): New.
	* c-tree.h (comptypes_check_different_types): Declare.

testsuite:
	* gcc.dg/c1x-typedef-1.c, gcc.dg/c1x-typedef-2.c,
	gcc.dg/c90-typedef-1.c, gcc.dg/c99-typedef-1.c: New tests.
	* gcc.dg/decl-8.c: Use -std=gnu89 -pedantic-errors.

From-SVN: r159767
parent 8f9e812d
2010-05-23 Joseph Myers <joseph@codesourcery.com>
* c-decl.c (diagnose_mismatched_decls): Give error for duplicate
typedefs with different but compatible types. Allow duplicate
typedefs with the same type except for pedantic non-C1X, but give
warning for variably modified types.
* c-typeck.c (tagged_types_tu_compatible_p,
function_types_compatible_p, type_lists_compatible_p,
comptypes_internal): Add parameter different_types_p; set
*different_types_p for different but compatible types. All
callers changed.
(comptypes_check_different_types): New.
* c-tree.h (comptypes_check_different_types): Declare.
2010-05-23 Steven Bosscher <steven@gcc.gnu.org> 2010-05-23 Steven Bosscher <steven@gcc.gnu.org>
* regs.h: Do not include obstack.h, basic-block.h. * regs.h: Do not include obstack.h, basic-block.h.
......
...@@ -1786,18 +1786,48 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl, ...@@ -1786,18 +1786,48 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* Redeclaration of a type is a constraint violation (6.7.2.3p1), /* Redeclaration of a type is a constraint violation (6.7.2.3p1),
but silently ignore the redeclaration if either is in a system but silently ignore the redeclaration if either is in a system
header. (Conflicting redeclarations were handled above.) */ header. (Conflicting redeclarations were handled above.) This
is allowed for C1X if the types are the same, not just
compatible. */
if (TREE_CODE (newdecl) == TYPE_DECL) if (TREE_CODE (newdecl) == TYPE_DECL)
{ {
bool types_different = false;
int comptypes_result;
comptypes_result
= comptypes_check_different_types (oldtype, newtype, &types_different);
if (comptypes_result != 1 || types_different)
{
error ("redefinition of typedef %q+D with different type", newdecl);
locate_old_decl (olddecl);
return false;
}
if (DECL_IN_SYSTEM_HEADER (newdecl) if (DECL_IN_SYSTEM_HEADER (newdecl)
|| DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (olddecl)
|| TREE_NO_WARNING (newdecl) || TREE_NO_WARNING (newdecl)
|| TREE_NO_WARNING (olddecl)) || TREE_NO_WARNING (olddecl))
return true; /* Allow OLDDECL to continue in use. */ return true; /* Allow OLDDECL to continue in use. */
error ("redefinition of typedef %q+D", newdecl); if (pedantic && !flag_isoc1x)
{
pedwarn (input_location, OPT_pedantic,
"redefinition of typedef %q+D", newdecl);
locate_old_decl (olddecl); locate_old_decl (olddecl);
return false; }
else if (variably_modified_type_p (newtype, NULL))
{
/* Whether there is a constraint violation for the types not
being the same cannot be determined at compile time; a
warning that there may be one at runtime is considered
appropriate (WG14 reflector message 11743, 8 May 2009). */
warning (0, "redefinition of typedef %q+D may be a constraint "
"violation at runtime", newdecl);
locate_old_decl (olddecl);
}
return true;
} }
/* Function declarations can either be 'static' or 'extern' (no /* Function declarations can either be 'static' or 'extern' (no
......
...@@ -506,6 +506,7 @@ extern tree c_objc_common_truthvalue_conversion (location_t, tree); ...@@ -506,6 +506,7 @@ extern tree c_objc_common_truthvalue_conversion (location_t, tree);
extern tree require_complete_type (tree); extern tree require_complete_type (tree);
extern int same_translation_unit_p (const_tree, const_tree); extern int same_translation_unit_p (const_tree, const_tree);
extern int comptypes (tree, tree); extern int comptypes (tree, tree);
extern int comptypes_check_different_types (tree, tree, bool *);
extern bool c_vla_type_p (const_tree); extern bool c_vla_type_p (const_tree);
extern bool c_mark_addressable (tree); extern bool c_mark_addressable (tree);
extern void c_incomplete_type_error (const_tree, const_tree); extern void c_incomplete_type_error (const_tree, const_tree);
......
...@@ -76,10 +76,12 @@ static int require_constant_elements; ...@@ -76,10 +76,12 @@ static int require_constant_elements;
static bool null_pointer_constant_p (const_tree); static bool null_pointer_constant_p (const_tree);
static tree qualify_type (tree, tree); static tree qualify_type (tree, tree);
static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *); static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
bool *);
static int comp_target_types (location_t, tree, tree); static int comp_target_types (location_t, tree, tree);
static int function_types_compatible_p (const_tree, const_tree, bool *); static int function_types_compatible_p (const_tree, const_tree, bool *,
static int type_lists_compatible_p (const_tree, const_tree, bool *); bool *);
static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
static tree lookup_field (tree, tree); static tree lookup_field (tree, tree);
static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree, static int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
tree); tree);
...@@ -106,7 +108,7 @@ static void readonly_error (tree, enum lvalue_use); ...@@ -106,7 +108,7 @@ static void readonly_error (tree, enum lvalue_use);
static void readonly_warning (tree, enum lvalue_use); static void readonly_warning (tree, enum lvalue_use);
static int lvalue_or_else (const_tree, enum lvalue_use); static int lvalue_or_else (const_tree, enum lvalue_use);
static void record_maybe_used_decl (tree); static void record_maybe_used_decl (tree);
static int comptypes_internal (const_tree, const_tree, bool *); static int comptypes_internal (const_tree, const_tree, bool *, bool *);
/* Return true if EXP is a null pointer constant, false otherwise. */ /* Return true if EXP is a null pointer constant, false otherwise. */
...@@ -972,7 +974,7 @@ comptypes (tree type1, tree type2) ...@@ -972,7 +974,7 @@ comptypes (tree type1, tree type2)
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
int val; int val;
val = comptypes_internal (type1, type2, NULL); val = comptypes_internal (type1, type2, NULL, NULL);
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
return val; return val;
...@@ -987,7 +989,23 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p) ...@@ -987,7 +989,23 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base; const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
int val; int val;
val = comptypes_internal (type1, type2, enum_and_int_p); val = comptypes_internal (type1, type2, enum_and_int_p, NULL);
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
return val;
}
/* Like comptypes, but if it returns nonzero for different types, it
sets *DIFFERENT_TYPES_P to true. */
int
comptypes_check_different_types (tree type1, tree type2,
bool *different_types_p)
{
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
int val;
val = comptypes_internal (type1, type2, NULL, different_types_p);
free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1); free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
return val; return val;
...@@ -998,11 +1016,17 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p) ...@@ -998,11 +1016,17 @@ comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
but a warning may be needed if you use them together. If but a warning may be needed if you use them together. If
ENUM_AND_INT_P is not NULL, and one type is an enum and the other a ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
compatible integer type, then this sets *ENUM_AND_INT_P to true; compatible integer type, then this sets *ENUM_AND_INT_P to true;
*ENUM_AND_INT_P is never set to false. This differs from *ENUM_AND_INT_P is never set to false. If DIFFERENT_TYPES_P is not
comptypes, in that we don't free the seen types. */ NULL, and the types are compatible but different enough not to be
permitted in C1X typedef redeclarations, then this sets
*DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
false, but may or may not be set if the types are incompatible.
This differs from comptypes, in that we don't free the seen
types. */
static int static int
comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
bool *different_types_p)
{ {
const_tree t1 = type1; const_tree t1 = type1;
const_tree t2 = type2; const_tree t2 = type2;
...@@ -1032,14 +1056,24 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) ...@@ -1032,14 +1056,24 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE) if (TREE_CODE (t1) == ENUMERAL_TYPE && TREE_CODE (t2) != ENUMERAL_TYPE)
{ {
t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1)); t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
if (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE) if (TREE_CODE (t2) != VOID_TYPE)
{
if (enum_and_int_p != NULL)
*enum_and_int_p = true; *enum_and_int_p = true;
if (different_types_p != NULL)
*different_types_p = true;
}
} }
else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE) else if (TREE_CODE (t2) == ENUMERAL_TYPE && TREE_CODE (t1) != ENUMERAL_TYPE)
{ {
t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2)); t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE) if (TREE_CODE (t1) != VOID_TYPE)
{
if (enum_and_int_p != NULL)
*enum_and_int_p = true; *enum_and_int_p = true;
if (different_types_p != NULL)
*different_types_p = true;
}
} }
if (t1 == t2) if (t1 == t2)
...@@ -1079,11 +1113,12 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) ...@@ -1079,11 +1113,12 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
break; break;
val = (TREE_TYPE (t1) == TREE_TYPE (t2) val = (TREE_TYPE (t1) == TREE_TYPE (t2)
? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
enum_and_int_p)); enum_and_int_p, different_types_p));
break; break;
case FUNCTION_TYPE: case FUNCTION_TYPE:
val = function_types_compatible_p (t1, t2, enum_and_int_p); val = function_types_compatible_p (t1, t2, enum_and_int_p,
different_types_p);
break; break;
case ARRAY_TYPE: case ARRAY_TYPE:
...@@ -1097,9 +1132,13 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) ...@@ -1097,9 +1132,13 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
/* Target types must match incl. qualifiers. */ /* Target types must match incl. qualifiers. */
if (TREE_TYPE (t1) != TREE_TYPE (t2) if (TREE_TYPE (t1) != TREE_TYPE (t2)
&& 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
enum_and_int_p))) enum_and_int_p,
different_types_p)))
return 0; return 0;
if (different_types_p != NULL
&& (d1 == 0) != (d2 == 0))
*different_types_p = true;
/* Sizes must match unless one is missing or variable. */ /* Sizes must match unless one is missing or variable. */
if (d1 == 0 || d2 == 0 || d1 == d2) if (d1 == 0 || d2 == 0 || d1 == d2)
break; break;
...@@ -1116,6 +1155,9 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) ...@@ -1116,6 +1155,9 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1)); d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2)); d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
if (different_types_p != NULL
&& d1_variable != d2_variable)
*different_types_p = true;
if (d1_variable || d2_variable) if (d1_variable || d2_variable)
break; break;
if (d1_zero && d2_zero) if (d1_zero && d2_zero)
...@@ -1141,15 +1183,17 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p) ...@@ -1141,15 +1183,17 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
break; break;
if (attrval != 2) if (attrval != 2)
return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p); return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p); different_types_p);
val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
different_types_p);
} }
break; break;
case VECTOR_TYPE: case VECTOR_TYPE:
val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
&& comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
enum_and_int_p)); enum_and_int_p, different_types_p));
break; break;
default: default:
...@@ -1281,11 +1325,12 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til) ...@@ -1281,11 +1325,12 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
compatible. If the two types are not the same (which has been compatible. If the two types are not the same (which has been
checked earlier), this can only happen when multiple translation checked earlier), this can only happen when multiple translation
units are being compiled. See C99 6.2.7 paragraph 1 for the exact units are being compiled. See C99 6.2.7 paragraph 1 for the exact
rules. ENUM_AND_INT_P is as in comptypes_internal. */ rules. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
comptypes_internal. */
static int static int
tagged_types_tu_compatible_p (const_tree t1, const_tree t2, tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
bool *enum_and_int_p) bool *enum_and_int_p, bool *different_types_p)
{ {
tree s1, s2; tree s1, s2;
bool needs_warning = false; bool needs_warning = false;
...@@ -1396,7 +1441,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, ...@@ -1396,7 +1441,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
if (DECL_NAME (s1) != DECL_NAME (s2)) if (DECL_NAME (s1) != DECL_NAME (s2))
break; break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
enum_and_int_p); enum_and_int_p, different_types_p);
if (result != 1 && !DECL_NAME (s1)) if (result != 1 && !DECL_NAME (s1))
break; break;
...@@ -1432,7 +1477,8 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, ...@@ -1432,7 +1477,8 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
int result; int result;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
enum_and_int_p); enum_and_int_p,
different_types_p);
if (result != 1 && !DECL_NAME (s1)) if (result != 1 && !DECL_NAME (s1))
continue; continue;
...@@ -1475,7 +1521,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, ...@@ -1475,7 +1521,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
|| DECL_NAME (s1) != DECL_NAME (s2)) || DECL_NAME (s1) != DECL_NAME (s2))
break; break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
enum_and_int_p); enum_and_int_p, different_types_p);
if (result == 0) if (result == 0)
break; break;
if (result == 2) if (result == 2)
...@@ -1504,11 +1550,11 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2, ...@@ -1504,11 +1550,11 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
Otherwise, if one type specifies only the number of arguments, Otherwise, if one type specifies only the number of arguments,
the other must specify that number of self-promoting arg types. the other must specify that number of self-promoting arg types.
Otherwise, the argument types must match. Otherwise, the argument types must match.
ENUM_AND_INT_P is as in comptypes_internal. */ ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal. */
static int static int
function_types_compatible_p (const_tree f1, const_tree f2, function_types_compatible_p (const_tree f1, const_tree f2,
bool *enum_and_int_p) bool *enum_and_int_p, bool *different_types_p)
{ {
tree args1, args2; tree args1, args2;
/* 1 if no need for warning yet, 2 if warning cause has been seen. */ /* 1 if no need for warning yet, 2 if warning cause has been seen. */
...@@ -1529,13 +1575,17 @@ function_types_compatible_p (const_tree f1, const_tree f2, ...@@ -1529,13 +1575,17 @@ function_types_compatible_p (const_tree f1, const_tree f2,
if (TYPE_VOLATILE (ret2)) if (TYPE_VOLATILE (ret2))
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2), ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE); TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
val = comptypes_internal (ret1, ret2, enum_and_int_p); val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
if (val == 0) if (val == 0)
return 0; return 0;
args1 = TYPE_ARG_TYPES (f1); args1 = TYPE_ARG_TYPES (f1);
args2 = TYPE_ARG_TYPES (f2); args2 = TYPE_ARG_TYPES (f2);
if (different_types_p != NULL
&& (args1 == 0) != (args2 == 0))
*different_types_p = true;
/* An unspecified parmlist matches any specified parmlist /* An unspecified parmlist matches any specified parmlist
whose argument types don't need default promotions. */ whose argument types don't need default promotions. */
...@@ -1548,7 +1598,7 @@ function_types_compatible_p (const_tree f1, const_tree f2, ...@@ -1548,7 +1598,7 @@ function_types_compatible_p (const_tree f1, const_tree f2,
If they don't match, ask for a warning (but no error). */ If they don't match, ask for a warning (but no error). */
if (TYPE_ACTUAL_ARG_TYPES (f1) if (TYPE_ACTUAL_ARG_TYPES (f1)
&& 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1), && 1 != type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
enum_and_int_p)) enum_and_int_p, different_types_p))
val = 2; val = 2;
return val; return val;
} }
...@@ -1558,23 +1608,25 @@ function_types_compatible_p (const_tree f1, const_tree f2, ...@@ -1558,23 +1608,25 @@ function_types_compatible_p (const_tree f1, const_tree f2,
return 0; return 0;
if (TYPE_ACTUAL_ARG_TYPES (f2) if (TYPE_ACTUAL_ARG_TYPES (f2)
&& 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2), && 1 != type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
enum_and_int_p)) enum_and_int_p, different_types_p))
val = 2; val = 2;
return val; return val;
} }
/* Both types have argument lists: compare them and propagate results. */ /* Both types have argument lists: compare them and propagate results. */
val1 = type_lists_compatible_p (args1, args2, enum_and_int_p); val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
different_types_p);
return val1 != 1 ? val1 : val; return val1 != 1 ? val1 : val;
} }
/* Check two lists of types for compatibility, returning 0 for /* Check two lists of types for compatibility, returning 0 for
incompatible, 1 for compatible, or 2 for compatible with incompatible, 1 for compatible, or 2 for compatible with
warning. ENUM_AND_INT_P is as in comptypes_internal. */ warning. ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
comptypes_internal. */
static int static int
type_lists_compatible_p (const_tree args1, const_tree args2, type_lists_compatible_p (const_tree args1, const_tree args2,
bool *enum_and_int_p) bool *enum_and_int_p, bool *different_types_p)
{ {
/* 1 if no need for warning yet, 2 if warning cause has been seen. */ /* 1 if no need for warning yet, 2 if warning cause has been seen. */
int val = 1; int val = 1;
...@@ -1599,6 +1651,9 @@ type_lists_compatible_p (const_tree args1, const_tree args2, ...@@ -1599,6 +1651,9 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
means there is supposed to be an argument means there is supposed to be an argument
but nothing is specified about what type it has. but nothing is specified about what type it has.
So match anything that self-promotes. */ So match anything that self-promotes. */
if (different_types_p != NULL
&& (a1 == 0) != (a2 == 0))
*different_types_p = true;
if (a1 == 0) if (a1 == 0)
{ {
if (c_type_promotes_to (a2) != a2) if (c_type_promotes_to (a2) != a2)
...@@ -1613,8 +1668,11 @@ type_lists_compatible_p (const_tree args1, const_tree args2, ...@@ -1613,8 +1668,11 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
else if (TREE_CODE (a1) == ERROR_MARK else if (TREE_CODE (a1) == ERROR_MARK
|| TREE_CODE (a2) == ERROR_MARK) || TREE_CODE (a2) == ERROR_MARK)
; ;
else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p))) else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
different_types_p)))
{ {
if (different_types_p != NULL)
*different_types_p = true;
/* Allow wait (union {union wait *u; int *i} *) /* Allow wait (union {union wait *u; int *i} *)
and wait (union wait *) to be compatible. */ and wait (union wait *) to be compatible. */
if (TREE_CODE (a1) == UNION_TYPE if (TREE_CODE (a1) == UNION_TYPE
...@@ -1632,7 +1690,8 @@ type_lists_compatible_p (const_tree args1, const_tree args2, ...@@ -1632,7 +1690,8 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
if (mv3 && mv3 != error_mark_node if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE) && TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3); mv3 = TYPE_MAIN_VARIANT (mv3);
if (comptypes_internal (mv3, mv2, enum_and_int_p)) if (comptypes_internal (mv3, mv2, enum_and_int_p,
different_types_p))
break; break;
} }
if (memb == 0) if (memb == 0)
...@@ -1653,7 +1712,8 @@ type_lists_compatible_p (const_tree args1, const_tree args2, ...@@ -1653,7 +1712,8 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
if (mv3 && mv3 != error_mark_node if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE) && TREE_CODE (mv3) != ARRAY_TYPE)
mv3 = TYPE_MAIN_VARIANT (mv3); mv3 = TYPE_MAIN_VARIANT (mv3);
if (comptypes_internal (mv3, mv1, enum_and_int_p)) if (comptypes_internal (mv3, mv1, enum_and_int_p,
different_types_p))
break; break;
} }
if (memb == 0) if (memb == 0)
......
2010-05-23 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/c1x-typedef-1.c, gcc.dg/c1x-typedef-2.c,
gcc.dg/c90-typedef-1.c, gcc.dg/c99-typedef-1.c: New tests.
* gcc.dg/decl-8.c: Use -std=gnu89 -pedantic-errors.
2010-05-23 H.J. Lu <hongjiu.lu@intel.com> 2010-05-23 H.J. Lu <hongjiu.lu@intel.com>
* gcc.c-target/pr43869.c: Move "dg-do run" before lp64. * gcc.c-target/pr43869.c: Move "dg-do run" before lp64.
......
/* Test typedef redeclaration in C1X. */
/* { dg-do compile } */
/* { dg-options "-std=c1x -pedantic-errors" } */
/* C1X permits typedefs to be redeclared to the same type, but not to
different-but-compatible types. */
#include <limits.h>
typedef int TI;
typedef int TI2;
typedef TI2 TI;
typedef TI TI2;
enum e { E1 = 0, E2 = INT_MAX, E3 = -1 };
typedef enum e TE;
typedef enum e TE; /* { dg-message "previous declaration" } */
typedef int TE; /* { dg-error "with different type" } */
struct s;
typedef struct s TS;
struct s { int i; };
typedef struct s TS;
typedef int IA[];
typedef TI2 IA[]; /* { dg-message "previous declaration" } */
typedef int A2[2];
typedef TI A2[2]; /* { dg-message "previous declaration" } */
typedef IA A2; /* { dg-error "with different type" } */
typedef int A3[3];
typedef A3 IA; /* { dg-error "with different type" } */
typedef void F(int);
typedef void F(TI); /* { dg-message "previous declaration" } */
typedef void F(enum e); /* { dg-error "with different type" } */
typedef int G(void);
typedef TI G(void); /* { dg-message "previous declaration" } */
typedef enum e G(void); /* { dg-error "with different type" } */
typedef int *P;
typedef TI *P; /* { dg-message "previous declaration" } */
typedef enum e *P; /* { dg-error "with different type" } */
typedef void F2();
typedef void F2(); /* { dg-message "previous declaration" } */
typedef void F2(int); /* { dg-error "with different type" } */
void
f (void)
{
int a = 1;
int b = 2;
typedef void FN(int (*p)[a]);
typedef void FN(int (*p)[b]);
typedef void FN(int (*p)[*]); /* { dg-message "previous declaration" } */
typedef void FN(int (*p)[1]); /* { dg-error "with different type" } */
typedef void FN2(int (*p)[a]);
typedef void FN2(int (*p)[b]);
typedef void FN2(int (*p)[*]); /* { dg-message "previous declaration" } */
typedef void FN2(int (*p)[]); /* { dg-error "with different type" } */
typedef int AV[a]; /* { dg-message "previous declaration" } */
typedef int AV[b-1]; /* { dg-warning "may be a constraint violation at runtime" } */
typedef int AAa[a];
typedef int AAb[b-1];
typedef AAa *VF(void); /* { dg-message "previous declaration" } */
typedef AAb *VF(void); /* { dg-warning "may be a constraint violation at runtime" } */
}
/* Test typedef redeclaration in C1X. Side effects from duplicate
declarations still apply. */
/* { dg-do run } */
/* { dg-options "-std=c1x -pedantic-errors" } */
extern void exit (int);
extern void abort (void);
int
main (void)
{
int a = 1, b = 1;
typedef int T[++a]; /* { dg-message "previous declaration" } */
typedef int T[++b]; /* { dg-warning "may be a constraint violation at runtime" } */
if (a != 2 || b != 2)
abort ();
exit (0);
}
/* Test typedef redeclaration not permitted in C90. */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
typedef int TI; /* { dg-message "previous declaration" } */
typedef int TI; /* { dg-error "redefinition of typedef" } */
/* Test typedef redeclaration not permitted in C99. */
/* { dg-do compile } */
/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
typedef int TI; /* { dg-message "previous declaration" } */
typedef int TI; /* { dg-error "redefinition of typedef" } */
/* Test diagnostics for duplicate typedefs. Basic diagnostics. */ /* Test diagnostics for duplicate typedefs. Basic diagnostics. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */ /* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "" } */ /* { dg-options "-std=gnu89 -pedantic-errors" } */
typedef int I; /* { dg-message "note: previous declaration of 'I' was here" } */ typedef int I; /* { dg-message "note: previous declaration of 'I' was here" } */
typedef int I; /* { dg-error "redefinition of typedef 'I'" } */ typedef int I; /* { dg-error "redefinition of typedef 'I'" } */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment