]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* c-decl.c (diagnose_mismatched_decls): Give error for duplicate
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 23 May 2010 20:47:16 +0000 (20:47 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 23 May 2010 20:47:16 +0000 (20:47 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159767 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-decl.c
gcc/c-tree.h
gcc/c-typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/c1x-typedef-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c1x-typedef-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c90-typedef-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c99-typedef-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/decl-8.c

index 9e58de369dfca6e8559731f4225c97547a10be87..da66a2873a415b200a60ad25dc710594e0534362 100644 (file)
@@ -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.
index af038e1783aaa4b129b21efeb733d60b753ef03e..68b0f8cd556dd4fa82a554a69b1b172279073236 100644 (file)
@@ -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
index 3090a6738426be7eda9b83ebcb7ab0ea72c06feb..1806e2ccff767922438668e13632b1c3e7eafe87 100644 (file)
@@ -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);
index a9cd10691aca532a6ad5df7d50d84c45a323312c..466586168f30caa2d069d68342874c873b7d9bc1 100644 (file)
@@ -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 *);
 \f
 /* 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)
index d31903a9d55aea3549201672b718f320397beaf3..1e748af68650015ab1314a6f98f13ecb86f2973d 100644 (file)
@@ -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 (file)
index 0000000..2b0bc74
--- /dev/null
@@ -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 (file)
index 0000000..fb5d918
--- /dev/null
@@ -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 (file)
index 0000000..1920f3b
--- /dev/null
@@ -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 (file)
index 0000000..8aacb3b
--- /dev/null
@@ -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" } */
index d0da48f7b596da2fb101c0bca6064053c0583a8d..485065b7aa12c08edcf87fad932ac37f3dbaacc3 100644 (file)
@@ -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'" } */