c++: Reject some further reinterpret casts in constexpr [PR82304, PR95307]

Message ID 20200529102532.GJ8462@tucnak
State New
Headers show
Series
  • c++: Reject some further reinterpret casts in constexpr [PR82304, PR95307]
Related show

Commit Message

Kewen.Lin via Gcc-patches May 29, 2020, 10:25 a.m.
Hi!

cxx_eval_outermost_constant_expr had a check for reinterpret_casts from
pointers (well, it checked from ADDR_EXPRs) to integral type, but that
only caught such cases at the toplevel of expressions.
As the comment said, it should be done even inside of the expressions,
but at the point of the writing e.g. pointer differences used to be a
problem.  We now have POINTER_DIFF_EXPR, so this is no longer an issue.

Had to do it just for CONVERT_EXPR, because the FE emits NOP_EXPR casts
from pointers to integrals in various spots, e.g. for the PMR & 1 tests,
though on NOP_EXPR we have the REINTERPRET_CAST_P bit that we do check,
while on CONVERT_EXPR we don't.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
PR92411 is not fixed by this change though.

2020-05-29  Jakub Jelinek  <jakub@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.


	Jakub

Comments

Kewen.Lin via Gcc-patches May 29, 2020, 5:26 p.m. | #1
On 5/29/20 6:25 AM, Jakub Jelinek wrote:
> Hi!

> 

> cxx_eval_outermost_constant_expr had a check for reinterpret_casts from

> pointers (well, it checked from ADDR_EXPRs) to integral type, but that

> only caught such cases at the toplevel of expressions.

> As the comment said, it should be done even inside of the expressions,

> but at the point of the writing e.g. pointer differences used to be a

> problem.  We now have POINTER_DIFF_EXPR, so this is no longer an issue.

> 

> Had to do it just for CONVERT_EXPR, because the FE emits NOP_EXPR casts

> from pointers to integrals in various spots, e.g. for the PMR & 1 tests,

> though on NOP_EXPR we have the REINTERPRET_CAST_P bit that we do check,

> while on CONVERT_EXPR we don't.

> 

> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

> PR92411 is not fixed by this change though.

> 

> 2020-05-29  Jakub Jelinek  <jakub@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-28 23:12:19.715303826 +0200

> +++ gcc/cp/constexpr.c	2020-05-29 12:02:06.161656532 +0200

> @@ -6194,6 +6194,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 ("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);

>   

> @@ -6795,19 +6807,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-01-12 11:54:37.249400796 +0100

> +++ gcc/testsuite/g++.dg/template/pr79650.C	2020-05-29 12:02:06.180656252 +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-01-12 11:54:37.115402818 +0100

> +++ gcc/testsuite/g++.dg/cpp1y/constexpr-shift1.C	2020-05-29 12:02:06.180656252 +0200

> @@ -3,7 +3,8 @@

>   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;

>   }

>   constexpr __PTRDIFF_TYPE__ r = bar (2); // { dg-message "in .constexpr. expansion of" }

> +					// { dg-error "conversion from pointer" "" { target *-*-* } .-1 }

>   constexpr __PTRDIFF_TYPE__ s = bar (0); // { dg-error "conversion from pointer" }


This is a diagnostic quality regression, moving the error message away 
from the line where the actual problem is.

Maybe use error_at (loc, ...)?

Jason
Kewen.Lin via Gcc-patches June 1, 2020, 10:50 p.m. | #2
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  <jakub@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
Kewen.Lin via Gcc-patches June 3, 2020, 6:48 p.m. | #3
On 6/1/20 6:50 PM, Jakub Jelinek wrote:
> 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?


OK.

> 2020-06-02  Jakub Jelinek  <jakub@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

>

Patch

--- gcc/cp/constexpr.c.jj	2020-05-28 23:12:19.715303826 +0200
+++ gcc/cp/constexpr.c	2020-05-29 12:02:06.161656532 +0200
@@ -6194,6 +6194,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 ("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);
 
@@ -6795,19 +6807,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-01-12 11:54:37.249400796 +0100
+++ gcc/testsuite/g++.dg/template/pr79650.C	2020-05-29 12:02:06.180656252 +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-01-12 11:54:37.115402818 +0100
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-shift1.C	2020-05-29 12:02:06.180656252 +0200
@@ -3,7 +3,8 @@ 
 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;
 }
 constexpr __PTRDIFF_TYPE__ r = bar (2); // { dg-message "in .constexpr. expansion of" }
+					// { dg-error "conversion from pointer" "" { target *-*-* } .-1 }
 constexpr __PTRDIFF_TYPE__ s = bar (0); // { dg-error "conversion from pointer" }
--- gcc/testsuite/g++.dg/cpp1y/constexpr-82304.C.jj	2020-05-29 12:04:58.077131497 +0200
+++ gcc/testsuite/g++.dg/cpp1y/constexpr-82304.C	2020-05-29 12:10:08.171576940 +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);
+  ++l;
+  return reinterpret_cast<const char *>(l);
+}
+
+constexpr auto s = foo ("Hello");	// { dg-error "conversion from pointer" }
--- gcc/testsuite/g++.dg/cpp0x/constexpr-95307.C.jj	2020-05-29 12:09:02.044548190 +0200
+++ gcc/testsuite/g++.dg/cpp0x/constexpr-95307.C	2020-05-29 12:08:28.890035152 +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" }