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

Reply via email to