[C PATCH] qualifiers of pointers to arrays in C2X [PR 98397]
Uecker, Martin
Martin.Uecker@med.uni-goettingen.de
Fri Jun 11 19:25:37 GMT 2021
(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 <muecker@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 <uecker@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 <uecker@eecs.berkeley.edu> */
> void tvoid(void* x);
> void transpose0(double* out, const double* in) { }
More information about the Gcc-patches
mailing list