diff mbox

C++ PATCH for c++/68206, 68530 (ICE with loop in constexpr)

Message ID 57167C85.40102@redhat.com
State New
Headers show

Commit Message

Jason Merrill April 19, 2016, 6:44 p.m. UTC
Well-formed C++14 code with a loop in a constexpr function works fine, 
but we were crashing while trying to diagnose an unsuitable constexpr 
function because potential_constant_expression_1 didn't understand loops.

The second patch improves constexpr handling of EXIT_EXPR and loops 
around COMPOUND_EXPR rather than STATEMENT_LIST.  This is not currently 
necessary, but might be in future.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit 0e632adeb8c2253f6a9f9e4445c577eef51b1f4c
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Apr 19 13:59:05 2016 -0400

    	Improve constexpr handling of other loop forms.
    
    	* constexpr.c (breaks): Handle EXIT_EXPR.
    	(cxx_eval_loop_expr): Handle COMPOUND_EXPR body.
    	(cxx_eval_constant_expression): Handle EXIT_EXPR, improve handling
    	of COMPOUND_EXPR.

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index d508660..41f0b5c 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3241,8 +3241,9 @@  static bool
 breaks (tree *jump_target)
 {
   return *jump_target
-    && TREE_CODE (*jump_target) == LABEL_DECL
-    && LABEL_DECL_BREAK (*jump_target);
+    && ((TREE_CODE (*jump_target) == LABEL_DECL
+	 && LABEL_DECL_BREAK (*jump_target))
+	|| TREE_CODE (*jump_target) == EXIT_EXPR);
 }
 
 static bool
@@ -3358,8 +3359,8 @@  cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
       hash_set<tree> save_exprs;
       new_ctx.save_exprs = &save_exprs;
 
-      cxx_eval_statement_list (&new_ctx, body,
-			       non_constant_p, overflow_p, jump_target);
+      cxx_eval_constant_expression (&new_ctx, body, /*lval*/false,
+				    non_constant_p, overflow_p, jump_target);
 
       /* Forget saved values of SAVE_EXPRs.  */
       for (hash_set<tree>::iterator iter = save_exprs.begin();
@@ -3750,6 +3751,8 @@  cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 	    cxx_eval_constant_expression (ctx, op0,
 					  true, non_constant_p, overflow_p,
 					  jump_target);
+	    if (*non_constant_p)
+	      return t;
 	    op1 = TREE_OPERAND (t, 1);
 	    r = cxx_eval_constant_expression (ctx, op1,
 					      lval, non_constant_p, overflow_p,
@@ -4015,6 +4018,17 @@  cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 	}
       break;
 
+    case EXIT_EXPR:
+      {
+	tree cond = TREE_OPERAND (t, 0);
+	cond = cxx_eval_constant_expression (ctx, cond, /*lval*/false,
+					     non_constant_p, overflow_p);
+	VERIFY_CONSTANT (cond);
+	if (integer_nonzerop (cond))
+	  *jump_target = t;
+      }
+      break;
+
     case GOTO_EXPR:
       *jump_target = TREE_OPERAND (t, 0);
       gcc_assert (breaks (jump_target) || continues (jump_target));