aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/c-decl.c38
-rw-r--r--gcc/c-tree.h1
-rw-r--r--gcc/c-typeck.c130
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/c1x-typedef-1.c68
-rw-r--r--gcc/testsuite/gcc.dg/c1x-typedef-2.c18
-rw-r--r--gcc/testsuite/gcc.dg/c90-typedef-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/c99-typedef-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/decl-8.c2
10 files changed, 249 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e58de36..da66a28 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+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>
* regs.h: Do not include obstack.h, basic-block.h.
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index af038e1..68b0f8c 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -1786,18 +1786,48 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
/* Redeclaration of a type is a constraint violation (6.7.2.3p1),
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)
{
+ 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)
|| DECL_IN_SYSTEM_HEADER (olddecl)
|| TREE_NO_WARNING (newdecl)
|| TREE_NO_WARNING (olddecl))
return true; /* Allow OLDDECL to continue in use. */
- error ("redefinition of typedef %q+D", newdecl);
- locate_old_decl (olddecl);
- return false;
+ if (pedantic && !flag_isoc1x)
+ {
+ pedwarn (input_location, OPT_pedantic,
+ "redefinition of typedef %q+D", newdecl);
+ locate_old_decl (olddecl);
+ }
+ 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
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 3090a67..1806e2c 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -506,6 +506,7 @@ extern tree c_objc_common_truthvalue_conversion (location_t, tree);
extern tree require_complete_type (tree);
extern int same_translation_unit_p (const_tree, const_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_mark_addressable (tree);
extern void c_incomplete_type_error (const_tree, const_tree);
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index a9cd106..4665861 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -76,10 +76,12 @@ static int require_constant_elements;
static bool null_pointer_constant_p (const_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 function_types_compatible_p (const_tree, const_tree, bool *);
-static int type_lists_compatible_p (const_tree, const_tree, bool *);
+static int function_types_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 int convert_arguments (tree, VEC(tree,gc) *, VEC(tree,gc) *, tree,
tree);
@@ -106,7 +108,7 @@ static void readonly_error (tree, enum lvalue_use);
static void readonly_warning (tree, enum lvalue_use);
static int lvalue_or_else (const_tree, enum lvalue_use);
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. */
@@ -972,7 +974,7 @@ comptypes (tree type1, tree type2)
const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = tagged_tu_seen_base;
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);
return val;
@@ -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;
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);
return val;
@@ -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
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;
- *ENUM_AND_INT_P is never set to false. This differs from
- comptypes, in that we don't free the seen types. */
+ *ENUM_AND_INT_P is never set to false. If DIFFERENT_TYPES_P is not
+ 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
-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 t2 = type2;
@@ -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)
{
t1 = c_common_type_for_size (TYPE_PRECISION (t1), TYPE_UNSIGNED (t1));
- if (enum_and_int_p != NULL && TREE_CODE (t2) != VOID_TYPE)
- *enum_and_int_p = true;
+ if (TREE_CODE (t2) != VOID_TYPE)
+ {
+ if (enum_and_int_p != NULL)
+ *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)
{
t2 = c_common_type_for_size (TYPE_PRECISION (t2), TYPE_UNSIGNED (t2));
- if (enum_and_int_p != NULL && TREE_CODE (t1) != VOID_TYPE)
- *enum_and_int_p = true;
+ if (TREE_CODE (t1) != VOID_TYPE)
+ {
+ if (enum_and_int_p != NULL)
+ *enum_and_int_p = true;
+ if (different_types_p != NULL)
+ *different_types_p = true;
+ }
}
if (t1 == t2)
@@ -1079,11 +1113,12 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
break;
val = (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;
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;
case ARRAY_TYPE:
@@ -1097,9 +1132,13 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
/* Target types must match incl. qualifiers. */
if (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;
+ if (different_types_p != NULL
+ && (d1 == 0) != (d2 == 0))
+ *different_types_p = true;
/* Sizes must match unless one is missing or variable. */
if (d1 == 0 || d2 == 0 || d1 == d2)
break;
@@ -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));
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)
break;
if (d1_zero && d2_zero)
@@ -1141,15 +1183,17 @@ comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p)
break;
if (attrval != 2)
- return tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
- val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p);
+ return 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;
case VECTOR_TYPE:
val = (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
&& comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
- enum_and_int_p));
+ enum_and_int_p, different_types_p));
break;
default:
@@ -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
checked earlier), this can only happen when multiple translation
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
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;
bool needs_warning = false;
@@ -1396,7 +1441,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
if (DECL_NAME (s1) != DECL_NAME (s2))
break;
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))
break;
@@ -1432,7 +1477,8 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
int result;
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))
continue;
@@ -1475,7 +1521,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
|| DECL_NAME (s1) != DECL_NAME (s2))
break;
result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
- enum_and_int_p);
+ enum_and_int_p, different_types_p);
if (result == 0)
break;
if (result == 2)
@@ -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,
the other must specify that number of self-promoting arg types.
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
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;
/* 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,
if (TYPE_VOLATILE (ret2))
ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
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)
return 0;
args1 = TYPE_ARG_TYPES (f1);
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
whose argument types don't need default promotions. */
@@ -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 (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;
return val;
}
@@ -1558,23 +1608,25 @@ function_types_compatible_p (const_tree f1, const_tree f2,
return 0;
if (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;
return val;
}
/* 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;
}
/* Check two lists of types for compatibility, returning 0 for
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
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. */
int val = 1;
@@ -1599,6 +1651,9 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
means there is supposed to be an argument
but nothing is specified about what type it has.
So match anything that self-promotes. */
+ if (different_types_p != NULL
+ && (a1 == 0) != (a2 == 0))
+ *different_types_p = true;
if (a1 == 0)
{
if (c_type_promotes_to (a2) != a2)
@@ -1613,8 +1668,11 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
else if (TREE_CODE (a1) == 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} *)
and wait (union wait *) to be compatible. */
if (TREE_CODE (a1) == UNION_TYPE
@@ -1632,7 +1690,8 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
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;
}
if (memb == 0)
@@ -1653,7 +1712,8 @@ type_lists_compatible_p (const_tree args1, const_tree args2,
if (mv3 && mv3 != error_mark_node
&& TREE_CODE (mv3) != ARRAY_TYPE)
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;
}
if (memb == 0)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d31903a..1e748af 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+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>
* gcc.c-target/pr43869.c: Move "dg-do run" before lp64.
diff --git a/gcc/testsuite/gcc.dg/c1x-typedef-1.c b/gcc/testsuite/gcc.dg/c1x-typedef-1.c
new file mode 100644
index 0000000..2b0bc74
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c1x-typedef-1.c
@@ -0,0 +1,68 @@
+/* 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" } */
+}
diff --git a/gcc/testsuite/gcc.dg/c1x-typedef-2.c b/gcc/testsuite/gcc.dg/c1x-typedef-2.c
new file mode 100644
index 0000000..fb5d918
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c1x-typedef-2.c
@@ -0,0 +1,18 @@
+/* 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);
+}
diff --git a/gcc/testsuite/gcc.dg/c90-typedef-1.c b/gcc/testsuite/gcc.dg/c90-typedef-1.c
new file mode 100644
index 0000000..1920f3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c90-typedef-1.c
@@ -0,0 +1,6 @@
+/* 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" } */
diff --git a/gcc/testsuite/gcc.dg/c99-typedef-1.c b/gcc/testsuite/gcc.dg/c99-typedef-1.c
new file mode 100644
index 0000000..8aacb3b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c99-typedef-1.c
@@ -0,0 +1,6 @@
+/* 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" } */
diff --git a/gcc/testsuite/gcc.dg/decl-8.c b/gcc/testsuite/gcc.dg/decl-8.c
index d0da48f..485065b 100644
--- a/gcc/testsuite/gcc.dg/decl-8.c
+++ b/gcc/testsuite/gcc.dg/decl-8.c
@@ -1,7 +1,7 @@
/* Test diagnostics for duplicate typedefs. Basic diagnostics. */
/* Origin: Joseph Myers <joseph@codesourcery.com> */
/* { 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-error "redefinition of typedef 'I'" } */