invoke.texi: Document -Wdiscarded-array-qualifiers.
authorMartin Uecker <uecker@eecs.berkeley.edu>
Sat, 20 Dec 2014 00:29:16 +0000 (16:29 -0800)
committerJoseph Myers <jsm28@gcc.gnu.org>
Sat, 20 Dec 2014 00:29:16 +0000 (00:29 +0000)
2014-12-20  Martin Uecker <uecker@eecs.berkeley.edu>

* doc/invoke.texi: Document -Wdiscarded-array-qualifiers.
* doc/extend.texi: Document new behavior for pointers to arrays
with qualifiers.

c/
* c-typeck.c: New behavious for pointers to arrays with qualifiers
        (common-pointer-type): For pointers to arrays take qualifiers from
element type.
        (build_conditional_expr): Add warnings for lost qualifiers.
(comp-target-types): Allow pointers to arrays with different qualifiers.
        (convert-for-assignment): Adapt warnings for discarded qualifiers. Add
WARNING_FOR_QUALIFIERS macro and rename WARN_FOR_QUALIFIERS
        to PEDWARN_FOR_QUALIFIERS.

c-family/
* c.opt (Wdiscarded-array-qualifiers): New option.

testsuite/
* gcc.dg/Wwrite-strings-1.c: Change dg-warning.
* gcc.dg/array-quals-1.c: Use -Wno-discarded-array-qualifiers.
* gcc.dg/array-quals-2.c: Change dg-options, dg-warning.
* gcc.dg/pointer-array-atomic.c: New test.
* gcc.dg/pointer-array-quals-1.c: New test.
* gcc.dg/pointer-array-quals-2.c: New test (-pedantic-errors).
* gcc.dg/qual-component-1.c: Change dg-options, dg-warnings.

From-SVN: r218985

15 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c.opt
gcc/c/ChangeLog
gcc/c/c-typeck.c
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/Wwrite-strings-1.c
gcc/testsuite/gcc.dg/array-quals-1.c
gcc/testsuite/gcc.dg/array-quals-2.c
gcc/testsuite/gcc.dg/pointer-array-atomic.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pointer-array-quals-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pointer-array-quals-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/qual-component-1.c

index 9c5841f91c8a8611f0d54b71b3e765c9e23eee23..bddb9a8b6fbbfe4b7f0ec4b42ed22e06d66cf968 100644 (file)
@@ -1,3 +1,9 @@
+2014-12-20  Martin Uecker <uecker@eecs.berkeley.edu>
+
+       * doc/invoke.texi: Document -Wdiscarded-array-qualifiers.
+       * doc/extend.texi: Document new behavior for pointers to arrays
+       with qualifiers.
+
 2014-12-19  Jan Hubicka  <hubicka@ucw.cz>
 
        * hash-table.h (struct pointer_hash): Fix formating.
index 94e6c34e9e6c0298c817fc3e03fc12130edf088d..7c0538d5da4de5dc5118ce4343f6b08faaf393f6 100644 (file)
@@ -1,3 +1,7 @@
+2014-12-20  Martin Uecker <uecker@eecs.berkeley.edu>
+
+       * c.opt (Wdiscarded-array-qualifiers): New option.
+
 2014-12-19  Jakub Jelinek  <jakub@redhat.com>
 
        PR preprocessor/63831
index 1676f65bcd2532cff0bc7ea068c4700c9c90cbd6..f86718b26f497560a70654ce9b38f14d75f81347 100644 (file)
@@ -387,6 +387,10 @@ Wdesignated-init
 C ObjC Var(warn_designated_init) Init(1) Warning
 Warn about positional initialization of structs requiring designated initializers
 
+Wdiscarded-array-qualifiers
+C ObjC Var(warn_discarded_array_qualifiers) Init(1) Warning
+Warn if qualifiers on arrays which are pointer targets are discarded
+
 Wdiscarded-qualifiers
 C ObjC Var(warn_discarded_qualifiers) Init(1) Warning
 Warn if type qualifiers on pointers are discarded
index ad9b8bc156fb2108b2f97065dce017812618a6a7..1661747d6046d5ef0e7debfbfd6096d99eeea240 100644 (file)
@@ -1,3 +1,14 @@
+2014-12-20  Martin Uecker <uecker@eecs.berkeley.edu>
+
+       * c-typeck.c: New behavious for pointers to arrays with qualifiers
+        (common-pointer-type): For pointers to arrays take qualifiers from
+       element type.
+        (build_conditional_expr): Add warnings for lost qualifiers.
+       (comp-target-types): Allow pointers to arrays with different qualifiers.
+        (convert-for-assignment): Adapt warnings for discarded qualifiers. Add
+       WARNING_FOR_QUALIFIERS macro and rename WARN_FOR_QUALIFIERS
+        to PEDWARN_FOR_QUALIFIERS.
+
 2014-12-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR sanitizer/64289
index ca9d512adf85bc186afcc3ecb83ade6ffd37ce04..abd452aed39cf05e262db2054811bf0338af7863 100644 (file)
@@ -673,12 +673,13 @@ common_pointer_type (tree t1, tree t2)
     mv2 = TYPE_MAIN_VARIANT (pointed_to_2);
   target = composite_type (mv1, mv2);
 
+  /* Strip array types to get correct qualifier for pointers to arrays */
+  quals1 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_1));
+  quals2 = TYPE_QUALS_NO_ADDR_SPACE (strip_array_types (pointed_to_2));
+
   /* For function types do not merge const qualifiers, but drop them
      if used inconsistently.  The middle-end uses these to mark const
      and noreturn functions.  */
-  quals1 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_1);
-  quals2 = TYPE_QUALS_NO_ADDR_SPACE (pointed_to_2);
-
   if (TREE_CODE (pointed_to_1) == FUNCTION_TYPE)
     target_quals = (quals1 & quals2);
   else
@@ -1224,6 +1225,7 @@ static int
 comp_target_types (location_t location, tree ttl, tree ttr)
 {
   int val;
+  int val_ped;
   tree mvl = TREE_TYPE (ttl);
   tree mvr = TREE_TYPE (ttr);
   addr_space_t asl = TYPE_ADDR_SPACE (mvl);
@@ -1235,19 +1237,32 @@ comp_target_types (location_t location, tree ttl, tree ttr)
   if (!addr_space_superset (asl, asr, &as_common))
     return 0;
 
-  /* Do not lose qualifiers on element types of array types that are
-     pointer targets by taking their TYPE_MAIN_VARIANT.  */
-  if (TREE_CODE (mvl) != ARRAY_TYPE)
-    mvl = (TYPE_ATOMIC (mvl)
-          ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl), TYPE_QUAL_ATOMIC)
-          : TYPE_MAIN_VARIANT (mvl));
-  if (TREE_CODE (mvr) != ARRAY_TYPE)
-    mvr = (TYPE_ATOMIC (mvr)
-          ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC)
-          : TYPE_MAIN_VARIANT (mvr));
+  /* For pedantic record result of comptypes on arrays before losing
+     qualifiers on the element type below. */
+  val_ped = 1;
+
+  if (TREE_CODE (mvl) == ARRAY_TYPE
+      && TREE_CODE (mvr) == ARRAY_TYPE)
+    val_ped = comptypes (mvl, mvr);
+
+  /* Qualifiers on element types of array types that are
+     pointer targets are lost by taking their TYPE_MAIN_VARIANT.  */
+
+  mvl = (TYPE_ATOMIC (strip_array_types (mvl))
+        ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvl), TYPE_QUAL_ATOMIC)
+        : TYPE_MAIN_VARIANT (mvl));
+
+  mvr = (TYPE_ATOMIC (strip_array_types (mvr))
+        ? c_build_qualified_type (TYPE_MAIN_VARIANT (mvr), TYPE_QUAL_ATOMIC)
+        : TYPE_MAIN_VARIANT (mvr));
+
   enum_and_int_p = false;
   val = comptypes_check_enum_int (mvl, mvr, &enum_and_int_p);
 
+  if (val == 1 && val_ped != 1)
+    pedwarn (location, OPT_Wpedantic, "pointers to arrays with different qualifiers "
+                                      "are incompatible in ISO C");
+
   if (val == 2)
     pedwarn (location, OPT_Wpedantic, "types are not quite compatible");
 
@@ -4609,6 +4624,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       else if (VOID_TYPE_P (TREE_TYPE (type1))
               && !TYPE_ATOMIC (TREE_TYPE (type1)))
        {
+         if ((TREE_CODE (TREE_TYPE (type2)) == ARRAY_TYPE)
+             && (TYPE_QUALS (strip_array_types (TREE_TYPE (type2)))
+                 & ~TYPE_QUALS (TREE_TYPE (type1))))
+           warning_at (colon_loc, OPT_Wdiscarded_array_qualifiers,
+                       "pointer to array loses qualifier "
+                       "in conditional expression");
+
          if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
            pedwarn (colon_loc, OPT_Wpedantic,
                     "ISO C forbids conditional expr between "
@@ -4619,6 +4641,13 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
       else if (VOID_TYPE_P (TREE_TYPE (type2))
               && !TYPE_ATOMIC (TREE_TYPE (type2)))
        {
+         if ((TREE_CODE (TREE_TYPE (type1)) == ARRAY_TYPE)
+             && (TYPE_QUALS (strip_array_types (TREE_TYPE (type1)))
+                 & ~TYPE_QUALS (TREE_TYPE (type2))))
+           warning_at (colon_loc, OPT_Wdiscarded_array_qualifiers,
+                       "pointer to array loses qualifier "
+                       "in conditional expression");
+
          if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
            pedwarn (colon_loc, OPT_Wpedantic,
                     "ISO C forbids conditional expr between "
@@ -5661,7 +5690,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
   /* This macro is used to emit diagnostics to ensure that all format
      strings are complete sentences, visible to gettext and checked at
      compile time.  */
-#define WARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE)        \
+#define PEDWARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE)     \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
@@ -5688,10 +5717,9 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
 
   /* This macro is used to emit diagnostics to ensure that all format
      strings are complete sentences, visible to gettext and checked at
-     compile time.  It is the same as WARN_FOR_ASSIGNMENT but with an
+     compile time.  It is the same as PEDWARN_FOR_ASSIGNMENT but with an
      extra parameter to enumerate qualifiers.  */
-
-#define WARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS)  \
+#define PEDWARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
   do {                                                                   \
     switch (errtype)                                                     \
       {                                                                  \
@@ -5716,6 +5744,35 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
       }                                                                  \
   } while (0)
 
+  /* This macro is used to emit diagnostics to ensure that all format
+     strings are complete sentences, visible to gettext and checked at
+     compile time.  It is the same as PEDWARN_FOR_QUALIFIERS but uses
+     warning_at instead of pedwarn.  */
+#define WARNING_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
+  do {                                                                   \
+    switch (errtype)                                                     \
+      {                                                                  \
+      case ic_argpass:                                                   \
+        if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS))           \
+          inform ((fundecl && !DECL_IS_BUILTIN (fundecl))                \
+                  ? DECL_SOURCE_LOCATION (fundecl) : PLOC,               \
+                  "expected %qT but argument is of type %qT",            \
+                  type, rhstype);                                        \
+        break;                                                           \
+      case ic_assign:                                                    \
+        warning_at (LOCATION, OPT, AS, QUALS);                           \
+        break;                                                           \
+      case ic_init:                                                      \
+        warning_at (LOCATION, OPT, IN, QUALS);                           \
+        break;                                                           \
+      case ic_return:                                                    \
+        warning_at (LOCATION, OPT, RE, QUALS);                           \
+        break;                                                           \
+      default:                                                           \
+        gcc_unreachable ();                                              \
+      }                                                                  \
+  } while (0)
+
   if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
     rhs = TREE_OPERAND (rhs, 0);
 
@@ -5758,15 +5815,15 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
          && TREE_CODE (type) == ENUMERAL_TYPE
          && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
        {
-         WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
-                              G_("enum conversion when passing argument "
-                                 "%d of %qE is invalid in C++"),
-                              G_("enum conversion in assignment is "
-                                 "invalid in C++"),
-                              G_("enum conversion in initialization is "
-                                 "invalid in C++"),
-                              G_("enum conversion in return is "
-                                 "invalid in C++"));
+         PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
+                                 G_("enum conversion when passing argument "
+                                    "%d of %qE is invalid in C++"),
+                                 G_("enum conversion in assignment is "
+                                    "invalid in C++"),
+                                 G_("enum conversion in initialization is "
+                                    "invalid in C++"),
+                                 G_("enum conversion in return is "
+                                    "invalid in C++"));
        }
     }
 
@@ -5921,34 +5978,34 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
                     vice-versa.  */
                  if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
                      & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-                   WARN_FOR_QUALIFIERS (location, expr_loc,
-                                        OPT_Wdiscarded_qualifiers,
-                                        G_("passing argument %d of %qE "
-                                           "makes %q#v qualified function "
-                                           "pointer from unqualified"),
-                                        G_("assignment makes %q#v qualified "
-                                           "function pointer from "
-                                           "unqualified"),
-                                        G_("initialization makes %q#v qualified "
-                                           "function pointer from "
-                                           "unqualified"),
-                                        G_("return makes %q#v qualified function "
-                                           "pointer from unqualified"),
-                                        TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
+                   PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+                                           OPT_Wdiscarded_qualifiers,
+                                           G_("passing argument %d of %qE "
+                                              "makes %q#v qualified function "
+                                              "pointer from unqualified"),
+                                           G_("assignment makes %q#v qualified "
+                                              "function pointer from "
+                                              "unqualified"),
+                                           G_("initialization makes %q#v qualified "
+                                              "function pointer from "
+                                              "unqualified"),
+                                           G_("return makes %q#v qualified function "
+                                              "pointer from unqualified"),
+                                           TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
                }
              else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
                       & ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
-               WARN_FOR_QUALIFIERS (location, expr_loc,
-                                    OPT_Wdiscarded_qualifiers,
-                                    G_("passing argument %d of %qE discards "
-                                       "%qv qualifier from pointer target type"),
-                                    G_("assignment discards %qv qualifier "
-                                       "from pointer target type"),
-                                    G_("initialization discards %qv qualifier "
-                                       "from pointer target type"),
-                                    G_("return discards %qv qualifier from "
-                                       "pointer target type"),
-                                    TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
+               PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+                                       OPT_Wdiscarded_qualifiers,
+                                       G_("passing argument %d of %qE discards "
+                                          "%qv qualifier from pointer target type"),
+                                       G_("assignment discards %qv qualifier "
+                                          "from pointer target type"),
+                                       G_("initialization discards %qv qualifier "
+                                          "from pointer target type"),
+                                       G_("return discards %qv qualifier from "
+                                          "pointer target type"),
+                                       TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
 
              memb = marginal_memb;
            }
@@ -6096,42 +6153,69 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
                  == c_common_signed_type (mvr))
              && TYPE_ATOMIC (mvl) == TYPE_ATOMIC (mvr)))
        {
-         if (pedantic
+         /* Warn about loss of qualifers from pointers to arrays with
+            qualifiers on the element type. */
+         if (TREE_CODE (ttr) == ARRAY_TYPE)
+           {
+             ttr = strip_array_types (ttr);
+             ttl = strip_array_types (ttl);
+
+             if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
+                 & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
+               WARNING_FOR_QUALIFIERS (location, expr_loc,
+                                       OPT_Wdiscarded_array_qualifiers,
+                                       G_("passing argument %d of %qE discards "
+                                          "%qv qualifier from pointer target type"),
+                                       G_("assignment discards %qv qualifier "
+                                          "from pointer target type"),
+                                       G_("initialization discards %qv qualifier "
+                                          "from pointer target type"),
+                                       G_("return discards %qv qualifier from "
+                                          "pointer target type"),
+                                        TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
+            }
+          else if (pedantic
              && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
                  ||
                  (VOID_TYPE_P (ttr)
                   && !null_pointer_constant
                   && TREE_CODE (ttl) == FUNCTION_TYPE)))
-           WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
-                                G_("ISO C forbids passing argument %d of "
-                                   "%qE between function pointer "
-                                   "and %<void *%>"),
-                                G_("ISO C forbids assignment between "
-                                   "function pointer and %<void *%>"),
-                                G_("ISO C forbids initialization between "
-                                   "function pointer and %<void *%>"),
-                                G_("ISO C forbids return between function "
-                                   "pointer and %<void *%>"));
+           PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
+                                   G_("ISO C forbids passing argument %d of "
+                                      "%qE between function pointer "
+                                      "and %<void *%>"),
+                                   G_("ISO C forbids assignment between "
+                                      "function pointer and %<void *%>"),
+                                   G_("ISO C forbids initialization between "
+                                      "function pointer and %<void *%>"),
+                                   G_("ISO C forbids return between function "
+                                      "pointer and %<void *%>"));
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
          else if (TREE_CODE (ttr) != FUNCTION_TYPE
                   && TREE_CODE (ttl) != FUNCTION_TYPE)
            {
+             /* Don't warn about loss of qualifier for conversions from
+                qualified void* to pointers to arrays with corresponding
+                qualifier on the element type. */
+             if (!pedantic)
+               ttl = strip_array_types (ttl);
+
              /* Assignments between atomic and non-atomic objects are OK.  */
              if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
                  & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
                {
-                 WARN_FOR_QUALIFIERS (location, expr_loc,
-                                      OPT_Wdiscarded_qualifiers,
-                                      G_("passing argument %d of %qE discards "
-                                         "%qv qualifier from pointer target type"),
-                                      G_("assignment discards %qv qualifier "
-                                         "from pointer target type"),
-                                      G_("initialization discards %qv qualifier "
-                                         "from pointer target type"),
-                                      G_("return discards %qv qualifier from "
-                                         "pointer target type"),
-                                      TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
+                 PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+                                         OPT_Wdiscarded_qualifiers,
+                                         G_("passing argument %d of %qE discards "
+                                            "%qv qualifier from pointer target type"),
+                                         G_("assignment discards %qv qualifier "
+                                            "from pointer target type"),
+                                         G_("initialization discards %qv qualifier "
+                                            "from pointer target type"),
+                                         G_("return discards %qv qualifier from "
+                                            "pointer target type"),
+                                         TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
                }
              /* If this is not a case of ignoring a mismatch in signedness,
                 no warning.  */
@@ -6140,15 +6224,15 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
                ;
              /* If there is a mismatch, do warn.  */
              else if (warn_pointer_sign)
-               WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
-                                    G_("pointer targets in passing argument "
-                                       "%d of %qE differ in signedness"),
-                                    G_("pointer targets in assignment "
-                                       "differ in signedness"),
-                                    G_("pointer targets in initialization "
-                                       "differ in signedness"),
-                                    G_("pointer targets in return differ "
-                                       "in signedness"));
+                PEDWARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
+                                        G_("pointer targets in passing argument "
+                                           "%d of %qE differ in signedness"),
+                                        G_("pointer targets in assignment "
+                                           "differ in signedness"),
+                                        G_("pointer targets in initialization "
+                                           "differ in signedness"),
+                                        G_("pointer targets in return differ "
+                                           "in signedness"));
            }
          else if (TREE_CODE (ttl) == FUNCTION_TYPE
                   && TREE_CODE (ttr) == FUNCTION_TYPE)
@@ -6159,31 +6243,31 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
                 where an ordinary one is wanted, but not vice-versa.  */
              if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
                  & ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
-               WARN_FOR_QUALIFIERS (location, expr_loc,
-                                    OPT_Wdiscarded_qualifiers,
-                                    G_("passing argument %d of %qE makes "
-                                       "%q#v qualified function pointer "
-                                       "from unqualified"),
-                                    G_("assignment makes %q#v qualified function "
-                                       "pointer from unqualified"),
-                                    G_("initialization makes %q#v qualified "
-                                       "function pointer from unqualified"),
-                                    G_("return makes %q#v qualified function "
-                                       "pointer from unqualified"),
-                                    TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
+               PEDWARN_FOR_QUALIFIERS (location, expr_loc,
+                                       OPT_Wdiscarded_qualifiers,
+                                       G_("passing argument %d of %qE makes "
+                                          "%q#v qualified function pointer "
+                                          "from unqualified"),
+                                       G_("assignment makes %q#v qualified function "
+                                          "pointer from unqualified"),
+                                       G_("initialization makes %q#v qualified "
+                                          "function pointer from unqualified"),
+                                       G_("return makes %q#v qualified function "
+                                          "pointer from unqualified"),
+                                       TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr));
            }
        }
       else
        /* Avoid warning about the volatile ObjC EH puts on decls.  */
        if (!objc_ok)
-         WARN_FOR_ASSIGNMENT (location, expr_loc,
-                              OPT_Wincompatible_pointer_types,
-                              G_("passing argument %d of %qE from "
-                                 "incompatible pointer type"),
-                              G_("assignment from incompatible pointer type"),
-                              G_("initialization from incompatible "
-                                 "pointer type"),
-                              G_("return from incompatible pointer type"));
+         PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+                                 OPT_Wincompatible_pointer_types,
+                                 G_("passing argument %d of %qE from "
+                                    "incompatible pointer type"),
+                                 G_("assignment from incompatible pointer type"),
+                                 G_("initialization from incompatible "
+                                    "pointer type"),
+                                 G_("return from incompatible pointer type"));
 
       return convert (type, rhs);
     }
@@ -6200,31 +6284,31 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
         or one that results from arithmetic, even including
         a cast to integer type.  */
       if (!null_pointer_constant)
-       WARN_FOR_ASSIGNMENT (location, expr_loc,
-                            OPT_Wint_conversion,
-                            G_("passing argument %d of %qE makes "
-                               "pointer from integer without a cast"),
-                            G_("assignment makes pointer from integer "
-                               "without a cast"),
-                            G_("initialization makes pointer from "
-                               "integer without a cast"),
-                            G_("return makes pointer from integer "
-                               "without a cast"));
+       PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+                               OPT_Wint_conversion,
+                               G_("passing argument %d of %qE makes "
+                                  "pointer from integer without a cast"),
+                               G_("assignment makes pointer from integer "
+                                  "without a cast"),
+                               G_("initialization makes pointer from "
+                                  "integer without a cast"),
+                               G_("return makes pointer from integer "
+                                  "without a cast"));
 
       return convert (type, rhs);
     }
   else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
     {
-      WARN_FOR_ASSIGNMENT (location, expr_loc,
-                          OPT_Wint_conversion,
-                          G_("passing argument %d of %qE makes integer "
-                             "from pointer without a cast"),
-                          G_("assignment makes integer from pointer "
-                             "without a cast"),
-                          G_("initialization makes integer from pointer "
-                             "without a cast"),
-                          G_("return makes integer from pointer "
-                             "without a cast"));
+      PEDWARN_FOR_ASSIGNMENT (location, expr_loc,
+                             OPT_Wint_conversion,
+                             G_("passing argument %d of %qE makes integer "
+                                "from pointer without a cast"),
+                             G_("assignment makes integer from pointer "
+                                "without a cast"),
+                             G_("initialization makes integer from pointer "
+                                "without a cast"),
+                             G_("return makes integer from pointer "
+                                "without a cast"));
       return convert (type, rhs);
     }
   else if (codel == BOOLEAN_TYPE && coder == POINTER_TYPE)
index aaace5343870d22553e4d4da1931bb0caaa30843..ffefb673efee243298d688ee9bb859b48c0eca7f 100644 (file)
@@ -46,6 +46,7 @@ extensions, accepted by GCC in C90 mode and in C++.
 * Escaped Newlines::    Slightly looser rules for escaped newlines.
 * Subscripting::        Any array can be subscripted, even if not an lvalue.
 * Pointer Arith::       Arithmetic on @code{void}-pointers and function pointers.
+* Pointers to Arrays::  Pointers to arrays with qualifiers work as expected.
 * Initializers::        Non-constant initializers.
 * Compound Literals::   Compound literals give structures, unions
                         or arrays as values.
@@ -1784,6 +1785,27 @@ and on function types, and returns 1.
 The option @option{-Wpointer-arith} requests a warning if these extensions
 are used.
 
+@node Pointers to Arrays
+@section Pointers to arrays with qualifiers work as expected
+@cindex pointers to arrays
+@cindex const qualifier
+
+In GNU C, pointers to arrays with qualifiers work similar to pointers
+to other qualified types. For example, a value of type @code{int (*)[5]}
+can be used to initialize a variable of type @code{const int (*)[5]}.
+These types are incompatible in ISO C because the @code{const} qualifier
+is formally attached to the element type of the array and not the
+array itself.
+
+@smallexample
+extern void
+transpose (int N, int M, double out[M][N], const double in[N][M]);
+double x[3][2];
+double y[2][3];
+@r{@dots{}}
+transpose(3, 2, y, x);
+@end smallexample
+
 @node Initializers
 @section Non-Constant Initializers
 @cindex initializers, non-constant
index e37c777e89562b54a4b64d4c78111a75ee6f3660..9f56f42218d567417dfdbd0a59d88e695366069e 100644 (file)
@@ -248,7 +248,8 @@ Objective-C and Objective-C++ Dialects}.
 -Wchar-subscripts -Wclobbered  -Wcomment -Wconditionally-supported  @gol
 -Wconversion -Wcoverage-mismatch -Wdate-time -Wdelete-incomplete -Wno-cpp  @gol
 -Wno-deprecated -Wno-deprecated-declarations -Wno-designated-init @gol
--Wdisabled-optimization -Wno-discarded-qualifiers @gol
+-Wdisabled-optimization @gol
+-Wno-discarded-qualifiers -Wno-discarded-array-qualifiers @gol
 -Wno-div-by-zero -Wdouble-promotion -Wempty-body  -Wenum-compare @gol
 -Wno-endif-labels -Werror  -Werror=* @gol
 -Wfatal-errors  -Wfloat-equal  -Wformat  -Wformat=2 @gol
@@ -4300,9 +4301,18 @@ This warning is enabled by @option{-Wall}.
 @opindex Wdiscarded-qualifiers
 Do not warn if type qualifiers on pointers are being discarded.
 Typically, the compiler will warn if a @code{const char *} variable is
-passed to a function that takes @code{char *} parameter.  This option
+passed to a function that takes @code{char *} parameter.  This option
 can be used to suppress such a warning.
 
+@item -Wno-discarded-array-qualifiers @r{(C and Objective-C only)}
+@opindex Wno-discarded-array-qualifiers
+@opindex Wdiscarded-array-qualifiers
+Do not warn if type qualifiers on arrays which are pointer targets
+are being discarded. Typically, the compiler will warn if a
+@code{const int (*)[]} variable is passed to a function that
+takes a @code{int (*)[]} parameter.  This option can be used to
+suppress such a warning.
+
 @item -Wno-incompatible-pointer-types @r{(C and Objective-C only)}
 @opindex Wno-incompatible-pointer-types
 @opindex Wincompatible-pointer-types
index ad7acfba947d0857762fb2e55c10dcc8995052c1..fd6c398ef8827eef44788578ddafa0e570b5193c 100644 (file)
@@ -1,3 +1,13 @@
+2014-12-20  Martin Uecker <uecker@eecs.berkeley.edu>
+
+       * gcc.dg/Wwrite-strings-1.c: Change dg-warning.
+       * gcc.dg/array-quals-1.c: Use -Wno-discarded-array-qualifiers.
+       * gcc.dg/array-quals-2.c: Change dg-options, dg-warning.
+       * gcc.dg/pointer-array-atomic.c: New test.
+       * gcc.dg/pointer-array-quals-1.c: New test.
+       * gcc.dg/pointer-array-quals-2.c: New test (-pedantic-errors).
+       * gcc.dg/qual-component-1.c: Change dg-options, dg-warnings.
+
 2014-12-19  David Malcolm  <dmalcolm@redhat.com>
 
        * jit.dg/test-expressions.c (make_tests_of_casts): Add tests of
index 03bb4094104fd799523ef2c1dfc06f673fd9df77..24547d02bd806aede20d3c5dbc96a6d3773a77be 100644 (file)
@@ -5,4 +5,4 @@
 /* { dg-do compile } */
 /* { dg-options "-Wwrite-strings" } */
 typedef char T[1];
-T *p = &""; /* { dg-warning "initialization from incompatible pointer type" } */
+T *p = &""; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
index 514daf8bc55580bd5c98bada67502203b6baac9a..3981c916021d86ed2f89a770099ebed7ce3a2887 100644 (file)
@@ -3,6 +3,7 @@
    all should end up in a read-only section.  PR c/12165.  */
 /* Origin: Joseph Myers <jsm@polyomino.org.uk> */
 /* { dg-do compile } */
+/* { dg-options "-Wno-discarded-array-qualifiers" } */
 /* The MMIX port always switches to the .data section at the end of a file.  */
 /* { dg-final { scan-assembler-not "\\.data(?!\\.rel\\.ro)" { xfail powerpc*-*-aix* mmix-*-* x86_64-*-mingw* } } } */
 static const int a[2] = { 1, 2 };
index 2f1304e2a649d6467b6e8165e407dd48dd7d84da..7f33e3fb2ce98f5b9217e7607f388588bf8d0fe1 100644 (file)
@@ -3,12 +3,12 @@
    lost in forming composite types.  */
 /* Origin: Joseph Myers <joseph@codesourcery.com> */
 /* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-pedantic -Wno-discarded-array-qualifiers" } */
 typedef const char T[1];
 typedef const char T2[1];
 typedef volatile char U[1];
 T *p;
 T2 *p2;
 U *q;
-void *f(void) { return 1 ? p : q; } /* { dg-warning "pointer type mismatch in conditional expression" } */
+void *f(void) { return 1 ? p : q; } /* { dg-warning "pointers to arrays with different qualifiers" } */
 T *g(void) { return 1 ? p : p2; }
diff --git a/gcc/testsuite/gcc.dg/pointer-array-atomic.c b/gcc/testsuite/gcc.dg/pointer-array-atomic.c
new file mode 100644 (file)
index 0000000..55b58e8
--- /dev/null
@@ -0,0 +1,60 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c11" } */
+/* Origin: Martin Uecker <uecker@eecs.berkeley.edu> */
+void tvoid(void* x);
+void transpose0(double* out, _Atomic double* in) { }
+void transpose1(double out[2][2], _Atomic double in[2][2]) { }
+void transpose2(double out[2][2][2], _Atomic double in[2][2][2]) { }
+// return
+int (*x2(_Atomic int x[3][3]))[3] { return x; } /* { dg-warning "return from incompatible pointer type" } */
+_Atomic int (*x3(int x[3][3]))[3] { return x; } /* { dg-warning "return from incompatible pointer type" } */
+void test(void)
+{
+       double x0[2];
+       double y0[2];
+       _Atomic double z0[4];
+       double x1[2][2];
+       double y1[2][2];
+       double o1[2][3];
+       _Atomic double z1[2][2];
+       double x2[2][2][2];
+       double y2[2][2][2];
+       double o2[2][2][3];
+       _Atomic double z2[2][2][2];
+       tvoid(z0);
+       tvoid(z1);
+       tvoid(z2);
+       // passing as arguments
+       transpose0(y0, x0); /* { dg-warning "passing argument 2 of 'transpose0' from incompatible pointer type" } */
+       transpose1(y1, o1); /* { dg-warning "passing argument 2 of 'transpose1' from incompatible pointer type" } */
+       transpose1(y1, x1); /* { dg-warning "passing argument 2 of 'transpose1' from incompatible pointer type" } */
+       transpose2(y2, o2); /* { dg-warning "passing argument 2 of 'transpose2' from incompatible pointer type" } */
+       transpose2(y2, x2); /* { dg-warning "passing argument 2 of 'transpose2' from incompatible pointer type" } */
+       // initialization
+       _Atomic double (*x0p) = x0; /* { dg-warning "initialization from incompatible pointer type" } */
+       _Atomic double (*x1p)[2] = x1; /* { dg-warning "initialization from incompatible pointer type" } */
+       _Atomic double (*x2p)[2][2] = x2; /* { dg-warning "initialization from incompatible pointer type" } */
+       // assignment
+       x0p = x0; /* { dg-warning "assignment from incompatible pointer type" } */
+       x1p = x1; /* { dg-warning "assignment from incompatible pointer type" } */
+       x2p = x2; /* { dg-warning "assignment from incompatible pointer type" } */
+       // subtraction
+       &(x0[1]) - &(z0[0]); /* { dg-error "invalid operands to binary" } */
+       &(x1[1]) - &(z1[0]); /* { dg-error "invalid operands to binary" } */
+       &(x2[1]) - &(z2[0]); /* { dg-error "invalid operands to binary" } */
+       // comparison
+       x0 == z0; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       x1 == z1; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       x2 == z2; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       x0 > z0; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       x1 > z1; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       x2 > z2; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       x0 < z0; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       x1 < z1; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       x2 < z2; /* { dg-warning "comparison of distinct pointer types lacks a cast" } */
+       // conditional expressions
+       (void)(1 ? x0 : z0); /* { dg-warning "pointer type mismatch in conditional expression" } */
+       (void)(1 ? x1 : z1); /* { dg-warning "pointer type mismatch in conditional expression" } */
+       (void)(1 ? x2 : z2); /* { dg-warning "pointer type mismatch in conditional expression" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/pointer-array-quals-1.c b/gcc/testsuite/gcc.dg/pointer-array-quals-1.c
new file mode 100644 (file)
index 0000000..921a37e
--- /dev/null
@@ -0,0 +1,106 @@
+/* { dg-do compile } */
+/* Origin: Martin Uecker <uecker@eecs.berkeley.edu> */
+/* { dg-options "-Wdiscarded-array-qualifiers" } */
+void tvoid(void* x);
+void transpose0(double* out, const double* in) { }
+void transpose1(double out[2][2], const double in[2][2]) { }
+void transpose2(double out[2][2][2], const double in[2][2][2]) { }
+// return
+int (*y2(const int x[3][3]))[3] { return x; } /* { dg-warning "return discards 'const' qualifier from pointer target type" } */
+const int (*y3(int x[3][3]))[3] { return x; }
+void test(void)
+{
+       double x0[2];
+       double y0[2];
+       const double z0[4];
+       double x1[2][2];
+       double y1[2][2];
+       double o1[2][3];
+       const double z1[2][2];
+       double x2[2][2][2];
+       double y2[2][2][2];
+       double o2[2][2][3];
+       const double z2[2][2][2];
+       // void pointers
+       tvoid(x0);
+       tvoid(x1);
+       tvoid(x2);
+       tvoid(z0); /* { dg-warning "passing argument 1 of 'tvoid' discards 'const' qualifier from pointer target type" } */
+       tvoid(z1); /* { dg-warning "passing argument 1 of 'tvoid' discards 'const' qualifier from pointer target type" } */
+       tvoid(z2); /* { dg-warning "passing argument 1 of 'tvoid' discards 'const' qualifier from pointer target type" } */
+       void* p;
+       const void* pc;
+       p = x0;
+       p = x1;
+       p = x2;
+       p = z0; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       p = z1; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       p = z2; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       pc = x0;
+       pc = x1;
+       pc = x2;
+       pc = z0;
+       pc = z1;
+       pc = z2;
+       transpose0(pc, p); /* { dg-warning "passing argument 1 of 'transpose0' discards 'const' qualifier from pointer target type" } */
+       transpose1(pc, p); /* { dg-warning "passing argument 1 of 'transpose1' discards 'const' qualifier from pointer target type" } */
+       transpose2(pc, p); /* { dg-warning "passing argument 1 of 'transpose2' discards 'const' qualifier from pointer target type" } */
+       transpose0(p, pc);
+       transpose1(p, pc);
+       transpose2(p, pc);
+       // passing as arguments
+       transpose0(y0, x0);
+       transpose1(y1, x1);
+       transpose2(y2, x2);
+       // initialization
+       const double (*u0p) = x0;
+       const double (*u1p)[2] = x1;
+       const double (*u2p)[2][2] = x2;
+       double (*v0p) = z0; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
+       double (*v1p)[2] = z1; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
+       double (*v2p)[2][2] = z2; /* { dg-warning "initialization discards 'const' qualifier from pointer target type" } */
+       // subtraction
+       &(x0[1]) - &(z0[0]);
+       &(x1[1]) - &(z1[0]);
+       &(x2[1]) - &(z2[0]);
+       // comparison
+       x0 == z0;
+       x1 == z1;
+       x2 == z2;
+       x0 < z0; 
+       x1 < z1; 
+       x2 < z2; 
+       x0 > z0;
+       x1 > z1;
+       x2 > z2;
+       // assignment
+       u0p = x0;
+       u1p = x1;
+       u2p = x2;
+       v0p = z0; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = z1; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v2p = z2; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       // conditional expressions
+       (void)(1 ? x0 : z0);
+       (void)(1 ? x1 : z1);
+       (void)(1 ? x2 : z2);
+       (void)(1 ? x0 : x1); /* { dg-warning "pointer type mismatch in conditional expression" } */
+       (void)(1 ? x1 : x2); /* { dg-warning "pointer type mismatch in conditional expression" } */
+       (void)(1 ? x2 : x0); /* { dg-warning "pointer type mismatch in conditional expression" } */
+       v0p = (1 ? z0 : v0p); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = (1 ? z1 : v1p); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v2p = (1 ? z2 : v2p); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v0p = (1 ? x0 : u0p); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = (1 ? x1 : u1p); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v2p = (1 ? x2 : u2p); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       (1 ? x0 : z0)[0] = 1; /* { dg-error "assignment of read-only location" } */
+       (1 ? x1 : z1)[0][0] = 1; /* { dg-error "assignment of read-only location" } */
+       (1 ? x2 : z2)[0][0][0] = 1; /* { dg-error "assignment of read-only location" } */
+       v0p = (1 ? p : z0); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = (1 ? p : z1); /* { dg-warning "pointer to array loses qualifier in conditional expression" } */
+       v2p = (1 ? p : z2); /* { dg-warning "pointer to array loses qualifier in conditional expression" } */
+       v0p = (1 ? pc : x0); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = (1 ? pc : x1); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       v2p = (1 ? pc : x2); /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+}
+
diff --git a/gcc/testsuite/gcc.dg/pointer-array-quals-2.c b/gcc/testsuite/gcc.dg/pointer-array-quals-2.c
new file mode 100644 (file)
index 0000000..30689c7
--- /dev/null
@@ -0,0 +1,102 @@
+/* { dg-do compile } */
+/* { dg-options "-Wdiscarded-array-qualifiers -pedantic-errors" } */
+/* Origin: Martin Uecker <uecker@eecs.berkeley.edu> */
+void tvoid(void* x);
+void transpose0(double* out, const double* in) { }
+void transpose1(double out[2][2], const double in[2][2]) { }
+void transpose2(double out[2][2][2], const double in[2][2][2]) { }
+// return
+int (*x2(const int x[3][3]))[3] { return x; } /* { dg-error "pointers to arrays with different qualifiers|return discards" } */
+const int (*x3(int x[3][3]))[3] { return x; } /* { dg-error "pointers to arrays with different qualifiers" } */
+void test(void)
+{
+       double x0[2];
+       double y0[2];
+       const double z0[4];
+       double x1[2][2];
+       double y1[2][2];
+       double o1[2][3];
+       const double z1[2][2];
+       double x2[2][2][2];
+       double y2[2][2][2];
+       double o2[2][2][3];
+       const double z2[2][2][2];
+       // void pointers
+       tvoid(z0); /* { dg-error "passing argument 1 of 'tvoid' discards 'const' qualifier from pointer target type" } */
+       tvoid(z1); /* { dg-warning "passing argument 1 of 'tvoid' discards 'const' qualifier from pointer target type" } */
+       tvoid(z2); /* { dg-warning "passing argument 1 of 'tvoid' discards 'const' qualifier from pointer target type" } */
+       void* p;
+       const void* pc;
+       p = x0;
+       p = x1;
+       p = x2;
+       p = z0; /* { dg-error "assignment discards 'const' qualifier from pointer target type" } */
+       p = z1; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       p = z2; /* { dg-warning "assignment discards 'const' qualifier from pointer target type" } */
+       pc = x0;
+       pc = x1;
+       pc = x2;
+       pc = z0;
+       pc = z1;
+       pc = z2;
+       transpose0(pc, p); /* { dg-error "passing argument 1 of 'transpose0' discards 'const' qualifier from pointer target type" } */
+       transpose1(pc, p); /* { dg-error "passing argument 1 of 'transpose1' discards 'const' qualifier from pointer target type" } */
+       transpose2(pc, p); /* { dg-error "passing argument 1 of 'transpose2' discards 'const' qualifier from pointer target type" } */
+       transpose0(p, pc);
+       transpose1(p, pc); /* { dg-error "passing argument 2 of 'transpose1' discards 'const' qualifier from pointer target type" } */
+       transpose2(p, pc); /* { dg-error "passing argument 2 of 'transpose2' discards 'const' qualifier from pointer target type" } */
+       // passing as arguments
+       transpose0(y0, x0);
+       transpose1(y1, o1); /* { dg-error "passing argument 2 of 'transpose1' from incompatible pointer type" } */
+       transpose1(y1, x1); /* { dg-error "pointers to arrays with different qualifiers" } */
+       transpose2(y2, o2); /* { dg-error "passing argument 2 of 'transpose2' from incompatible pointer type" } */
+       transpose2(y2, x2); /* { dg-error "pointers to arrays with different qualifiers" } */
+       // initialization
+       const double (*x0p) = x0;
+       const double (*x1p)[2] = x1; /* { dg-error "pointers to arrays with different qualifiers" } */
+       const double (*x2p)[2][2] = x2; /* { dg-error "pointers to arrays with different qualifiers" } */
+       double (*v0p) = z0; /* { dg-error "initialization discards 'const' qualifier from pointer target type" } */
+       double (*v1p)[2] = z1; /* { dg-error "pointers to arrays with different qualifiers|initialization discards" } */
+       double (*v2p)[2][2] = z2; /* { dg-error "pointers to arrays with different qualifiers|initialization discards" } */
+       // assignment
+       x0p = x0;
+       x1p = x1; /* { dg-error "pointers to arrays with different qualifiers" } */
+       x2p = x2; /* { dg-error "pointers to arrays with different qualifiers" } */
+       // subtraction
+       &(x0[1]) - &(z0[0]);
+       &(x1[1]) - &(z1[0]); /* { dg-error "pointers to arrays with different qualifiers" } */
+       &(x2[1]) - &(z2[0]); /* { dg-error "pointers to arrays with different qualifiers" } */
+       // comparison
+       x0 == z0;
+       x1 == z1; /* { dg-error "pointers to arrays with different qualifiers" } */
+       x2 == z2; /* { dg-error "pointers to arrays with different qualifiers" } */
+       x0 < z0;
+       x1 < z1; /* { dg-error "pointers to arrays with different qualifiers" } */
+       x2 < z2; /* { dg-error "pointers to arrays with different qualifiers" } */
+       x0 > z0;
+       x1 > z1; /* { dg-error "pointers to arrays with different qualifiers" } */
+       x2 > z2; /* { dg-error "pointers to arrays with different qualifiers" } */
+       // conditional expressions
+       (void)(1 ? x0 : z0);
+       (void)(1 ? x1 : z1); /* { dg-error "pointers to arrays with different qualifiers" } */
+       (void)(1 ? x2 : z2); /* { dg-error "pointers to arrays with different qualifiers" } */
+       (void)(1 ? x0 : x1); /* { dg-error "pointer type mismatch in conditional expression" } */
+       (void)(1 ? x1 : x2); /* { dg-error "pointer type mismatch in conditional expression" } */
+       (void)(1 ? x2 : x0); /* { dg-error "pointer type mismatch in conditional expression" } */
+       v0p = (1 ? z0 : v0p); /* { dg-error "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = (1 ? z1 : v1p); /* { dg-error "pointers to arrays with different qualifiers|assignment discards" } */
+       v2p = (1 ? z2 : v2p); /* { dg-error "pointers to arrays with different qualifiers|assignment discards" } */
+       v0p = (1 ? x0 : x0p); /* { dg-error "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = (1 ? x1 : x1p); /* { dg-error "pointers to arrays with different qualifiers|assignment discards" } */
+       v2p = (1 ? x2 : x2p); /* { dg-error "pointers to arrays with different qualifiers|assignment discards" } */
+       (1 ? x0 : z0)[0] = 1; /* { dg-error "assignment of read-only location" } */
+       (1 ? x1 : z1)[0][0] = 1; /* { dg-error "assignment of read-only location|pointers to arrays" } */
+       (1 ? x2 : z2)[0][0][0] = 1; /* { dg-error "assignment of read-only location|pointers to arrays" } */
+       v0p = (1 ? p : z0); /* { dg-error "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = (1 ? p : z1); /* { dg-warning "pointer to array loses qualifier in conditional expression" } */
+       v2p = (1 ? p : z2); /* { dg-warning "pointer to array loses qualifier in conditional expression" } */
+       v0p = (1 ? pc : x0); /* { dg-error "assignment discards 'const' qualifier from pointer target type" } */
+       v1p = (1 ? pc : x1); /* { dg-error "assignment discards 'const' qualifier from pointer target type" } */
+       v2p = (1 ? pc : x2); /* { dg-error "assignment discards 'const' qualifier from pointer target type" } */
+}
+
index dedc63f39b201ddf377c4abc9dbd470b9cc225be..4eaa71a2d19acdad57e339e14014c9bc86570926 100644 (file)
@@ -3,7 +3,7 @@
    union.  Bug 27697 from Frank Victor Fischer.  */
 /* Origin: Joseph Myers <joseph@codesourcery.com> */
 /* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-pedantic -Wdiscarded-array-qualifiers" } */
 
 struct s {
   int a;
@@ -110,24 +110,24 @@ g (void)
     int (*b)[1] = &v1.b;
     int (*c)[2][3] = &v1.c;
     int (*cc)[3] = v1.c;
-    const int (*ff)[3] = v1.c; /* { dg-warning "initialization from incompatible pointer type" } */
+    const int (*ff)[3] = v1.c; /* { dg-warning "pointers to arrays with different qualifiers" } */
     a = &v1.a;
     b = &v1.b;
     c = &v1.c;
     cc = v1.c;
-    ff = v1.c; /* { dg-warning "assignment from incompatible pointer type" } */
+    ff = v1.c; /* { dg-warning "pointers to arrays with different qualifiers" } */
   }
   {
     const int *d = &v1.d;
     const int (*e)[1] = &v1.e;
     const int (*f)[2][3] = &v1.f;
     const int (*ff)[3] = v1.f;
-    int (*cc)[3] = v1.f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v1.f; /* { dg-warning "pointers to arrays with different qualifiers|initialization discards" } */
     d = &v1.d;
     e = &v1.e;
     f = &v1.f;
     ff = v1.f;
-    cc = v1.f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v1.f; /* { dg-warning "pointers to arrays with different qualifiers|assignment discards" } */
   }
 
   {
@@ -135,24 +135,24 @@ g (void)
     int (*b)[1] = &v2->b;
     int (*c)[2][3] = &v2->c;
     int (*cc)[3] = v2->c;
-    const int (*ff)[3] = v2->c; /* { dg-warning "initialization from incompatible pointer type" } */
+    const int (*ff)[3] = v2->c; /* { dg-warning "pointers to arrays with different qualifiers" } */
     a = &v2->a;
     b = &v2->b;
     c = &v2->c;
     cc = v2->c;
-    ff = v2->c; /* { dg-warning "assignment from incompatible pointer type" } */
+    ff = v2->c; /* { dg-warning "pointers to arrays with different qualifiers" } */
   }
   {
     const int *d = &v2->d;
     const int (*e)[1] = &v2->e;
     const int (*f)[2][3] = &v2->f;
     const int (*ff)[3] = v2->f;
-    int (*cc)[3] = v2->f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v2->f; /* { dg-warning "pointers to arrays with different qualifiers|initialization discards" } */
     d = &v2->d;
     e = &v2->e;
     f = &v2->f;
     ff = v2->f;
-    cc = v2->f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v2->f; /* { dg-warning "pointers to arrays with different qualifiers|assignment discards" } */
   }
 
   {
@@ -160,24 +160,24 @@ g (void)
     const int (*e)[1] = &v3->b;
     const int (*f)[2][3] = &v3->c;
     const int (*ff)[3] = v3->c;
-    int (*cc)[3] = v3->c; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v3->c; /* { dg-warning "pointers to arrays with different qualifiers|initialization discards" } */
     d = &v3->a;
     e = &v3->b;
     f = &v3->c;
     ff = v3->c;
-    cc = v3->c; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v3->c; /* { dg-warning "pointers to arrays with different qualifiers|assignment discards" } */
   }
   {
     const int *d = &v3->d;
     const int (*e)[1] = &v3->e;
     const int (*f)[2][3] = &v3->f;
     const int (*ff)[3] = v3->f;
-    int (*cc)[3] = v3->f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v3->f; /* { dg-warning "pointers to arrays with different qualifiers|initialization discards" } */
     d = &v3->d;
     e = &v3->e;
     f = &v3->f;
     ff = v3->f;
-    cc = v3->f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v3->f; /* { dg-warning "pointers to arrays with different qualifiers|assignment discards" } */
   }
 
   {
@@ -185,24 +185,24 @@ g (void)
     const int (*e)[1] = &v4.b;
     const int (*f)[2][3] = &v4.c;
     const int (*ff)[3] = v4.c;
-    int (*cc)[3] = v4.c; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v4.c; /* { dg-warning "pointers to arrays with different qualifiers|initialization discards" } */
     d = &v4.a;
     e = &v4.b;
     f = &v4.c;
     ff = v4.c;
-    cc = v4.c; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v4.c; /* { dg-warning "pointers to arrays with different qualifiers|assignment discards" } */
   }
   {
     const int *d = &v4.d;
     const int (*e)[1] = &v4.e;
     const int (*f)[2][3] = &v4.f;
     const int (*ff)[3] = v4.f;
-    int (*cc)[3] = v4.f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v4.f; /* { dg-warning "pointers to arrays with different qualifiers|initialization discards" } */
     d = &v4.d;
     e = &v4.e;
     f = &v4.f;
     ff = v4.f;
-    cc = v4.f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v4.f; /* { dg-warning "pointers to arrays with different qualifiers|assignment discards" } */
   }
 
   {
@@ -210,23 +210,23 @@ g (void)
     const int (*e)[1] = &v5.x.b;
     const int (*f)[2][3] = &v5.x.c;
     const int (*ff)[3] = v5.x.c;
-    int (*cc)[3] = v5.x.c; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v5.x.c; /* { dg-warning "pointers to arrays with different qualifiers|initialization discards" } */
     d = &v5.x.a;
     e = &v5.x.b;
     f = &v5.x.c;
     ff = v5.x.c;
-    cc = v5.x.c; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v5.x.c; /* { dg-warning "pointers to arrays with different qualifiers|assignment discards" } */
   }
   {
     const int *d = &v5.x.d;
     const int (*e)[1] = &v5.x.e;
     const int (*f)[2][3] = &v5.x.f;
     const int (*ff)[3] = v5.x.f;
-    int (*cc)[3] = v5.x.f; /* { dg-warning "initialization from incompatible pointer type" } */
+    int (*cc)[3] = v5.x.f; /* { dg-warning "pointers to arrays with different qualifiers|initialization discards" } */
     d = &v5.x.d;
     e = &v5.x.e;
     f = &v5.x.f;
     ff = v5.x.f;
-    cc = v5.x.f; /* { dg-warning "assignment from incompatible pointer type" } */
+    cc = v5.x.f; /* { dg-warning "pointers to arrays with different qualifiers|assignment discards" } */
   }
 }