Correct treatment of qualifiers for pointers to arrays for C2X [PR98397]
2021-08-22 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/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.
This commit is contained in:
parent
9b08f7764c
commit
972eab51f5
186
gcc/c/c-typeck.c
186
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)))
|
||||
else if ((VOID_TYPE_P (TREE_TYPE (type1))
|
||||
&& !TYPE_ATOMIC (TREE_TYPE (type1)))
|
||||
|| (VOID_TYPE_P (TREE_TYPE (type2))
|
||||
&& !TYPE_ATOMIC (TREE_TYPE (type2))))
|
||||
{
|
||||
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)
|
||||
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 "
|
||||
"%<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))
|
||||
@ -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)
|
||||
|
11
gcc/testsuite/gcc.dg/c11-qual-1.c
Normal file
11
gcc/testsuite/gcc.dg/c11-qual-1.c
Normal file
@ -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");
|
||||
}
|
30
gcc/testsuite/gcc.dg/c2x-qual-1.c
Normal file
30
gcc/testsuite/gcc.dg/c2x-qual-1.c
Normal file
@ -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;
|
||||
}
|
||||
|
30
gcc/testsuite/gcc.dg/c2x-qual-2.c
Normal file
30
gcc/testsuite/gcc.dg/c2x-qual-2.c
Normal file
@ -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" } */
|
||||
}
|
||||
|
30
gcc/testsuite/gcc.dg/c2x-qual-3.c
Normal file
30
gcc/testsuite/gcc.dg/c2x-qual-3.c
Normal file
@ -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" } */
|
||||
}
|
||||
|
105
gcc/testsuite/gcc.dg/c2x-qual-4.c
Normal file
105
gcc/testsuite/gcc.dg/c2x-qual-4.c
Normal file
@ -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" } */
|
||||
}
|
||||
|
101
gcc/testsuite/gcc.dg/c2x-qual-5.c
Normal file
101
gcc/testsuite/gcc.dg/c2x-qual-5.c
Normal file
@ -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" } */
|
||||
}
|
||||
|
114
gcc/testsuite/gcc.dg/c2x-qual-6.c
Normal file
114
gcc/testsuite/gcc.dg/c2x-qual-6.c
Normal file
@ -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" } */
|
||||
}
|
||||
|
16
gcc/testsuite/gcc.dg/c2x-qual-7.c
Normal file
16
gcc/testsuite/gcc.dg/c2x-qual-7.c
Normal file
@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
@ -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]) { }
|
||||
|
@ -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) { }
|
||||
|
Loading…
Reference in New Issue
Block a user