On Fri, May 29, 2020 at 01:26:32PM -0400, Jason Merrill via Gcc-patches wrote: > This is a diagnostic quality regression, moving the error message away from > the line where the actual problem is. > > Maybe use error_at (loc, ...)?
That works fine, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2020-06-02 Jakub Jelinek <ja...@redhat.com> PR c++/82304 PR c++/95307 * constexpr.c (cxx_eval_constant_expression): Diagnose CONVERT_EXPR conversions from pointer types to arithmetic types here... (cxx_eval_outermost_constant_expr): ... instead of here. * g++.dg/template/pr79650.C: Expect different diagnostics and expect it on all lines that do pointer to integer casts. * g++.dg/cpp1y/constexpr-shift1.C: Expect different diagnostics. * g++.dg/cpp1y/constexpr-82304.C: New test. * g++.dg/cpp0x/constexpr-95307.C: New test. --- gcc/cp/constexpr.c.jj 2020-05-29 23:49:25.479087388 +0200 +++ gcc/cp/constexpr.c 2020-06-01 12:53:30.348337388 +0200 @@ -6210,6 +6210,18 @@ cxx_eval_constant_expression (const cons if (VOID_TYPE_P (type)) return void_node; + if (TREE_CODE (t) == CONVERT_EXPR + && ARITHMETIC_TYPE_P (type) + && INDIRECT_TYPE_P (TREE_TYPE (op))) + { + if (!ctx->quiet) + error_at (loc, + "conversion from pointer type %qT to arithmetic type " + "%qT in a constant expression", TREE_TYPE (op), type); + *non_constant_p = true; + return t; + } + if (TREE_CODE (op) == PTRMEM_CST && !TYPE_PTRMEM_P (type)) op = cplus_expand_constant (op); @@ -6811,19 +6823,6 @@ cxx_eval_outermost_constant_expr (tree t non_constant_p = true; } - /* Technically we should check this for all subexpressions, but that - runs into problems with our internal representation of pointer - subtraction and the 5.19 rules are still in flux. */ - if (CONVERT_EXPR_CODE_P (TREE_CODE (r)) - && ARITHMETIC_TYPE_P (TREE_TYPE (r)) - && TREE_CODE (TREE_OPERAND (r, 0)) == ADDR_EXPR) - { - if (!allow_non_constant) - error ("conversion from pointer type %qT " - "to arithmetic type %qT in a constant expression", - TREE_TYPE (TREE_OPERAND (r, 0)), TREE_TYPE (r)); - non_constant_p = true; - } if (!non_constant_p && overflow_p) non_constant_p = true; --- gcc/testsuite/g++.dg/template/pr79650.C.jj 2020-05-29 23:49:19.040183088 +0200 +++ gcc/testsuite/g++.dg/template/pr79650.C 2020-06-01 12:53:30.348337388 +0200 @@ -11,10 +11,10 @@ foo () static int a, b; lab1: lab2: - A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab2> c; // { dg-error "not a constant integer" } - A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab1> d; - A<(intptr_t)&a - (intptr_t)&b> e; // { dg-error "is not a constant expression" } - A<(intptr_t)&a - (intptr_t)&a> f; - A<(intptr_t)sizeof(a) + (intptr_t)&a> g; // { dg-error "not a constant integer" } + A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab2> c; // { dg-error "conversion from pointer type" } + A<(intptr_t)&&lab1 - (__INTPTR_TYPE__)&&lab1> d; // { dg-error "conversion from pointer type" } + A<(intptr_t)&a - (intptr_t)&b> e; // { dg-error "conversion from pointer type" } + A<(intptr_t)&a - (intptr_t)&a> f; // { dg-error "conversion from pointer type" } + A<(intptr_t)sizeof(a) + (intptr_t)&a> g; // { dg-error "conversion from pointer type" } A<(intptr_t)&a> h; // { dg-error "conversion from pointer type" } } --- gcc/testsuite/g++.dg/cpp1y/constexpr-shift1.C.jj 2020-05-29 23:49:19.036183148 +0200 +++ gcc/testsuite/g++.dg/cpp1y/constexpr-shift1.C 2020-06-01 13:55:22.607594689 +0200 @@ -3,7 +3,7 @@ constexpr int p = 1; constexpr __PTRDIFF_TYPE__ bar (int a) { - return ((__PTRDIFF_TYPE__) &p) << a; // { dg-error "is not a constant expression" } + return ((__PTRDIFF_TYPE__) &p) << a; // { dg-error "conversion from pointer" } } constexpr __PTRDIFF_TYPE__ r = bar (2); // { dg-message "in .constexpr. expansion of" } -constexpr __PTRDIFF_TYPE__ s = bar (0); // { dg-error "conversion from pointer" } +constexpr __PTRDIFF_TYPE__ s = bar (0); --- gcc/testsuite/g++.dg/cpp1y/constexpr-82304.C.jj 2020-06-01 12:53:30.349337373 +0200 +++ gcc/testsuite/g++.dg/cpp1y/constexpr-82304.C 2020-06-01 13:03:40.668227604 +0200 @@ -0,0 +1,14 @@ +// PR c++/82304 +// { dg-do compile { target c++14 } } + +typedef __UINTPTR_TYPE__ uintptr_t; + +constexpr const char * +foo (const char *p) +{ + auto l = reinterpret_cast<uintptr_t>(p); // { dg-error "conversion from pointer" } + ++l; + return reinterpret_cast<const char *>(l); +} + +constexpr auto s = foo ("Hello"); --- gcc/testsuite/g++.dg/cpp0x/constexpr-95307.C.jj 2020-06-01 12:53:30.349337373 +0200 +++ gcc/testsuite/g++.dg/cpp0x/constexpr-95307.C 2020-06-01 12:53:30.349337373 +0200 @@ -0,0 +1,5 @@ +// PR c++/95307 +// { dg-do compile { target c++11 } } + +int v; +constexpr auto p{reinterpret_cast<__UINTPTR_TYPE__>(&v) - 1u}; // { dg-error "conversion from pointer type" } Jakub