From 715dd933bd56edc7498495dc7dfe66768347f7b5 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Wed, 18 Apr 2018 08:57:45 +0200 Subject: [PATCH] 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) : ... 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 --- gcc/cp/ChangeLog | 8 +++++++ gcc/cp/cp-gimplify.c | 23 +++++++++++++++++++ gcc/cp/typeck.c | 13 ----------- gcc/testsuite/ChangeLog | 12 ++++++++++ gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C | 22 ++++++++++++++++++ .../g++.dg/cpp0x/constexpr-nullptr-1.C | 2 +- .../g++.dg/cpp0x/constexpr-nullptr-2.C | 9 ++++---- gcc/testsuite/g++.dg/init/struct2.C | 2 +- gcc/testsuite/g++.dg/parse/array-size2.C | 2 +- 9 files changed, 72 insertions(+), 21 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ff6f4121723..c80b281d313 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2018-04-18 Jakub Jelinek + + PR c++/84463 + * typeck.c (cp_build_addr_expr_1): Move handling of offsetof-like + tricks from here to ... + * cp-gimplify.c (cp_fold) : ... here. Only use it + if INDIRECT_REF's operand is INTEGER_CST cast to pointer type. + 2018-04-18 Alexandre Oliva PR c++/80290 diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index fb0aea3e0c7..74490654631 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -2215,6 +2215,28 @@ cp_fold (tree x) goto unary; 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 IMAGPART_EXPR: rval_ops = false; @@ -2232,6 +2254,7 @@ cp_fold (tree x) loc = EXPR_LOCATION (x); op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops); + finish_unary: if (op0 != TREE_OPERAND (x, 0)) { if (op0 == error_mark_node) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index b449b1f7f53..f5081c1661c 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -5893,19 +5893,6 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) 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) by reduction to simpler cases. */ val = unary_complex_lvalue (ADDR_EXPR, arg); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6dba141769f..658b52de527 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2018-04-18 Jakub Jelinek + + 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 * gcc.target/powerpc/undef-bool-2.c: Add -mvsx. diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C new file mode 100644 index 00000000000..0743059be53 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-84463.C @@ -0,0 +1,22 @@ +// 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); diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C index e2f7917d36e..ed53fcd69aa 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-1.C @@ -6,7 +6,7 @@ // c++/67376 on gcc-patches for additional background. // { 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. #define RA(e) ((e) ? (void)0 : __builtin_abort ()) diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C index aeea87c2ae7..3b3f01adea3 100644 --- a/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nullptr-2.C @@ -192,12 +192,11 @@ constexpr bool b11 = ps >= (S*)0; constexpr S* ps1 = ps; constexpr S* ps2 = ps1; -// The following aren't diagnosed due to a bug. -// constexpr int* pi0 = &((S*)0)->i; -// constexpr int* pi1 = &((S*)nullptr)->i; +constexpr int* pi0 = &((S*)0)->i; // { dg-error "null pointer|not a constant" } +constexpr int* pi1 = &((S*)nullptr)->i; // { dg-error "null pointer|not a constant" } -constexpr int* pj0 = &((S*)0)->j; // { dg-error "not a constant expression" } -constexpr int* pj1 = &((S*)nullptr)->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 "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" } diff --git a/gcc/testsuite/g++.dg/init/struct2.C b/gcc/testsuite/g++.dg/init/struct2.C index 85aacc6fa09..4396febdc46 100644 --- a/gcc/testsuite/g++.dg/init/struct2.C +++ b/gcc/testsuite/g++.dg/init/struct2.C @@ -15,7 +15,7 @@ void saveOrLoad() { }; SaveLoadEntry trackEntries = { - ((long) (__SIZE_TYPE__) (&((Track *) 42)->soundName[0])) - 42, + ((int) (__SIZE_TYPE__) (&((Track *) 42)->soundName[0])) - 42, 0, 1 }; saveLoadEntries(&trackEntries); diff --git a/gcc/testsuite/g++.dg/parse/array-size2.C b/gcc/testsuite/g++.dg/parse/array-size2.C index 3c833472d69..d0bc47fe746 100644 --- a/gcc/testsuite/g++.dg/parse/array-size2.C +++ b/gcc/testsuite/g++.dg/parse/array-size2.C @@ -15,6 +15,6 @@ void foo (void) { 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); } -- 2.30.2