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) { }