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

Jason Merrill jason@redhat.com
Fri May 29 17:26:32 GMT 2020


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



More information about the Gcc-patches mailing list