[PATCH] c++/67376 Comparison with pointer to past-the-end, of array fails inside constant expression

Jeff Law law@redhat.com
Fri Mar 18 19:13:00 GMT 2016


On 03/17/2016 03:16 PM, Martin Sebor wrote:

>
> gcc-67376.patch
>
>
> PR c++/67376 - [5/6 regression] Comparison with pointer to past-the-end
> 	of array fails inside constant expression
> PR c++/70170 - [6 regression] bogus not a constant expression error comparing
> 	pointer to array to null
> PR c++/70172 - incorrect reinterpret_cast from integer to pointer error
> 	on invalid constexpr initialization
> PR c++/60760 - arithmetic on null pointers should not be allowed in constant
> 	expressions
> PR c++/70228 - insufficient detail in diagnostics for a constexpr out of bounds
> 	array subscript
>
> gcc/testsuite/ChangeLog:
> 2016-03-17  Martin Sebor<msebor@redhat.com>
>
> 	PR c++/67376
> 	PR c++/70170
> 	PR c++/70172
> 	PR c++/60760
> 	PR c++/70228
> 	* g++.dg/cpp0x/constexpr-array-ptr10.C: New test.
> 	* g++.dg/cpp0x/constexpr-array-ptr9.C: New test.
> 	* g++.dg/cpp0x/constexpr-array5.C: Adjust text of expected diagnostic.
> 	* g++.dg/cpp0x/constexpr-nullptr.C: Add test cases.
> 	* g++.dg/cpp0x/constexpr-string.C: Same.
> 	* g++.dg/cpp0x/constexpr-wstring2.C: Same.
> 	* g++.dg/cpp0x/pr65398.C: Same.
> 	* g++.dg/ext/constexpr-vla1.C: Same.
> 	* g++.dg/ext/constexpr-vla2.C: Same.
> 	* g++.dg/ext/constexpr-vla3.C: Same.
> 	* g++.dg/ubsan/pr63956.C: Same.
>
> gcc/cp/ChangeLog:
> 2016-03-17  Martin Sebor<msebor@redhat.com>
>
> 	PR c++/67376
> 	PR c++/70170
> 	PR c++/70172
> 	PR c++/60760
> 	PR c++/70228
> 	* constexpr.c (cxx_eval_binary_expression): Add argument.
> 	(cxx_eval_component_reference): Same.
> 	(cxx_eval_constant_expression): Same.
> 	(cxx_eval_indirect_ref): Same.
> 	(cxx_eval_outermost_constant_expr): Same.
> 	(diag_array_subscript): New function.
> 	(cxx_eval_call_expression): Adjust.
> 	(cxx_eval_conditional_expression): Same.
> 	(cxx_eval_array_reference): Detect null pointers.
> 	(cxx_eval_statement_list): Adjust.
>
> gcc/ChangeLog:
> 2016-03-17  Martin Sebor<msebor@redhat.com>
>
> 	PR c++/67376
> 	* fold-const.c (maybe_nonzero_address): New function.
> 	(fold_comparison): Call it.  Fold equality and relational
> 	expressions involving null pointers.
> 	(tree_single_nonzero_warnv_p): Call maybe_nonzero_address.
>
> Index: gcc/cp/constexpr.c
> ===================================================================
> --- gcc/cp/constexpr.c	(revision 234306)
> +++ gcc/cp/constexpr.c	(working copy)
> @@ -1839,11 +1874,26 @@ cxx_eval_array_reference (const constexp

> @@ -3300,10 +3357,21 @@ cxx_eval_constant_expression (const cons
> +
> +      if (TREE_CODE (t) == INTEGER_CST
> +	  && TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
> +	  && !integer_zerop (t))
> +	{
> +	  if (!ctx->quiet)
> +	    error ("null pointer arithmetic in %qE", t);
> +	  if (nullptr_p)
> +	    *nullptr_p = true;
> +	}
Something looks odd here.

You're testing !integer_zerop, so in T is going to be non-NULL, but you 
mentioned null pointer arithmetic in the error message.  Am I missing 
something here?



> @@ -3738,15 +3812,32 @@ cxx_eval_constant_expression (const cons
> Index: gcc/fold-const.c
> @@ -8639,6 +8653,38 @@ fold_comparison (location_t loc, enum tr
>   	    base1 = build_fold_addr_expr_loc (loc, base1);
>   	  return fold_build2_loc (loc, code, type, base0, base1);
>   	}
> +
> +      /* Comparison between an ordinary (non-weak) symbol and a null
> +	 pointer can be eliminated since such sybols must have a non
> +	 null address.  */
> +      else if (DECL_P (base0)
> +	       && maybe_nonzero_address (base0) > 0
> +	       // && (!HAS_DECL_ASSEMBLER_NAME_P (base0) || !DECL_WEAK (base0))
Please remove the commented out line.


> +	       /* Avoid folding references to struct members at offset 0 to
> +		  prevent tests like '&ptr->firstmember == 0' from getting
> +		  eliminated.  When ptr is null, although the -> expression
> +		  is strictly speaking invalid, GCC retains it as a matter
> +		  of QoI.  See PR c/44555. */
> +	       && (TREE_CODE (op0) != ADDR_EXPR
> +		   || TREE_CODE (TREE_OPERAND (op0, 0)) != COMPONENT_REF
> +		   || compare_tree_int (DECL_FIELD_OFFSET ((TREE_OPERAND
> +				           (TREE_OPERAND (op0, 0), 1))), 0))
> +	       && TREE_CODE (arg1) == INTEGER_CST
> +	       && compare_tree_int (arg1, 0) == 0)
> +	{
> +	  switch (code)
> +	    {
> +	    case GE_EXPR:
> +	    case EQ_EXPR:
> +	    case LE_EXPR:
> +	      return boolean_false_node;
> +	    case GT_EXPR:
> +	    case LT_EXPR:
> +	    case NE_EXPR:
> +	      return boolean_true_node;
> +	    default: gcc_unreachable ();
Can you put the gcc_unreachable on a new line?  I know there's a few 
cases in the sources where it's on the default: line, but the vast 
majority have it on its own line.





More information about the Gcc-patches mailing list