From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1924) id E5DAC3858417; Sun, 22 Aug 2021 22:15:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E5DAC3858417 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Martin Uecker To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-3060] Correct treatment of qualifiers for pointers to arrays for C2X [PR98397] X-Act-Checkin: gcc X-Git-Author: Martin Uecker X-Git-Refname: refs/heads/master X-Git-Oldrev: 9b08f7764cecd16cba84944f2a8b67a7f73a7ce7 X-Git-Newrev: 972eab51f53d1db26864ec7d62d40c2ff83407ec Message-Id: <20210822221541.E5DAC3858417@sourceware.org> Date: Sun, 22 Aug 2021 22:15:41 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 22 Aug 2021 22:15:42 -0000 https://gcc.gnu.org/g:972eab51f53d1db26864ec7d62d40c2ff83407ec commit r12-3060-g972eab51f53d1db26864ec7d62d40c2ff83407ec Author: Martin Uecker Date: Sun Aug 22 23:47:58 2021 +0200 Correct treatment of qualifiers for pointers to arrays for C2X [PR98397] 2021-08-22 Martin Uecker 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/c2x-qual-7.c: New test. * gcc.dg/pointer-array-quals-1.c: Remove unnecessary flag. * gcc.dg/pointer-array-quals-2.c: Remove unnecessary flag. Diff: --- gcc/c/c-typeck.c | 188 +++++++++++++-------------- gcc/testsuite/gcc.dg/c11-qual-1.c | 11 ++ gcc/testsuite/gcc.dg/c2x-qual-1.c | 30 +++++ gcc/testsuite/gcc.dg/c2x-qual-2.c | 30 +++++ gcc/testsuite/gcc.dg/c2x-qual-3.c | 30 +++++ gcc/testsuite/gcc.dg/c2x-qual-4.c | 105 +++++++++++++++ gcc/testsuite/gcc.dg/c2x-qual-5.c | 101 ++++++++++++++ gcc/testsuite/gcc.dg/c2x-qual-6.c | 114 ++++++++++++++++ gcc/testsuite/gcc.dg/c2x-qual-7.c | 16 +++ gcc/testsuite/gcc.dg/pointer-array-quals-1.c | 2 +- gcc/testsuite/gcc.dg/pointer-array-quals-2.c | 2 +- 11 files changed, 532 insertions(+), 97 deletions(-) diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 0c07af61f24..d9f26d67bd3 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"); @@ -5406,39 +5406,41 @@ 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) + && !TYPE_ATOMIC (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 " "% 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 " - "% 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)) @@ -6797,27 +6799,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 (); \ @@ -6826,32 +6841,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); @@ -7370,17 +7364,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) @@ -7403,28 +7398,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/c2x-qual-7.c b/gcc/testsuite/gcc.dg/c2x-qual-7.c new file mode 100644 index 00000000000..5fe15e1d2cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-qual-7.c @@ -0,0 +1,16 @@ +/* Tests related to qualifiers and pointers to arrays in C2X, PR98397 */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +/* test that _Atomic qualifier is not preserved in tertiary operator for pointers to arrays in C2X */ + +void f(void) +{ + _Atomic void *u; + void *v; + _Static_assert(_Generic(1 ? u : v, _Atomic void*: 0, void*: 1), "_Atomic should be removed"); + _Static_assert(_Generic(1 ? v : u, _Atomic void*: 0, void*: 1), "_Atomic should be removed"); +} + + + 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 */ -/* { 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 */ void tvoid(void* x); void transpose0(double* out, const double* in) { }