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

Message ID 20180412174746.GD10214@redhat.com
State New
Headers show
Series
  • C++ PATCH for c++/85258, ICE with invalid range-based for-loop
Related show

Commit Message

Marek Polacek April 12, 2018, 5:47 p.m.
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  <polacek@redhat.com>

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

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


	Marek

Comments

Jason Merrill April 12, 2018, 7:52 p.m. | #1
OK.

On Thu, Apr 12, 2018 at 1:47 PM, Marek Polacek <polacek@redhat.com> 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  <polacek@redhat.com>
>
>         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<int> void foo()
> +{
> +  int x[8];
> +  for (int& i, j : x) // { dg-error "multiple" }
> +    i = 0; // { dg-error "local variable" }
> +}
> +
> +void bar()
> +{
> +  foo<0>();
> +}
>
>         Marek

Patch

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<int> void foo()
+{
+  int x[8];
+  for (int& i, j : x) // { dg-error "multiple" }
+    i = 0; // { dg-error "local variable" }
+}
+
+void bar()
+{
+  foo<0>();
+}