Am Freitag, den 11.06.2021, 21:25 +0200 schrieb Martin Uecker:
> (PING. In case you missed this. Sorry, forgot to CC you.)
> 
> Am Montag, den 24.05.2021, 08:05 +0200 schrieb Martin Uecker:
> > Hi Joseph,
> > 
> > I found some time to update this patch. The only real change
> > of the patch is the qualifier in the conditional expression for
> > pointer to arrays in C2X. All the rest are the warnings,
> > which were wrong in the last version.
> > 
> > I hope I got this correct this time in combination with
> > -pedantic-errors and -Wc11-c2x-compat. 
> > 
> > Martin
> > 
> > 
> > 2021-05-16  Martin Uecker  <muec...@gwdg.de>
> >     
> > gcc/c/
> >      PR c/98397
> >      * c-typeck.c (comp_target_types): Change pedwarn to pedwarn_c11
> >      for pointers to arrays with qualifiers.
> >      (build_conditional_expr): For C23 don't lose qualifiers for pointers
> >      to arrays when the other pointer is a void pointer. Update warnings.
> >      (convert_for_assignment): Update warnings for C2X when converting from
> >      void* with qualifiers to a pointer to array with the same qualifiers.
> > 
> > gcc/testsuite/
> >      PR c/98397
> >      * gcc.dg/c11-qual-1.c: New test.
> >      * gcc.dg/c2x-qual-1.c: New test.
> >      * gcc.dg/c2x-qual-2.c: New test.
> >      * gcc.dg/c2x-qual-3.c: New test.
> >      * gcc.dg/c2x-qual-4.c: New test.
> >      * gcc.dg/c2x-qual-5.c: New test.
> >      * gcc.dg/c2x-qual-6.c: New test.
> >      * gcc.dg/pointer-array-quals-1.c: Remove unnecessary flag.
> >      * gcc.dg/pointer-array-quals-2.c: Remove unnecessary flag.
> > 
> > 
> > diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
> > index fc64ef96fb8..5b13656c090 100644
> > --- a/gcc/c/c-typeck.c
> > +++ b/gcc/c/c-typeck.c
> > @@ -1328,8 +1328,8 @@ comp_target_types (location_t location, tree ttl, 
> > tree ttr)
> >    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");
> > +    pedwarn_c11 (location, OPT_Wpedantic, "invalid use of pointers to 
> > arrays with different
> > qualifiers "
> > +                                     "in ISO C before C2X");
> >  
> >    if (val == 2)
> >      pedwarn (location, OPT_Wpedantic, "types are not quite compatible");
> > @@ -5396,39 +5396,40 @@ build_conditional_expr (location_t colon_loc, tree 
> > ifexp, bool
> > ifexp_bcp,
> >                 "used in conditional expression");
> >       return error_mark_node;
> >     }
> > -      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)
> > +      else if ((VOID_TYPE_P (TREE_TYPE (type1))
> > +           && !TYPE_ATOMIC (TREE_TYPE (type1)))
> > +          || (VOID_TYPE_P (TREE_TYPE (type2))
> > +              && !TYPE_ATOMIC (TREE_TYPE (type2))))
> > +   {
> > +     tree t1 = TREE_TYPE (type1);
> > +     tree t2 = TREE_TYPE (type2);
> > +     if (!VOID_TYPE_P (t1))
> > +      {
> > +        /* roles are swapped */
> > +        t1 = t2;
> > +        t2 = TREE_TYPE (type1);
> > +      }
> > +     tree t2_stripped = strip_array_types (t2);
> > +     if ((TREE_CODE (t2) == ARRAY_TYPE)
> > +         && (TYPE_QUALS (t2_stripped) & ~TYPE_QUALS (t1)))
> > +       {
> > +         if (!flag_isoc2x)
> > +           warning_at (colon_loc, OPT_Wdiscarded_array_qualifiers,
> > +                       "pointer to array loses qualifier "
> > +                       "in conditional expression");
> > +         else if (warn_c11_c2x_compat > 0)
> > +           warning_at (colon_loc, OPT_Wc11_c2x_compat,
> > +                       "pointer to array loses qualifier "
> > +                       "in conditional expression in ISO C before C2X");
> > +       }
> > +     if (TREE_CODE (t2) == FUNCTION_TYPE)
> >         pedwarn (colon_loc, OPT_Wpedantic,
> >                  "ISO C forbids conditional expr between "
> >                  "%<void *%> and function pointer");
> > -     result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
> > -                                                     TREE_TYPE (type2)));
> > -   }
> > -      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 "
> > -                "%<void *%> and function pointer");
> > -     result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
> > -                                                     TREE_TYPE (type1)));
> > +     /* for array, use qualifiers of element type */
> > +     if (flag_isoc2x)
> > +       t2 = t2_stripped;
> > +     result_type = build_pointer_type (qualify_type (t1, t2));
> >     }
> >        /* Objective-C pointer comparisons are a bit more lenient.  */
> >        else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
> > @@ -6786,27 +6787,40 @@ 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 PEDWARN_FOR_ASSIGNMENT but with an
> > -     extra parameter to enumerate qualifiers.  */
> > -#define PEDWARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) 
> > \
> > +     compile time.  It can be called with 'pedwarn' or 'warning_at'.  */
> > +#define WARNING_FOR_QUALIFIERS(PEDWARN, LOCATION, PLOC, OPT, AR, AS, IN, 
> > RE, QUALS) \
> >    do {                                                                   \
> >      switch (errtype)                                                     \
> >        {                                                                  \
> >        case ic_argpass:                                                   \
> > -   {                                                               \
> > -   auto_diagnostic_group d;                                                
> > \
> > -   if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS))             \
> > -     inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype);     \
> > -   }                                                               \
> > +   {                                                                \
> > +     auto_diagnostic_group d;                                       \
> > +     if (PEDWARN) {                                                 \
> > +       if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS))          \
> > +         inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype);  \
> > +     } else {                                                       \
> > +       if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS))       \
> > +         inform_for_arg (fundecl, (PLOC), parmnum, type, rhstype);  \
> > +     }                                                              \
> > +   }                                                                \
> >          break;                                                           \
> >        case ic_assign:                                                    \
> > -        pedwarn (LOCATION, OPT, AS, QUALS);                                
> >  \
> > +   if (PEDWARN)                                                     \
> > +     pedwarn (LOCATION, OPT, AS, QUALS);                            \
> > +   else                                                             \
> > +     warning_at (LOCATION, OPT, AS, QUALS);                         \
> >          break;                                                           \
> >        case ic_init:                                                      \
> > -        pedwarn (LOCATION, OPT, IN, QUALS);                                
> >  \
> > +   if (PEDWARN)                                                     \
> > +     pedwarn (LOCATION, OPT, IN, QUALS);                            \
> > +   else                                                             \
> > +     warning_at (LOCATION, OPT, IN, QUALS);                         \
> >          break;                                                           \
> >        case ic_return:                                                    \
> > -        pedwarn (LOCATION, OPT, RE, QUALS);                                
> >  \
> > +   if (PEDWARN)                                                     \
> > +     pedwarn (LOCATION, OPT, RE, QUALS);                            \
> > +   else                                                             \
> > +     warning_at (LOCATION, OPT, RE, QUALS);                         \
> >          break;                                                           \
> >        default:                                                           \
> >          gcc_unreachable ();                                              \
> > @@ -6815,32 +6829,11 @@ 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 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:                                                   \
> > -   {                                                               \
> > -     auto_diagnostic_group d;                                              
> > \
> > -     if (warning_at (PLOC, OPT, AR, parmnum, rname, QUALS))        \
> > -       inform_for_arg (fundecl, (PLOC), parmnum, 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)
> > +     compile time.  It is the same as PEDWARN_FOR_ASSIGNMENT but with an
> > +     extra parameter to enumerate qualifiers.  */
> > +#define PEDWARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) 
> > \
> > +   WARNING_FOR_QUALIFIERS (true, LOCATION, PLOC, OPT, AR, AS, IN, RE, 
> > QUALS)
> > +
> >  
> >    if (TREE_CODE (rhs) == EXCESS_PRECISION_EXPR)
> >      rhs = TREE_OPERAND (rhs, 0);
> > @@ -7348,17 +7341,18 @@ convert_for_assignment (location_t location, 
> > location_t expr_loc, tree
> > type,
> >  
> >           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 
> > "
> > +           WARNING_FOR_QUALIFIERS (flag_isoc2x,
> > +                                   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 "
> > +                                   G_("assignment discards %qv qualifier "
> >                                        "from pointer target type"),
> > -                                   G_("initialization discards %qv 
> > qualifier "
> > +                                   G_("initialization discards %qv 
> > qualifier "
> >                                        "from pointer target type"),
> > -                                   G_("return discards %qv qualifier from "
> > +                                   G_("return discards %qv qualifier from "
> >                                        "pointer target type"),
> > -                                        TYPE_QUALS (ttr) & ~TYPE_QUALS 
> > (ttl));
> > +                                   TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl));
> >              }
> >            else if (pedantic
> >           && ((VOID_TYPE_P (ttl) && TREE_CODE (ttr) == FUNCTION_TYPE)
> > @@ -7381,28 +7375,31 @@ convert_for_assignment (location_t location, 
> > location_t expr_loc, tree
> > type,
> >       else if (TREE_CODE (ttr) != FUNCTION_TYPE
> >                && TREE_CODE (ttl) != FUNCTION_TYPE)
> >         {
> > +          /* Assignments between atomic and non-atomic objects are OK.  */
> > +          bool warn_quals_ped = TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
> > +                                & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC 
> > (ttl);
> > +          bool warn_quals = TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
> > +                            & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC 
> > (strip_array_types (ttl));
> > +
> >           /* 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);
> > +            qualifier on the element type (except for pedantic before 
> > C23). */
> > +         if (warn_quals || (warn_quals_ped && pedantic && !flag_isoc2x))
> > +           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));
> > +         else if (warn_quals_ped)
> > +           pedwarn_c11 (location, OPT_Wc11_c2x_compat,
> > +                        "array with qualifier on the element is not 
> > qualified before C2X");
> >  
> > -         /* 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))
> > -           {
> > -             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.  */
> >           else if (VOID_TYPE_P (ttl) || VOID_TYPE_P (ttr)
> > diff --git a/gcc/testsuite/gcc.dg/c11-qual-1.c 
> > b/gcc/testsuite/gcc.dg/c11-qual-1.c
> > new file mode 100644
> > index 00000000000..f731e068830
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c11-qual-1.c
> > @@ -0,0 +1,11 @@
> > +/* Test that qualifiers are lost in tertiary operator for pointers to 
> > arrays before C2X,
> > PR98397
> > */
> > +/* { dg-do compile } */
> > +/* { dg-options "-std=c11 -pedantic-errors 
> > -Wno-discarded-array-qualifiers" } */
> > +
> > +void foo(void)
> > +{
> > +   const int (*u)[1];
> > +   void *v;
> > +   _Static_assert(_Generic(1 ? u : v, const void*: 0, void*: 1), 
> > "qualifier not lost");
> > +   _Static_assert(_Generic(1 ? v : u, const void*: 0, void*: 1), 
> > "qualifier not lost");
> > +}
> > diff --git a/gcc/testsuite/gcc.dg/c2x-qual-1.c 
> > b/gcc/testsuite/gcc.dg/c2x-qual-1.c
> > new file mode 100644
> > index 00000000000..4d33db1907d
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c2x-qual-1.c
> > @@ -0,0 +1,30 @@
> > +/* Tests related to qualifiers and pointers to arrays in C2X, PR98397 */
> > +/* { dg-do compile } */
> > +/* { dg-options "-std=c2x -pedantic-errors" } */
> > +
> > +/* test that qualifiers are preserved in tertiary operator for pointers to 
> > arrays in C2X */
> > +
> > +void f(void)
> > +{
> > +   const int (*u)[1];
> > +   void *v;
> > +   _Static_assert(_Generic(1 ? u : v, const void*: 1, void*: 0), "lost 
> > qualifier");
> > +   _Static_assert(_Generic(1 ? v : u, const void*: 1, void*: 0), "lost 
> > qualifier");
> > +}
> > +
> > +/* test that assignment of unqualified to qualified pointers works as 
> > expected */
> > +
> > +void g(void)
> > +{
> > +   int (*x)[3];
> > +   const int (*p)[3] = x;
> > +}
> > +
> > +/* test that assignment of qualified void pointers works as expected */
> > +
> > +void h(void)
> > +{
> > +   const void* x;
> > +   const int (*p)[3] = x;
> > +}
> > +
> > diff --git a/gcc/testsuite/gcc.dg/c2x-qual-2.c 
> > b/gcc/testsuite/gcc.dg/c2x-qual-2.c
> > new file mode 100644
> > index 00000000000..f60a5b18faa
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c2x-qual-2.c
> > @@ -0,0 +1,30 @@
> > +/* Tests related to qualifiers and pointers to arrays in C2X, PR98397 */
> > +/* { dg-do compile } */
> > +/* { dg-options "-std=c2x -Wc11-c2x-compat" } */
> > +
> > +/* test that qualifiers are preserved in tertiary operator for pointers to 
> > arrays in C2X */
> > +
> > +void f(void)
> > +{
> > +   const int (*u)[1];
> > +   void *v;
> > +   _Static_assert(_Generic(1 ? u : v, const void*: 1, void*: 0), "lost 
> > qualifier");        /* { dg-
> > warning "pointer to array loses qualifier in conditional" } */
> > +   _Static_assert(_Generic(1 ? v : u, const void*: 1, void*: 0), "lost 
> > qualifier");        /* { dg-
> > warning "pointer to array loses qualifier in conditional" } */
> > +}
> > +
> > +/* test that assignment of unqualified to qualified pointers works as 
> > expected */
> > +
> > +void g(void)
> > +{
> > +   int (*x)[3];
> > +   const int (*p)[3] = x; /* { dg-warning "arrays with different 
> > qualifiers"  } */
> > +}
> > +
> > +/* test that assignment of qualified void pointers works as expected */
> > +
> > +void h(void)
> > +{
> > +   const void* x;
> > +   const int (*p)[3] = x; /* { dg-warning "array with qualifier on the 
> > element is not qualified
> > before C2X" } */
> > +}
> > +
> > diff --git a/gcc/testsuite/gcc.dg/c2x-qual-3.c 
> > b/gcc/testsuite/gcc.dg/c2x-qual-3.c
> > new file mode 100644
> > index 00000000000..31896fcb1a1
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c2x-qual-3.c
> > @@ -0,0 +1,30 @@
> > +/* Tests related to qualifiers and pointers to arrays in C2X, PR98397 */
> > +/* { dg-do compile } */
> > +/* { dg-options "-std=c2x -Wc11-c2x-compat -pedantic-errors" } */
> > +
> > +/* test that qualifiers are preserved in tertiary operator for pointers to 
> > arrays in C2X */
> > +
> > +void f(void)
> > +{
> > +   const int (*u)[1];
> > +   void *v;
> > +   _Static_assert(_Generic(1 ? u : v, const void*: 1, void*: 0), "lost 
> > qualifier");        /* { dg-
> > warning "pointer to array loses qualifier in conditional" } */
> > +   _Static_assert(_Generic(1 ? v : u, const void*: 1, void*: 0), "lost 
> > qualifier");        /* { dg-
> > warning "pointer to array loses qualifier in conditional" } */
> > +}
> > +
> > +/* test that assignment of unqualified to qualified pointers works as 
> > expected */
> > +
> > +void g(void)
> > +{
> > +   int (*x)[3];
> > +   const int (*p)[3] = x; /* { dg-warning "arrays with different 
> > qualifiers"  } */
> > +}
> > +
> > +/* test that assignment of qualified void pointers works as expected */
> > +
> > +void h(void)
> > +{
> > +   const void* x;
> > +   const int (*p)[3] = x; /* { dg-warning "array with qualifier on the 
> > element is not qualified
> > before C2X" } */
> > +}
> > +
> > diff --git a/gcc/testsuite/gcc.dg/c2x-qual-4.c 
> > b/gcc/testsuite/gcc.dg/c2x-qual-4.c
> > new file mode 100644
> > index 00000000000..93b4723dcd6
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c2x-qual-4.c
> > @@ -0,0 +1,105 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-std=c2x" } */
> > +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 "assignment discards 'const' 
> > qualifier from pointer
> > target type" } */
> > +   v2p = (1 ? p : z2); /* { dg-warning "assignment discards 'const' 
> > qualifier from pointer
> > target type" } */
> > +   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/c2x-qual-5.c 
> > b/gcc/testsuite/gcc.dg/c2x-qual-5.c
> > new file mode 100644
> > index 00000000000..0801fa0eed5
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c2x-qual-5.c
> > @@ -0,0 +1,101 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-std=c2x -pedantic-errors" } */
> > +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 "return 
> > discards" } */
> > +const int (*x3(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(z0); /* { dg-error "passing argument 1 of 'tvoid' discards 
> > 'const' qualifier from
> > pointer target type" } */
> > +   tvoid(z1); /* { dg-error "passing argument 1 of 'tvoid' discards 
> > 'const' qualifier from
> > pointer target type" } */
> > +   tvoid(z2); /* { dg-error "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-error "assignment discards 'const' qualifier from 
> > pointer target type" } */
> > +   p = z2; /* { dg-error "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);
> > +   transpose2(p, pc);
> > +   // passing as arguments
> > +   transpose0(y0, x0);
> > +   transpose1(y1, o1); /* { dg-error "passing argument 2 of 'transpose1' 
> > from incompatible
> > pointer type" } */
> > +   transpose1(y1, x1);
> > +   transpose2(y2, o2); /* { dg-error "passing argument 2 of 'transpose2' 
> > from incompatible
> > pointer type" } */
> > +   transpose2(y2, x2);
> > +   // initialization
> > +   const double (*x0p) = x0;
> > +   const double (*x1p)[2] = x1;
> > +   const double (*x2p)[2][2] = x2;
> > +   double (*v0p) = z0; /* { dg-error "initialization discards 'const' 
> > qualifier from pointer
> > target type" } */
> > +   double (*v1p)[2] = z1; /* { dg-error "initialization discards" } */
> > +   double (*v2p)[2][2] = z2; /* { dg-error "initialization discards" } */
> > +   // assignment
> > +   x0p = x0;
> > +   x1p = x1;
> > +   x2p = x2;
> > +   // 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;
> > +   // conditional expressions
> > +   (void)(1 ? x0 : z0);
> > +   (void)(1 ? x1 : z1);
> > +   (void)(1 ? x2 : z2);
> > +   (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 "assignment discards" } */
> > +   v2p = (1 ? z2 : v2p); /* { dg-error "assignment discards" } */
> > +   v0p = (1 ? x0 : x0p); /* { dg-error "assignment discards 'const' 
> > qualifier from pointer
> > target type" } */
> > +   v1p = (1 ? x1 : x1p); /* { dg-error "assignment discards" } */
> > +   v2p = (1 ? x2 : x2p); /* { dg-error "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" } */
> > +   (1 ? x2 : z2)[0][0][0] = 1; /* { dg-error "assignment of read-only 
> > location" } */
> > +   v0p = (1 ? p : z0); /* { dg-error "assignment discards 'const' 
> > qualifier from pointer target
> > type" } */
> > +   v1p = (1 ? p : z1); /* { dg-error "assignment discards 'const' 
> > qualifier from pointer target
> > type" } */
> > +   v2p = (1 ? p : z2); /* { dg-error "assignment discards 'const' 
> > qualifier from pointer target
> > type" } */
> > +   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" } */
> > +}
> > +
> > diff --git a/gcc/testsuite/gcc.dg/c2x-qual-6.c 
> > b/gcc/testsuite/gcc.dg/c2x-qual-6.c
> > new file mode 100644
> > index 00000000000..9c91e206e30
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/c2x-qual-6.c
> > @@ -0,0 +1,114 @@
> > +/* { dg-do compile } */
> > +/* { dg-options "-std=c2x -Wc11-c2x-compat -pedantic-errors" } */
> > +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-warning "before C2X" 
> > } */
> > +                                           /* { dg-error "return discards" 
> > "" { target *-*-* }
> > .-1 } */
> > +const int (*x3(int x[3][3]))[3] { return x; }      /* { dg-warning "before 
> > C2X" } */
> > +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-error "passing argument 1 of 'tvoid' discards 
> > 'const' qualifier from
> > pointer target type" } */
> > +   tvoid(z2); /* { dg-error "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-error "assignment discards 'const' qualifier from 
> > pointer target type" } */
> > +   p = z2; /* { dg-error "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-warning "before C2X" } */
> > +   transpose2(p, pc); /* { dg-warning "before C2X" } */
> > +   // passing as arguments
> > +   transpose0(y0, x0);
> > +   transpose1(y1, o1); /* { dg-error "passing argument 2 of 'transpose1' 
> > from incompatible
> > pointer type" } */
> > +   transpose1(y1, x1); /* { dg-warning "before C2X" } */
> > +   transpose2(y2, o2); /* { dg-error "passing argument 2 of 'transpose2' 
> > from incompatible
> > pointer type" } */
> > +   transpose2(y2, x2); /* { dg-warning "before C2X" } */
> > +   // initialization
> > +   const double (*x0p) = x0;
> > +   const double (*x1p)[2] = x1; /* { dg-warning "before C2X" } */
> > +   const double (*x2p)[2][2] = x2; /* { dg-warning "before C2X" } */
> > +   double (*v0p) = z0; /* { dg-error "initialization discards 'const' 
> > qualifier from pointer
> > target type" } */
> > +   double (*v1p)[2] = z1; /* { dg-warning "before C2X" } */
> > +                           /* { dg-error "initialization discards" "" { 
> > target *-*-* } .-1 } */
> > +   double (*v2p)[2][2] = z2; /* { dg-warning "before C2X" } */
> > +                           /* { dg-error "initialization discards" "" { 
> > target *-*-* } .-1 } */
> > +                           
> > +   // assignment
> > +   x0p = x0;
> > +   x1p = x1; /* { dg-warning "before C2X" } */
> > +   x2p = x2; /* { dg-warning "before C2X" } */
> > +
> > +   // subtraction
> > +   &(x0[1]) - &(z0[0]);
> > +   &(x1[1]) - &(z1[0]); /* { dg-warning "before C2X" } */
> > +   &(x2[1]) - &(z2[0]); /* { dg-warning "before C2X" } */
> > +   // comparison
> > +   x0 == z0;
> > +   x1 == z1; /* { dg-warning "before C2X" } */
> > +   x2 == z2; /* { dg-warning "before C2X" } */
> > +   x0 < z0;
> > +   x1 < z1; /* { dg-warning "before C2X" } */
> > +   x2 < z2; /* { dg-warning "before C2X" } */
> > +   x0 > z0;
> > +   x1 > z1; /* { dg-warning "before C2X" } */
> > +   x2 > z2; /* { dg-warning "before C2X" } */
> > +   // conditional expressions
> > +   (void)(1 ? x0 : z0);
> > +   (void)(1 ? x1 : z1); /* { dg-warning "before C2X" } */
> > +   (void)(1 ? x2 : z2); /* { dg-warning "before C2X" } */
> > +   (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-warning "before C2X" } */
> > +                           /* { dg-error "assignment discards" "" { target 
> > *-*-* } .-1 } */
> > +   v2p = (1 ? z2 : v2p); /* { dg-warning "before C2X" } */
> > +                           /* { dg-error "assignment discards" "" { target 
> > *-*-* } .-1 } */
> > +   v0p = (1 ? x0 : x0p); /* { dg-error "assignment discards 'const' 
> > qualifier from pointer
> > target type" } */
> > +   v1p = (1 ? x1 : x1p); /* { dg-error "assignment discards" } */
> > +                           /* { dg-warning "before C2X" "" { target *-*-* 
> > } .-1 } */
> > +   v2p = (1 ? x2 : x2p); /* { dg-error "assignment discards" } */
> > +                           /* { dg-warning "before C2X" "" { target *-*-* 
> > } .-1 } */
> > +   (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" } */
> > +                           /* { dg-warning "before C2X" "" { target *-*-* 
> > } .-1 } */
> > +   (1 ? x2 : z2)[0][0][0] = 1; /* { dg-error "assignment of read-only 
> > location" } */
> > +                           /* { dg-warning "before C2X" "" { target *-*-* 
> > } .-1 } */
> > +   v0p = (1 ? p : z0); /* { dg-error "assignment discards 'const' 
> > qualifier from pointer target
> > type" } */
> > +   v1p = (1 ? p : z1); /* { dg-error "assignment discards 'const' 
> > qualifier from pointer target
> > type" } */
> > +                           /* { dg-warning "before C2X" "" { target *-*-* 
> > } .-1 } */
> > +   v2p = (1 ? p : z2); /* { dg-error "assignment discards 'const' 
> > qualifier from pointer target
> > type" } */
> > +                           /* { dg-warning "before C2X" "" { target *-*-* 
> > } .-1 } */
> > +   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" } */
> > +}
> > +
> > diff --git a/gcc/testsuite/gcc.dg/pointer-array-quals-1.c 
> > b/gcc/testsuite/gcc.dg/pointer-array-
> > quals-1.c
> > index 921a37e9e0d..498ab223162 100644
> > --- a/gcc/testsuite/gcc.dg/pointer-array-quals-1.c
> > +++ b/gcc/testsuite/gcc.dg/pointer-array-quals-1.c
> > @@ -1,6 +1,6 @@
> >  /* { dg-do compile } */
> >  /* Origin: Martin Uecker <uec...@eecs.berkeley.edu> */
> > -/* { dg-options "-Wdiscarded-array-qualifiers" } */
> > +/* { dg-options "" } */
> >  void tvoid(void* x);
> >  void transpose0(double* out, const double* in) { }
> >  void transpose1(double out[2][2], const double in[2][2]) { }
> > diff --git a/gcc/testsuite/gcc.dg/pointer-array-quals-2.c 
> > b/gcc/testsuite/gcc.dg/pointer-array-
> > quals-2.c
> > index 30689c7312d..4c95d8a3a78 100644
> > --- a/gcc/testsuite/gcc.dg/pointer-array-quals-2.c
> > +++ b/gcc/testsuite/gcc.dg/pointer-array-quals-2.c
> > @@ -1,5 +1,5 @@
> >  /* { dg-do compile } */
> > -/* { dg-options "-Wdiscarded-array-qualifiers -pedantic-errors" } */
> > +/* { dg-options "-pedantic-errors" } */
> >  /* Origin: Martin Uecker <uec...@eecs.berkeley.edu> */
> >  void tvoid(void* x);
> >  void transpose0(double* out, const double* in) { }

Reply via email to