In some cases we were accepting in constant-expressions const variables of non-integral type, which is not correct; variables of non-integral type must be marked constexpr to be usable in constant expressions.

When fixing this we need to preserve the optimization that lets us use such constant values in calculating initializers for other variables, however.

I implemented this by adding a 'strict' flag to potential_constant_expression and cxx_eval_constant_expression which is normally true, but is false in maybe_constant_init.

Along the way, I changed the name of integral_constant_value, which hasn't been correct for a while now, and fixed up a couple of callers that don't need to guard against aggregate values from scalar_constant_value. This also fixes a bug in ocp_convert where we could pull a CONSTRUCTOR out of a variable when converting to a scalar type.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 1f57d6c56b65f548c22a32dcb76b6f9f79745a54
Author: Jason Merrill <ja...@redhat.com>
Date:   Tue Nov 18 23:42:39 2014 -0500

    	PR c++/57979
    	* init.c (decl_really_constant_value): Rename from
    	integral_constant_value.
    	(scalar_constant_value): Similar but limited to scalar results.
    	(decl_constant_value_safe): Remove.
    	(constant_value_1): Respect return_aggregate_cst_ok_p.
    	* typeck.c (decay_conversion): Use scalar_constant_value.
    	* call.c (convert_like_real): Likewise.
    	* cvt.c (ocp_convert): No need to check CLASS_TYPE_P.
    	* typeck.c (decay_conversion): Or ARRAY_TYPE.
    	* constexpr.c (struct constexpr_ctx): Add strict field.
    	(cxx_eval_constant_expression) [VAR_DECL]: Use it to select between
    	decl_constant_value and decl_really_constant_value.
    	(cxx_eval_outermost_constant_expr): Add strict parm.
    	(maybe_constant_init): Not strict.
    	(potential_constant_expression_1): Add strict parm.
    	Shorten most internal calls with RECUR macro.
    	* cp-tree.h, pt.c, semantics.c: Adjust.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index c180890..5cda1b1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6247,7 +6247,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	 leave it as an lvalue.  */
       if (inner >= 0)
         {   
-          expr = decl_constant_value_safe (expr);
+          expr = scalar_constant_value (expr);
           if (expr == null_node && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype))
             /* If __null has been converted to an integer type, we do not
                want to warn about uses of EXPR as an integer, rather than
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 77f5159..5268545 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -869,6 +869,7 @@ struct constexpr_ctx {
   tree ctor;
   tree object;
   bool quiet;
+  bool strict;
 };
 
 /* A table of all constexpr calls that have been evaluated by the
@@ -2818,7 +2819,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 	return t;
       /* else fall through. */
     case CONST_DECL:
-      r = integral_constant_value (t);
+      if (ctx->strict)
+	r = decl_really_constant_value (t);
+      else
+	r = decl_constant_value (t);
       if (TREE_CODE (r) == TARGET_EXPR
 	  && TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
 	r = TARGET_EXPR_INITIAL (r);
@@ -3302,11 +3306,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 
 static tree
 cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
-				  tree object = NULL_TREE)
+				  bool strict = true, tree object = NULL_TREE)
 {
   bool non_constant_p = false;
   bool overflow_p = false;
-  constexpr_ctx ctx = { NULL, NULL, NULL, NULL, allow_non_constant };
+  constexpr_ctx ctx = { NULL, NULL, NULL, NULL, allow_non_constant, strict };
   hash_map<tree,tree> map;
   ctx.values = &map;
   tree type = initialized_type (t);
@@ -3415,7 +3419,7 @@ is_sub_constant_expr (tree t)
 {
   bool non_constant_p = false;
   bool overflow_p = false;
-  constexpr_ctx ctx = { NULL, NULL, NULL, NULL, true };
+  constexpr_ctx ctx = { NULL, NULL, NULL, NULL, true, true };
   hash_map <tree, tree> map;
   ctx.values = &map;
   cxx_eval_constant_expression (&ctx, t, false, &non_constant_p,
@@ -3430,7 +3434,7 @@ is_sub_constant_expr (tree t)
 tree
 cxx_constant_value (tree t, tree decl)
 {
-  return cxx_eval_outermost_constant_expr (t, false, decl);
+  return cxx_eval_outermost_constant_expr (t, false, true, decl);
 }
 
 /* If T is a constant expression, returns its reduced value.
@@ -3455,7 +3459,7 @@ maybe_constant_value (tree t, tree decl)
       return t;
     }
 
-  r = cxx_eval_outermost_constant_expr (t, true, decl);
+  r = cxx_eval_outermost_constant_expr (t, true, true, decl);
 #ifdef ENABLE_CHECKING
   /* cp_tree_equal looks through NOPs, so allow them.  */
   gcc_assert (r == t
@@ -3515,7 +3519,7 @@ fold_non_dependent_expr (tree t)
 	      return t;
 	    }
 
-	  tree r = cxx_eval_outermost_constant_expr (t, true, NULL_TREE);
+	  tree r = cxx_eval_outermost_constant_expr (t, true, true, NULL_TREE);
 #ifdef ENABLE_CHECKING
 	  /* cp_tree_equal looks through NOPs, so allow them.  */
 	  gcc_assert (r == t
@@ -3550,7 +3554,13 @@ maybe_constant_init (tree t, tree decl)
     t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == INIT_EXPR)
     t = TREE_OPERAND (t, 1);
-  t = maybe_constant_value (t, decl);
+  if (instantiation_dependent_expression_p (t)
+      || type_unknown_p (t)
+      || BRACE_ENCLOSED_INITIALIZER_P (t)
+      || !potential_static_init_expression (t))
+    /* Don't try to evaluate it.  */;
+  else
+    t = cxx_eval_outermost_constant_expr (t, true, false, decl);
   if (TREE_CODE (t) == TARGET_EXPR)
     {
       tree init = TARGET_EXPR_INITIAL (t);
@@ -3604,8 +3614,10 @@ check_automatic_or_tls (tree ref)
       not evaluated are not considered.   */
 
 static bool
-potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
+potential_constant_expression_1 (tree t, bool want_rval, bool strict,
+				 tsubst_flags_t flags)
 {
+#define RECUR(T,RV) potential_constant_expression_1 ((T), (RV), strict, flags)
   enum { any = false, rval = true };
   int i;
   tree tmp;
@@ -3698,14 +3710,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 		    tree x = get_nth_callarg (t, 0);
 		    if (is_this_parameter (x))
 		      return true;
-		    else if (!potential_constant_expression_1 (x, rval, flags))
+		    else if (!RECUR (x, rval))
 		      return false;
 		    i = 1;
 		  }
 	      }
 	    else
 	      {
-		if (!potential_constant_expression_1 (fun, true, flags))
+		if (!RECUR (fun, true))
 		  return false;
 		fun = get_first_fn (fun);
 	      }
@@ -3716,7 +3728,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  }
 	else
           {
-	    if (potential_constant_expression_1 (fun, rval, flags))
+	    if (RECUR (fun, rval))
 	      /* Might end up being a constant function pointer.  */;
 	    else
 	      return false;
@@ -3724,7 +3736,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
         for (; i < nargs; ++i)
           {
             tree x = get_nth_callarg (t, i);
-	    if (!potential_constant_expression_1 (x, rval, flags))
+	    if (!RECUR (x, rval))
 	      return false;
           }
         return true;
@@ -3739,10 +3751,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
             -- an lvalue of literal type that refers to non-volatile
                object defined with constexpr, or that refers to a
                sub-object of such an object;  */
-      return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags);
+      return RECUR (TREE_OPERAND (t, 0), rval);
 
     case VAR_DECL:
-      if (want_rval && !decl_constant_var_p (t)
+      if (want_rval
+	  && !decl_constant_var_p (t)
+	  && (strict
+	      || !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t))
+	      || !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t))
 	  && !var_in_constexpr_fn (t)
 	  && !dependent_type_p (TREE_TYPE (t)))
         {
@@ -3768,8 +3784,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 			"reinterpret_cast from integer to pointer");
 	    return false;
 	  }
-        return (potential_constant_expression_1
-		(from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags));
+        return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
       }
 
     case ADDR_EXPR:
@@ -3797,7 +3812,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
           return false;
         }
 #endif
-      return potential_constant_expression_1 (t, any, flags);
+      return RECUR (t, any);
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -3807,12 +3822,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
             of literal type or of pointer to literal type.  */
       /* This test would be redundant, as it follows from the
 	 postfix-expression being a potential constant expression.  */
-      return potential_constant_expression_1 (TREE_OPERAND (t, 0),
-					      want_rval, flags);
+      return RECUR (TREE_OPERAND (t, 0), want_rval);
 
     case EXPR_PACK_EXPANSION:
-      return potential_constant_expression_1 (PACK_EXPANSION_PATTERN (t),
-					      want_rval, flags);
+      return RECUR (PACK_EXPANSION_PATTERN (t), want_rval);
 
     case INDIRECT_REF:
       {
@@ -3829,7 +3842,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	      }
 	    return true;
 	  }
-	return potential_constant_expression_1 (x, rval, flags);
+	return RECUR (x, rval);
       }
 
     case STATEMENT_LIST:
@@ -3837,7 +3850,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	tree_stmt_iterator i;
 	for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
 	  {
-	    if (!potential_constant_expression_1 (tsi_stmt (i), any, flags))
+	    if (!RECUR (tsi_stmt (i), any))
 	      return false;
 	  }
 	return true;
@@ -3847,64 +3860,64 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case MODIFY_EXPR:
       if (cxx_dialect < cxx14)
 	goto fail;
-      if (!potential_constant_expression_1 (TREE_OPERAND (t, 0), any, flags))
+      if (!RECUR (TREE_OPERAND (t, 0), any))
 	return false;
-      if (!potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags))
+      if (!RECUR (TREE_OPERAND (t, 1), rval))
 	return false;
       return true;
 
     case MODOP_EXPR:
       if (cxx_dialect < cxx14)
 	goto fail;
-      if (!potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags))
+      if (!RECUR (TREE_OPERAND (t, 0), rval))
 	return false;
-      if (!potential_constant_expression_1 (TREE_OPERAND (t, 2), rval, flags))
+      if (!RECUR (TREE_OPERAND (t, 2), rval))
 	return false;
       return true;
 
     case IF_STMT:
-      if (!potential_constant_expression_1 (IF_COND (t), rval, flags))
+      if (!RECUR (IF_COND (t), rval))
 	return false;
-      if (!potential_constant_expression_1 (THEN_CLAUSE (t), any, flags))
+      if (!RECUR (THEN_CLAUSE (t), any))
 	return false;
-      if (!potential_constant_expression_1 (ELSE_CLAUSE (t), any, flags))
+      if (!RECUR (ELSE_CLAUSE (t), any))
 	return false;
       return true;
 
     case DO_STMT:
-      if (!potential_constant_expression_1 (DO_COND (t), rval, flags))
+      if (!RECUR (DO_COND (t), rval))
 	return false;
-      if (!potential_constant_expression_1 (DO_BODY (t), any, flags))
+      if (!RECUR (DO_BODY (t), any))
 	return false;
       return true;
 
     case FOR_STMT:
-      if (!potential_constant_expression_1 (FOR_INIT_STMT (t), any, flags))
+      if (!RECUR (FOR_INIT_STMT (t), any))
 	return false;
-      if (!potential_constant_expression_1 (FOR_COND (t), rval, flags))
+      if (!RECUR (FOR_COND (t), rval))
 	return false;
-      if (!potential_constant_expression_1 (FOR_EXPR (t), any, flags))
+      if (!RECUR (FOR_EXPR (t), any))
 	return false;
-      if (!potential_constant_expression_1 (FOR_BODY (t), any, flags))
+      if (!RECUR (FOR_BODY (t), any))
 	return false;
       return true;
 
     case WHILE_STMT:
-      if (!potential_constant_expression_1 (WHILE_COND (t), rval, flags))
+      if (!RECUR (WHILE_COND (t), rval))
 	return false;
-      if (!potential_constant_expression_1 (WHILE_BODY (t), any, flags))
+      if (!RECUR (WHILE_BODY (t), any))
 	return false;
       return true;
 
     case SWITCH_STMT:
-      if (!potential_constant_expression_1 (SWITCH_STMT_COND (t), rval, flags))
+      if (!RECUR (SWITCH_STMT_COND (t), rval))
 	return false;
-      if (!potential_constant_expression_1 (SWITCH_STMT_BODY (t), any, flags))
+      if (!RECUR (SWITCH_STMT_BODY (t), any))
 	return false;
       return true;
 
     case STMT_EXPR:
-      return potential_constant_expression_1 (STMT_EXPR_STMT (t), rval, flags);
+      return RECUR (STMT_EXPR_STMT (t), rval);
 
     case LAMBDA_EXPR:
     case DYNAMIC_CAST_EXPR:
@@ -4002,8 +4015,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case FIXED_CONVERT_EXPR:
     case UNARY_PLUS_EXPR:
     unary:
-      return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval,
-					      flags);
+      return RECUR (TREE_OPERAND (t, 0), rval);
 
     case CAST_EXPR:
     case CONST_CAST_EXPR:
@@ -4022,13 +4034,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
 	}
 
-      return (potential_constant_expression_1
-	      (TREE_OPERAND (t, 0),
-	       TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
+      return (RECUR (TREE_OPERAND (t, 0),
+		     TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE));
 
     case BIND_EXPR:
-      return potential_constant_expression_1 (BIND_EXPR_BODY (t),
-					      want_rval, flags);
+      return RECUR (BIND_EXPR_BODY (t), want_rval);
 
     case WITH_CLEANUP_EXPR:
     case CLEANUP_POINT_EXPR:
@@ -4041,12 +4051,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case NON_DEPENDENT_EXPR:
       /* For convenience.  */
     case RETURN_EXPR:
-      return potential_constant_expression_1 (TREE_OPERAND (t, 0),
-					      want_rval, flags);
+      return RECUR (TREE_OPERAND (t, 0), want_rval);
 
     case SCOPE_REF:
-      return potential_constant_expression_1 (TREE_OPERAND (t, 1),
-					      want_rval, flags);
+      return RECUR (TREE_OPERAND (t, 1), want_rval);
 
     case TARGET_EXPR:
       if (!literal_type_p (TREE_TYPE (t)))
@@ -4060,15 +4068,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	  return false;
 	}
     case INIT_EXPR:
-      return potential_constant_expression_1 (TREE_OPERAND (t, 1),
-					      rval, flags);
+      return RECUR (TREE_OPERAND (t, 1), rval);
 
     case CONSTRUCTOR:
       {
         vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
         constructor_elt *ce;
         for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
-	  if (!potential_constant_expression_1 (ce->value, want_rval, flags))
+	  if (!RECUR (ce->value, want_rval))
 	    return false;
 	return true;
       }
@@ -4077,13 +4084,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       {
 	gcc_assert (TREE_PURPOSE (t) == NULL_TREE
 		    || DECL_P (TREE_PURPOSE (t)));
-	if (!potential_constant_expression_1 (TREE_VALUE (t), want_rval,
-					      flags))
+	if (!RECUR (TREE_VALUE (t), want_rval))
 	  return false;
 	if (TREE_CHAIN (t) == NULL_TREE)
 	  return true;
-	return potential_constant_expression_1 (TREE_CHAIN (t), want_rval,
-						flags);
+	return RECUR (TREE_CHAIN (t), want_rval);
       }
 
     case TRUNC_DIV_EXPR:
@@ -4095,7 +4100,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case ROUND_MOD_EXPR:
       {
 	tree denom = TREE_OPERAND (t, 1);
-	if (!potential_constant_expression_1 (denom, rval, flags))
+	if (!RECUR (denom, rval))
 	  return false;
 	/* We can't call cxx_eval_outermost_constant_expr on an expression
 	   that hasn't been through instantiate_non_dependent_expr yet.  */
@@ -4110,8 +4115,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	else
 	  {
 	    want_rval = true;
-	    return potential_constant_expression_1 (TREE_OPERAND (t, 0),
-						    want_rval, flags);
+	    return RECUR (TREE_OPERAND (t, 0), want_rval);
 	  }
       }
 
@@ -4125,7 +4129,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	STRIP_NOPS (op1);
 	if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
 	    || TREE_CODE (op1) == EMPTY_CLASS_EXPR)
-	  return potential_constant_expression_1 (op0, want_rval, flags);
+	  return RECUR (op0, want_rval);
 	else
 	  goto binary;
       }
@@ -4143,12 +4147,12 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     truth:
       {
 	tree op = TREE_OPERAND (t, 0);
-	if (!potential_constant_expression_1 (op, rval, flags))
+	if (!RECUR (op, rval))
 	  return false;
 	if (!processing_template_decl)
 	  op = cxx_eval_outermost_constant_expr (op, true);
 	if (tree_int_cst_equal (op, tmp))
-	  return potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags);
+	  return RECUR (TREE_OPERAND (t, 1), rval);
 	else
 	  return true;
       }
@@ -4186,8 +4190,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case DOTSTAR_EXPR:
     binary:
       for (i = 0; i < 2; ++i)
-	if (!potential_constant_expression_1 (TREE_OPERAND (t, i),
-					      want_rval, flags))
+	if (!RECUR (TREE_OPERAND (t, i), want_rval))
 	  return false;
       return true;
 
@@ -4199,8 +4202,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case FMA_EXPR:
     case VEC_PERM_EXPR:
      for (i = 0; i < 3; ++i)
-      if (!potential_constant_expression_1 (TREE_OPERAND (t, i),
-					    true, flags))
+      if (!RECUR (TREE_OPERAND (t, i), true))
 	return false;
      return true;
 
@@ -4210,19 +4212,17 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 	 care about; otherwise we only require that the condition and
 	 either of the legs be potentially constant.  */
       tmp = TREE_OPERAND (t, 0);
-      if (!potential_constant_expression_1 (tmp, rval, flags))
+      if (!RECUR (tmp, rval))
 	return false;
       if (!processing_template_decl)
 	tmp = cxx_eval_outermost_constant_expr (tmp, true);
       if (integer_zerop (tmp))
-	return potential_constant_expression_1 (TREE_OPERAND (t, 2),
-						want_rval, flags);
+	return RECUR (TREE_OPERAND (t, 2), want_rval);
       else if (TREE_CODE (tmp) == INTEGER_CST)
-	return potential_constant_expression_1 (TREE_OPERAND (t, 1),
-						want_rval, flags);
+	return RECUR (TREE_OPERAND (t, 1), want_rval);
       for (i = 1; i < 3; ++i)
 	if (potential_constant_expression_1 (TREE_OPERAND (t, i),
-					     want_rval, tf_none))
+					     want_rval, strict, tf_none))
 	  return true;
       if (flags & tf_error)
         error ("expression %qE is not a constant-expression", t);
@@ -4246,6 +4246,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
       gcc_unreachable();
       return false;
     }
+#undef RECUR
 }
 
 /* The main entry point to the above.  */
@@ -4253,7 +4254,13 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
 bool
 potential_constant_expression (tree t)
 {
-  return potential_constant_expression_1 (t, false, tf_none);
+  return potential_constant_expression_1 (t, false, true, tf_none);
+}
+
+bool
+potential_static_init_expression (tree t)
+{
+  return potential_constant_expression_1 (t, false, false, tf_none);
 }
 
 /* As above, but require a constant rvalue.  */
@@ -4261,7 +4268,7 @@ potential_constant_expression (tree t)
 bool
 potential_rvalue_constant_expression (tree t)
 {
-  return potential_constant_expression_1 (t, true, tf_none);
+  return potential_constant_expression_1 (t, true, true, tf_none);
 }
 
 /* Like above, but complain about non-constant expressions.  */
@@ -4269,7 +4276,7 @@ potential_rvalue_constant_expression (tree t)
 bool
 require_potential_constant_expression (tree t)
 {
-  return potential_constant_expression_1 (t, false, tf_warning_or_error);
+  return potential_constant_expression_1 (t, false, true, tf_warning_or_error);
 }
 
 /* Cross product of the above.  */
@@ -4277,7 +4284,7 @@ require_potential_constant_expression (tree t)
 bool
 require_potential_rvalue_constant_expression (tree t)
 {
-  return potential_constant_expression_1 (t, true, tf_warning_or_error);
+  return potential_constant_expression_1 (t, true, true, tf_warning_or_error);
 }
 
 #include "gt-cp-constexpr.h"
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 3542344..1e09629 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5551,8 +5551,8 @@ extern tree build_vec_delete			(tree, tree,
 extern tree create_temporary_var		(tree);
 extern void initialize_vtbl_ptrs		(tree);
 extern tree build_java_class_ref		(tree);
-extern tree integral_constant_value		(tree);
-extern tree decl_constant_value_safe	        (tree);
+extern tree scalar_constant_value		(tree);
+extern tree decl_really_constant_value		(tree);
 extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, bool);
 extern tree build_vtbl_address                  (tree);
 
@@ -6349,6 +6349,7 @@ extern tree register_constexpr_fundef           (tree, tree);
 extern bool check_constexpr_ctor_body           (tree, tree, bool);
 extern tree ensure_literal_type_for_constexpr_object (tree);
 extern bool potential_constant_expression       (tree);
+extern bool potential_static_init_expression    (tree);
 extern bool potential_rvalue_constant_expression (tree);
 extern bool require_potential_constant_expression (tree);
 extern bool require_potential_rvalue_constant_expression (tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 7be4f31..aba75ff 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -675,9 +675,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
     }
 
   /* FIXME remove when moving to c_fully_fold model.  */
-  /* FIXME do we still need this test?  */
-  if (!CLASS_TYPE_P (type))
-    e = integral_constant_value (e);
+  e = scalar_constant_value (e);
   if (error_operand_p (e))
     return error_mark_node;
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e69b521..899637f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -12993,7 +12993,7 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
   tree context;
   tree type;
 
-  /* integral_constant_value will pull out this expression, so make sure
+  /* scalar_constant_value will pull out this expression, so make sure
      it's folded as appropriate.  */
   if (processing_template_decl)
     value = fold_non_dependent_expr (value);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 5c61107..19e2cdd 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2004,16 +2004,16 @@ build_offset_ref (tree type, tree member, bool address_p,
 
 /* If DECL is a scalar enumeration constant or variable with a
    constant initializer, return the initializer (or, its initializers,
-   recursively); otherwise, return DECL.  If INTEGRAL_P, the
-   initializer is only returned if DECL is an integral
+   recursively); otherwise, return DECL.  If STRICT_P, the
+   initializer is only returned if DECL is a
    constant-expression.  If RETURN_AGGREGATE_CST_OK_P, it is ok to
    return an aggregate constant.  */
 
 static tree
-constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p)
+constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p)
 {
   while (TREE_CODE (decl) == CONST_DECL
-	 || (integral_p
+	 || (strict_p
 	     ? decl_constant_var_p (decl)
 	     : (VAR_P (decl)
 		&& CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
@@ -2047,7 +2047,7 @@ constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p)
       if (!init
 	  || !TREE_TYPE (init)
 	  || !TREE_CONSTANT (init)
-	  || (!integral_p && !return_aggregate_cst_ok_p
+	  || (!return_aggregate_cst_ok_p
 	      /* Unless RETURN_AGGREGATE_CST_OK_P is true, do not
 		 return an aggregate constant (of which string
 		 literals are a special case), as we do not want
@@ -2062,37 +2062,36 @@ constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p)
   return decl;
 }
 
-/* If DECL is a CONST_DECL, or a constant VAR_DECL initialized by
-   constant of integral or enumeration type, then return that value.
-   These are those variables permitted in constant expressions by
-   [5.19/1].  */
+/* If DECL is a CONST_DECL, or a constant VAR_DECL initialized by constant
+   of integral or enumeration type, or a constexpr variable of scalar type,
+   then return that value.  These are those variables permitted in constant
+   expressions by [5.19/1].  */
 
 tree
-integral_constant_value (tree decl)
+scalar_constant_value (tree decl)
 {
-  return constant_value_1 (decl, /*integral_p=*/true,
+  return constant_value_1 (decl, /*strict_p=*/true,
 			   /*return_aggregate_cst_ok_p=*/false);
 }
 
-/* A more relaxed version of integral_constant_value, used by the
+/* Like scalar_constant_value, but can also return aggregate initializers.  */
+
+tree
+decl_really_constant_value (tree decl)
+{
+  return constant_value_1 (decl, /*strict_p=*/true,
+			   /*return_aggregate_cst_ok_p=*/true);
+}
+
+/* A more relaxed version of scalar_constant_value, used by the
    common C/C++ code.  */
 
 tree
 decl_constant_value (tree decl)
 {
-  return constant_value_1 (decl, /*integral_p=*/processing_template_decl,
+  return constant_value_1 (decl, /*strict_p=*/processing_template_decl,
 			   /*return_aggregate_cst_ok_p=*/true);
 }
-
-/* A version of integral_constant_value used by the C++ front end for
-   optimization purposes.  */
-
-tree
-decl_constant_value_safe (tree decl)
-{
-  return constant_value_1 (decl, /*integral_p=*/processing_template_decl,
-			   /*return_aggregate_cst_ok_p=*/false);
-}
 
 /* Common subroutines of build_new and build_vec_delete.  */
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 6661325..0b8fd7f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12805,7 +12805,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	  return t;
 	/* If ARGS is NULL, then T is known to be non-dependent.  */
 	if (args == NULL_TREE)
-	  return integral_constant_value (t);
+	  return scalar_constant_value (t);
 
 	/* Unfortunately, we cannot just call lookup_name here.
 	   Consider:
@@ -12936,7 +12936,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 		      else if (decl_constant_var_p (r))
 			/* A use of a local constant decays to its value.
 			   FIXME update for core DR 696.  */
-			r = integral_constant_value (r);
+			r = scalar_constant_value (r);
 		    }
 		}
 	      /* Remember this for subsequent uses.  */
@@ -18420,7 +18420,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
     case CONST_DECL:
       if (DECL_TEMPLATE_PARM_P (parm))
 	return unify (tparms, targs, DECL_INITIAL (parm), arg, strict, explain_p);
-      if (arg != integral_constant_value (parm))
+      if (arg != scalar_constant_value (parm))
 	return unify_template_argument_mismatch (explain_p, parm, arg);
       return unify_success (explain_p);
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 6888121..639702a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3125,7 +3125,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)
 	   form, so wait until instantiation time.  */
 	return decl;
       else if (decl_constant_var_p (decl))
-	return integral_constant_value (decl);
+	return scalar_constant_value (decl);
     }
 
   if (parsing_nsdmi ())
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 05bc916..53fe67a 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1936,17 +1936,10 @@ decay_conversion (tree exp, tsubst_flags_t complain)
 
   code = TREE_CODE (type);
 
-  /* For an array decl decay_conversion should not try to return its
-     initializer.  */
-  if (code != ARRAY_TYPE)
-    {
-      /* FIXME remove? at least need to remember that this isn't really a
-	 constant expression if EXP isn't decl_constant_var_p, like with
-	 C_MAYBE_CONST_EXPR.  */
-      exp = decl_constant_value_safe (exp);
-      if (error_operand_p (exp))
-	return error_mark_node;
-    }
+  /* FIXME remove for delayed folding.  */
+  exp = scalar_constant_value (exp);
+  if (error_operand_p (exp))
+    return error_mark_node;
 
   if (NULLPTR_TYPE_P (type) && !TREE_SIDE_EFFECTS (exp))
     return nullptr_node;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C
index d52967a..bd146ad 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-object2.C
@@ -3,9 +3,9 @@
 constexpr int verysquare(int x) { return x * x; }
 
 const double mass = 9.8;
-constexpr double energy = mass * verysquare(56.6); // { dg-error "mass" "" { xfail *-*-* } }
+constexpr double energy = mass * verysquare(56.6); // { dg-error "mass" }
 
-int arr[(int)mass];		// { dg-error "mass" "" { xfail *-*-* } }
+int arr[(int)mass];		// { dg-error "" }
 
 float array[verysquare(9)];         // OK -- not C99 VLA
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/nullptr06.C b/gcc/testsuite/g++.dg/cpp0x/nullptr06.C
index e933c35..396ac3a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/nullptr06.C
+++ b/gcc/testsuite/g++.dg/cpp0x/nullptr06.C
@@ -4,7 +4,7 @@
 
 #define assert_true(b) do { char c[2 * bool(b) - 1]; } while(0)
 
-char* const cp1 = nullptr;
+constexpr char* cp1 = nullptr;
 
 void fun()
 {

Reply via email to