Am Freitag, den 01.01.2021, 00:01 +0000 schrieb Joseph Myers: > > > I'd expect c2x-* tests to use -std=c2x not -std=gnu2x. Tests needing > -std=gnu2x can be gnu2x-* tests, but you should be able to test the types > using _Generic without needing any gnu2x features. c2x-* tests should > also use -pedantic or -pedantic-errors unless they are specifically > testing something that doesn't work with those options. > > There should also be tests for cases where code is valid before C2x but > invalid in C2x (assignment storing a pointer-to-qualified-array in void *, > for example). > > All the tests should have both c2x-* and c11-* variants so the testsuite > verifies that the code is properly handled in C11 mode (warnings with > -pedantic, errors with -pedantic-errors, in the cases that are invalid for > C11 but valid for C2x). There should also be -Wc11-c2x-compat tests with > -std=c2x where appropriate.
Here is a revised version which adds some missing warnings and also fixed some error regarding which warnings got emitted. I added tests for C2X that test with std=c2x and -pedantic-errors with and without -Wc11-c2x-compat. In the conditional operator I directly test for the type using _Generic and _Static_assert. This test also exists for c11 testing for the old behavior. I did not add tests for c11 for warnings because we already had warnings before and the tests for these exist. (I removed -Wdiscarded-array-qualifiers from the old tests as this flag is not needed.) Or should there be additional warnings with -Wc11-c2x-compat for c11? But warning twice about the same issue does not seem ideal... More comments? Best, Martin diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 67c0080a5ef..243790e7abf 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -1318,8 +1318,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, "pointers to arrays with different qualifiers " + "are incompatible in ISO C before C2X"); if (val == 2) pedwarn (location, OPT_Wpedantic, "types are not quite compatible"); @@ -5331,39 +5331,39 @@ 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 does not lose qualifier in C2X " + "in conditional expression"); + } + 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))); + 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)) @@ -7316,15 +7316,16 @@ 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); - - /* 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)) + if (warn_quals || (warn_quals_ped && pedantic && !flag_isoc2x)) { PEDWARN_FOR_QUALIFIERS (location, expr_loc, OPT_Wdiscarded_qualifiers, @@ -7338,6 +7339,10 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, "pointer target type"), TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl)); } + else if (warn_quals_ped && pedantic && flag_isoc2x && (warn_c11_c2x_compat > 0)) + pedwarn (expr_loc, OPT_Wc11_c2x_compat, + "array with qualifier on the element is not qualified before C2X"); + /* 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..d53dc214f91 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-qual-1.c @@ -0,0 +1,11 @@ +/* Test related to qualifiers and pointers to arrays in C2X, PR98397 */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +void foo(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"); +} 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..3304410bb96 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-qual-2.c @@ -0,0 +1,12 @@ +/* Test related to qualifiers and pointers to arrays in C2X, PR98397 */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */ + +void foo(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 does not lose qualifier in C2X" } */ + _Static_assert(_Generic(1 ? v : u, const void*: 1, void*: 0), "lost qualifier"); /* { dg-warning "pointer to array does not lose qualifier in 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..58fe16fed94 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-qual-3.c @@ -0,0 +1,9 @@ +/* Test related to qualifiers and pointers to arrays in C2X, PR98397 */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +void f(void) +{ + int (*x)[3]; + const int (*p)[3] = x; +} 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..e04668eb752 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-qual-4.c @@ -0,0 +1,9 @@ +/* Test related to qualifiers and pointers to arrays in C2X, PR98397 */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */ + +void f(void) +{ + int (*x)[3]; + const int (*p)[3] = x; /* { dg-warning "pointers to arrays with different qualifiers are incompatible in ISO C before C2X" } */ +} 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..4647d0b0dfe --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-qual-5.c @@ -0,0 +1,9 @@ +/* Test related to qualifiers and pointers to arrays in C2X, PR98397 */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors" } */ + +void f(void) +{ + const void* x; + const int (*p)[3] = x; +} 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..dca50ac014f --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-qual-6.c @@ -0,0 +1,9 @@ +/* Test related to qualifiers and pointers to arrays in C2X, PR98397 */ +/* { dg-do compile } */ +/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */ + +void f(void) +{ + const void* x; + const int (*p)[3] = x; /* { dg-error "array with qualifier on the element is not qualified before C2X" } */ +} 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) { }