Re: C++ PATCH for c++/85258, ICE with invalid range-based for-loop

2018-04-12 Thread Jason Merrill
OK.

On Thu, Apr 12, 2018 at 1:47 PM, Marek Polacek  wrote:
> This is a crash on invalid which started when we changed 
> decl_maybe_constant_var_p
> to say true for references.  Then in tsubst_copy we take this branch:
>   if (decl_maybe_constant_var_p (r))
> {
>   /* We can't call cp_finish_decl, so handle the
>  initializer by hand.  */
>   tree init = tsubst_init (DECL_INITIAL (t), r, args,
>complain, in_decl);
> but tsubst_init can return NULL_TREE, which potential_constant_expression
> knows how to handle, but reduced_constant_expression_p didn't.  So the
> following patch will fix the ICE.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2018-04-12  Marek Polacek  
>
> PR c++/85258
> * constexpr.c (reduced_constant_expression_p): Return false for null
> trees.
>
> * g++.dg/parse/error61.C: New test.
>
> diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
> index 75f56df4465..82f14baaefd 100644
> --- gcc/cp/constexpr.c
> +++ gcc/cp/constexpr.c
> @@ -1773,6 +1773,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
> tree t,
>  bool
>  reduced_constant_expression_p (tree t)
>  {
> +  if (t == NULL_TREE)
> +return false;
> +
>switch (TREE_CODE (t))
>  {
>  case PTRMEM_CST:
> @@ -1794,9 +1797,8 @@ reduced_constant_expression_p (tree t)
> field = NULL_TREE;
>FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), i, idx, val)
> {
> - if (!val)
> -   /* We're in the middle of initializing this element.  */
> -   return false;
> + /* If VAL is null, we're in the middle of initializing this
> +element.  */
>   if (!reduced_constant_expression_p (val))
> return false;
>   if (field)
> diff --git gcc/testsuite/g++.dg/parse/error61.C 
> gcc/testsuite/g++.dg/parse/error61.C
> index e69de29bb2d..199e1aa721c 100644
> --- gcc/testsuite/g++.dg/parse/error61.C
> +++ gcc/testsuite/g++.dg/parse/error61.C
> @@ -0,0 +1,14 @@
> +// PR c++/85258
> +// { dg-do compile { target c++11 } }
> +
> +template void foo()
> +{
> +  int x[8];
> +  for (int& i, j : x) // { dg-error "multiple" }
> +i = 0; // { dg-error "local variable" }
> +}
> +
> +void bar()
> +{
> +  foo<0>();
> +}
>
> Marek


C++ PATCH for c++/85258, ICE with invalid range-based for-loop

2018-04-12 Thread Marek Polacek
This is a crash on invalid which started when we changed 
decl_maybe_constant_var_p
to say true for references.  Then in tsubst_copy we take this branch:
  if (decl_maybe_constant_var_p (r))
{
  /* We can't call cp_finish_decl, so handle the
 initializer by hand.  */
  tree init = tsubst_init (DECL_INITIAL (t), r, args,
   complain, in_decl);
but tsubst_init can return NULL_TREE, which potential_constant_expression
knows how to handle, but reduced_constant_expression_p didn't.  So the
following patch will fix the ICE.

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

2018-04-12  Marek Polacek  

PR c++/85258
* constexpr.c (reduced_constant_expression_p): Return false for null
trees.

* g++.dg/parse/error61.C: New test.

diff --git gcc/cp/constexpr.c gcc/cp/constexpr.c
index 75f56df4465..82f14baaefd 100644
--- gcc/cp/constexpr.c
+++ gcc/cp/constexpr.c
@@ -1773,6 +1773,9 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
 bool
 reduced_constant_expression_p (tree t)
 {
+  if (t == NULL_TREE)
+return false;
+
   switch (TREE_CODE (t))
 {
 case PTRMEM_CST:
@@ -1794,9 +1797,8 @@ reduced_constant_expression_p (tree t)
field = NULL_TREE;
   FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), i, idx, val)
{
- if (!val)
-   /* We're in the middle of initializing this element.  */
-   return false;
+ /* If VAL is null, we're in the middle of initializing this
+element.  */
  if (!reduced_constant_expression_p (val))
return false;
  if (field)
diff --git gcc/testsuite/g++.dg/parse/error61.C 
gcc/testsuite/g++.dg/parse/error61.C
index e69de29bb2d..199e1aa721c 100644
--- gcc/testsuite/g++.dg/parse/error61.C
+++ gcc/testsuite/g++.dg/parse/error61.C
@@ -0,0 +1,14 @@
+// PR c++/85258
+// { dg-do compile { target c++11 } }
+
+template void foo()
+{
+  int x[8];
+  for (int& i, j : x) // { dg-error "multiple" }
+i = 0; // { dg-error "local variable" }
+}
+
+void bar()
+{
+  foo<0>();
+}

Marek