Commit 715dd933 by Jakub Jelinek Committed by Jakub Jelinek

re PR c++/84463 (Supposedly-incompliant "error: '* key0' is not a constant expression")

	PR c++/84463
	* typeck.c (cp_build_addr_expr_1): Move handling of offsetof-like
	tricks from here to ...
	* cp-gimplify.c (cp_fold) <case ADDR_EXPR>: ... here.  Only use it
	if INDIRECT_REF's operand is INTEGER_CST cast to pointer type.

	* g++.dg/cpp0x/constexpr-nullptr-1.C: Add -O1 to dg-options.
	* g++.dg/cpp0x/constexpr-nullptr-2.C: Expect different diagnostics
	in two cases.  Uncomment two other tests and add expected dg-error for
	them.
	* g++.dg/init/struct2.C: Cast to int rather than long to avoid
	-Wnarrowing diagnostics on some targets for c++11.
	* g++.dg/parse/array-size2.C: Remove xfail.
	* g++.dg/cpp0x/constexpr-84463.C: New test.

From-SVN: r259458
parent a56e2f69
2018-04-18 Jakub Jelinek <jakub@redhat.com>
PR c++/84463
* typeck.c (cp_build_addr_expr_1): Move handling of offsetof-like
tricks from here to ...
* cp-gimplify.c (cp_fold) <case ADDR_EXPR>: ... here. Only use it
if INDIRECT_REF's operand is INTEGER_CST cast to pointer type.
2018-04-18 Alexandre Oliva <aoliva@redhat.com> 2018-04-18 Alexandre Oliva <aoliva@redhat.com>
PR c++/80290 PR c++/80290
......
...@@ -2215,6 +2215,28 @@ cp_fold (tree x) ...@@ -2215,6 +2215,28 @@ cp_fold (tree x)
goto unary; goto unary;
case ADDR_EXPR: case ADDR_EXPR:
loc = EXPR_LOCATION (x);
op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), false);
/* Cope with user tricks that amount to offsetof. */
if (op0 != error_mark_node
&& TREE_CODE (TREE_TYPE (op0)) != FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (op0)) != METHOD_TYPE)
{
tree val = get_base_address (op0);
if (val
&& INDIRECT_REF_P (val)
&& COMPLETE_TYPE_P (TREE_TYPE (val))
&& TREE_CONSTANT (TREE_OPERAND (val, 0)))
{
val = TREE_OPERAND (val, 0);
STRIP_NOPS (val);
if (TREE_CODE (val) == INTEGER_CST)
return fold_convert (TREE_TYPE (x), fold_offsetof_1 (op0));
}
}
goto finish_unary;
case REALPART_EXPR: case REALPART_EXPR:
case IMAGPART_EXPR: case IMAGPART_EXPR:
rval_ops = false; rval_ops = false;
...@@ -2232,6 +2254,7 @@ cp_fold (tree x) ...@@ -2232,6 +2254,7 @@ cp_fold (tree x)
loc = EXPR_LOCATION (x); loc = EXPR_LOCATION (x);
op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops); op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops);
finish_unary:
if (op0 != TREE_OPERAND (x, 0)) if (op0 != TREE_OPERAND (x, 0))
{ {
if (op0 == error_mark_node) if (op0 == error_mark_node)
......
...@@ -5893,19 +5893,6 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) ...@@ -5893,19 +5893,6 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain)
return arg; return arg;
} }
/* ??? Cope with user tricks that amount to offsetof. */
if (TREE_CODE (argtype) != FUNCTION_TYPE
&& TREE_CODE (argtype) != METHOD_TYPE
&& argtype != unknown_type_node
&& (val = get_base_address (arg))
&& COMPLETE_TYPE_P (TREE_TYPE (val))
&& INDIRECT_REF_P (val)
&& TREE_CONSTANT (TREE_OPERAND (val, 0)))
{
tree type = build_pointer_type (argtype);
return fold_convert (type, fold_offsetof_1 (arg));
}
/* Handle complex lvalues (when permitted) /* Handle complex lvalues (when permitted)
by reduction to simpler cases. */ by reduction to simpler cases. */
val = unary_complex_lvalue (ADDR_EXPR, arg); val = unary_complex_lvalue (ADDR_EXPR, arg);
......
2018-04-18 Jakub Jelinek <jakub@redhat.com>
PR c++/84463
* g++.dg/cpp0x/constexpr-nullptr-1.C: Add -O1 to dg-options.
* g++.dg/cpp0x/constexpr-nullptr-2.C: Expect different diagnostics
in two cases. Uncomment two other tests and add expected dg-error for
them.
* g++.dg/init/struct2.C: Cast to int rather than long to avoid
-Wnarrowing diagnostics on some targets for c++11.
* g++.dg/parse/array-size2.C: Remove xfail.
* g++.dg/cpp0x/constexpr-84463.C: New test.
2018-04-17 Bill Schmidt <wschmidt@linux.ibm.com> 2018-04-17 Bill Schmidt <wschmidt@linux.ibm.com>
* gcc.target/powerpc/undef-bool-2.c: Add -mvsx. * gcc.target/powerpc/undef-bool-2.c: Add -mvsx.
......
// PR c++/84463
// { dg-do compile { target c++11 } }
struct S { int r; const unsigned char s[5]; };
static constexpr S a[] = { { 0, "abcd" } };
struct T { const unsigned char s[5]; };
static constexpr T b[] = { { "abcd" } };
constexpr int
foo (const unsigned char *x)
{
return x[0];
}
constexpr static const S *j = &a[0];
constexpr static const int k = j->s[0];
constexpr static int l = foo (a[0].s);
constexpr static int m = foo (j->s);
constexpr static const T *n = &b[0];
constexpr static const int o = n->s[0];
constexpr static int p = foo (b[0].s);
constexpr static int q = foo (n->s);
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
// c++/67376 on gcc-patches for additional background. // c++/67376 on gcc-patches for additional background.
// { dg-do compile { target c++11 } } // { dg-do compile { target c++11 } }
// { dg-options "-fdelete-null-pointer-checks -fdump-tree-optimized" } // { dg-options "-O1 -fdelete-null-pointer-checks -fdump-tree-optimized" }
// Runtime assert. Used for potentially invalid expressions. // Runtime assert. Used for potentially invalid expressions.
#define RA(e) ((e) ? (void)0 : __builtin_abort ()) #define RA(e) ((e) ? (void)0 : __builtin_abort ())
......
...@@ -192,12 +192,11 @@ constexpr bool b11 = ps >= (S*)0; ...@@ -192,12 +192,11 @@ constexpr bool b11 = ps >= (S*)0;
constexpr S* ps1 = ps; constexpr S* ps1 = ps;
constexpr S* ps2 = ps1; constexpr S* ps2 = ps1;
// The following aren't diagnosed due to a bug. constexpr int* pi0 = &((S*)0)->i; // { dg-error "null pointer|not a constant" }
// constexpr int* pi0 = &((S*)0)->i; constexpr int* pi1 = &((S*)nullptr)->i; // { dg-error "null pointer|not a constant" }
// constexpr int* pi1 = &((S*)nullptr)->i;
constexpr int* pj0 = &((S*)0)->j; // { dg-error "not a constant expression" } constexpr int* pj0 = &((S*)0)->j; // { dg-error "null pointer|not a constant" }
constexpr int* pj1 = &((S*)nullptr)->j; // { dg-error "not a constant expression" } constexpr int* pj1 = &((S*)nullptr)->j; // { dg-error "null pointer|not a constant" }
constexpr int* psi = &ps->i; // { dg-error "null pointer|not a constant" } constexpr int* psi = &ps->i; // { dg-error "null pointer|not a constant" }
constexpr int* psj = &ps->j; // { dg-error "null pointer|not a constant" } constexpr int* psj = &ps->j; // { dg-error "null pointer|not a constant" }
......
...@@ -15,7 +15,7 @@ void saveOrLoad() { ...@@ -15,7 +15,7 @@ void saveOrLoad() {
}; };
SaveLoadEntry trackEntries = { SaveLoadEntry trackEntries = {
((long) (__SIZE_TYPE__) (&((Track *) 42)->soundName[0])) - 42, ((int) (__SIZE_TYPE__) (&((Track *) 42)->soundName[0])) - 42,
0, 1 0, 1
}; };
saveLoadEntries(&trackEntries); saveLoadEntries(&trackEntries);
......
...@@ -15,6 +15,6 @@ void ...@@ -15,6 +15,6 @@ void
foo (void) foo (void)
{ {
char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant" } char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant" }
char h[(__SIZE_TYPE__) &((struct S *) 8)->b]; // { dg-error "constant" "" { xfail *-*-* } } char h[(__SIZE_TYPE__) &((struct S *) 8)->b]; // { dg-error "constant" }
bar (g, h); bar (g, h);
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment