This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: C++ delayed folding merge


I'm planning to merge the C++ delayed folding branch this week, but I need to get approval of the back end changes (the first patch attached). Most of these are the introduction of non-folding variants of convert_to_*, but there are a few others.

One question: The branch changes 'convert' to not fold its result, and it's not clear to me whether that's part of the expected behavior of a front end 'convert' function or not.

Also, I'm a bit uncertain about merging this at the end of stage 1, since it's a large internal change with relatively small user impact; it just improves handling of constant expression corner cases. I'm inclined to go ahead with it at this point, but I'm interested in contrary opinions.

diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index ae16cfc..d8c7faf 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -930,8 +930,9 @@ interpret_float (const cpp_token *token, unsigned int flags,
   value = build_real (const_type, real);
   if (flags & CPP_N_IMAGINARY)
     {
-      value = build_complex (NULL_TREE, convert (const_type,
-						 integer_zero_node), value);
+      value = build_complex (NULL_TREE,
+			     fold_convert (const_type,
+					   integer_zero_node), value);
       if (type != const_type)
 	{
 	  const_type = TREE_TYPE (value);
diff --git a/gcc/convert.c b/gcc/convert.c
index 113c11f..298d1e4 100644
--- a/gcc/convert.c
+++ b/gcc/convert.c
@@ -34,12 +34,20 @@ along with GCC; see the file COPYING3.  If not see
 #include "builtins.h"
 #include "ubsan.h"
 
+#define maybe_fold_build1_loc(FOLD_P, LOC, CODE, TYPE, EXPR) \
+  ((FOLD_P) ? fold_build1_loc (LOC, CODE, TYPE, EXPR)	     \
+   : build1_loc (LOC, CODE, TYPE, EXPR))
+#define maybe_fold_build2_loc(FOLD_P, LOC, CODE, TYPE, EXPR1, EXPR2) \
+  ((FOLD_P) ? fold_build2_loc (LOC, CODE, TYPE, EXPR1, EXPR2)	     \
+   : build2_loc (LOC, CODE, TYPE, EXPR1, EXPR2))
+
 /* Convert EXPR to some pointer or reference type TYPE.
    EXPR must be pointer, reference, integer, enumeral, or literal zero;
-   in other cases error is called.  */
+   in other cases error is called.  If FOLD_P is true, try to fold the
+   expression.  */
 
-tree
-convert_to_pointer (tree type, tree expr)
+static tree
+convert_to_pointer_1 (tree type, tree expr, bool fold_p)
 {
   location_t loc = EXPR_LOCATION (expr);
   if (TREE_TYPE (expr) == type)
@@ -56,9 +64,10 @@ convert_to_pointer (tree type, tree expr)
 	addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
 
 	if (to_as == from_as)
-	  return fold_build1_loc (loc, NOP_EXPR, type, expr);
+	  return maybe_fold_build1_loc (fold_p, loc, NOP_EXPR, type, expr);
 	else
-	  return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
+	  return maybe_fold_build1_loc (fold_p, loc, ADDR_SPACE_CONVERT_EXPR,
+					type, expr);
       }
 
     case INTEGER_TYPE:
@@ -72,35 +81,54 @@ convert_to_pointer (tree type, tree expr)
 	unsigned int pprec = TYPE_PRECISION (type);
 	unsigned int eprec = TYPE_PRECISION (TREE_TYPE (expr));
 
- 	if (eprec != pprec)
-	  expr = fold_build1_loc (loc, NOP_EXPR,
-			      lang_hooks.types.type_for_size (pprec, 0),
-			      expr);
+	if (eprec != pprec)
+	  expr
+	    = maybe_fold_build1_loc (fold_p, loc, NOP_EXPR,
+				     lang_hooks.types.type_for_size (pprec, 0),
+				     expr);
       }
-
-      return fold_build1_loc (loc, CONVERT_EXPR, type, expr);
+      return maybe_fold_build1_loc (fold_p, loc, CONVERT_EXPR, type, expr);
 
     default:
       error ("cannot convert to a pointer type");
-      return convert_to_pointer (type, integer_zero_node);
+      return convert_to_pointer_1 (type, integer_zero_node, fold_p);
     }
 }
 
+/* A wrapper around convert_to_pointer_1 that always folds the
+   expression.  */
+
+tree
+convert_to_pointer (tree type, tree expr)
+{
+  return convert_to_pointer_1 (type, expr, true);
+}
+
+/* A wrapper around convert_to_pointer_1 that only folds the
+   expression if it is CONSTANT_CLASS_P.  */
+
+tree
+convert_to_pointer_nofold (tree type, tree expr)
+{
+  return convert_to_pointer_1 (type, expr, CONSTANT_CLASS_P (expr));
+}
 
 /* Convert EXPR to some floating-point type TYPE.
 
    EXPR must be float, fixed-point, integer, or enumeral;
-   in other cases error is called.  */
+   in other cases error is called.  If FOLD_P is true, try to fold
+   the expression.  */
 
-tree
-convert_to_real (tree type, tree expr)
+static tree
+convert_to_real_1 (tree type, tree expr, bool fold_p)
 {
   enum built_in_function fcode = builtin_mathfn_code (expr);
   tree itype = TREE_TYPE (expr);
+  location_t loc = EXPR_LOCATION (expr);
 
   if (TREE_CODE (expr) == COMPOUND_EXPR)
     {
-      tree t = convert_to_real (type, TREE_OPERAND (expr, 1));
+      tree t = convert_to_real_1 (type, TREE_OPERAND (expr, 1), fold_p);
       if (t == TREE_OPERAND (expr, 1))
 	return expr;
       return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t),
@@ -208,14 +236,13 @@ convert_to_real (tree type, tree expr)
 		      || TYPE_MODE (newtype) == TYPE_MODE (float_type_node)))
 		{
 		  tree fn = mathfn_built_in (newtype, fcode);
-
 		  if (fn)
-		  {
-		    tree arg = fold (convert_to_real (newtype, arg0));
-		    expr = build_call_expr (fn, 1, arg);
-		    if (newtype == type)
-		      return expr;
-		  }
+		    {
+		      tree arg = convert_to_real_1 (newtype, arg0, fold_p);
+		      expr = build_call_expr (fn, 1, arg);
+		      if (newtype == type)
+			return expr;
+		    }
 		}
 	    }
 	default:
@@ -234,9 +261,11 @@ convert_to_real (tree type, tree expr)
 	  if (!flag_rounding_math
 	      && FLOAT_TYPE_P (itype)
 	      && TYPE_PRECISION (type) < TYPE_PRECISION (itype))
-	    return build1 (TREE_CODE (expr), type,
-			   fold (convert_to_real (type,
-						  TREE_OPERAND (expr, 0))));
+	    {
+	      tree arg = convert_to_real_1 (type, TREE_OPERAND (expr, 0),
+					    fold_p);
+	      return build1 (TREE_CODE (expr), type, arg);
+	    }
 	  break;
 	/* Convert (outertype)((innertype0)a+(innertype1)b)
 	   into ((newtype)a+(newtype)b) where newtype
@@ -272,8 +301,10 @@ convert_to_real (tree type, tree expr)
 		      || newtype == dfloat128_type_node)
 		    {
 		      expr = build2 (TREE_CODE (expr), newtype,
-				     fold (convert_to_real (newtype, arg0)),
-				     fold (convert_to_real (newtype, arg1)));
+				     convert_to_real_1 (newtype, arg0,
+							fold_p),
+				     convert_to_real_1 (newtype, arg1,
+							fold_p));
 		      if (newtype == type)
 			return expr;
 		      break;
@@ -312,8 +343,10 @@ convert_to_real (tree type, tree expr)
 			      && !excess_precision_type (newtype))))
 		    {
 		      expr = build2 (TREE_CODE (expr), newtype,
-				     fold (convert_to_real (newtype, arg0)),
-				     fold (convert_to_real (newtype, arg1)));
+				     convert_to_real_1 (newtype, arg0,
+							fold_p),
+				     convert_to_real_1 (newtype, arg1,
+							fold_p));
 		      if (newtype == type)
 			return expr;
 		    }
@@ -344,30 +377,51 @@ convert_to_real (tree type, tree expr)
 
     case COMPLEX_TYPE:
       return convert (type,
-		      fold_build1 (REALPART_EXPR,
-				   TREE_TYPE (TREE_TYPE (expr)), expr));
+		      maybe_fold_build1_loc (fold_p, loc, REALPART_EXPR,
+					     TREE_TYPE (TREE_TYPE (expr)),
+					     expr));
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       error ("pointer value used where a floating point value was expected");
-      return convert_to_real (type, integer_zero_node);
+      return convert_to_real_1 (type, integer_zero_node, fold_p);
 
     default:
       error ("aggregate value used where a float was expected");
-      return convert_to_real (type, integer_zero_node);
+      return convert_to_real_1 (type, integer_zero_node, fold_p);
     }
 }
 
+/* A wrapper around convert_to_real_1 that always folds the
+   expression.  */
+
+tree
+convert_to_real (tree type, tree expr)
+{
+  return convert_to_real_1 (type, expr, true);
+}
+
+/* A wrapper around convert_to_real_1 that only folds the
+   expression if it is CONSTANT_CLASS_P.  */
+
+tree
+convert_to_real_nofold (tree type, tree expr)
+{
+  return convert_to_real_1 (type, expr, CONSTANT_CLASS_P (expr));
+}
+
 /* Convert EXPR to some integer (or enum) type TYPE.
 
    EXPR must be pointer, integer, discrete (enum, char, or bool), float,
    fixed-point or vector; in other cases error is called.
 
+   If DOFOLD is TRUE, we try to simplify newly-created patterns by folding.
+
    The result of this is always supposed to be a newly created tree node
    not in use in any existing structure.  */
 
-tree
-convert_to_integer (tree type, tree expr)
+static tree
+convert_to_integer_1 (tree type, tree expr, bool dofold)
 {
   enum tree_code ex_form = TREE_CODE (expr);
   tree intype = TREE_TYPE (expr);
@@ -385,7 +439,7 @@ convert_to_integer (tree type, tree expr)
 
   if (ex_form == COMPOUND_EXPR)
     {
-      tree t = convert_to_integer (type, TREE_OPERAND (expr, 1));
+      tree t = convert_to_integer_1 (type, TREE_OPERAND (expr, 1), dofold);
       if (t == TREE_OPERAND (expr, 1))
 	return expr;
       return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t),
@@ -479,7 +533,7 @@ convert_to_integer (tree type, tree expr)
 	  break;
 
 	CASE_FLT_FN (BUILT_IN_TRUNC):
-	  return convert_to_integer (type, CALL_EXPR_ARG (s_expr, 0));
+	  return convert_to_integer_1 (type, CALL_EXPR_ARG (s_expr, 0), dofold);
 
 	default:
 	  break;
@@ -488,7 +542,7 @@ convert_to_integer (tree type, tree expr)
       if (fn)
         {
 	  tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0));
-	  return convert_to_integer (type, newexpr);
+	  return convert_to_integer_1 (type, newexpr, dofold);
 	}
     }
 
@@ -519,7 +573,7 @@ convert_to_integer (tree type, tree expr)
       if (fn)
         {
 	  tree newexpr = build_call_expr (fn, 1, CALL_EXPR_ARG (s_expr, 0));
-	  return convert_to_integer (type, newexpr);
+	  return convert_to_integer_1 (type, newexpr, dofold);
 	}
     }
 
@@ -534,6 +588,8 @@ convert_to_integer (tree type, tree expr)
 	 there widen/truncate to the required type.  Some targets support the
 	 coexistence of multiple valid pointer sizes, so fetch the one we need
 	 from the type.  */
+      if (!dofold)
+	return build1 (CONVERT_EXPR, type, expr);
       expr = fold_build1 (CONVERT_EXPR,
 			  lang_hooks.types.type_for_size
 			    (TYPE_PRECISION (intype), 0),
@@ -578,6 +634,8 @@ convert_to_integer (tree type, tree expr)
 	  else
 	    code = NOP_EXPR;
 
+	  if (!dofold)
+	    return build1 (code, type, expr);
 	  return fold_build1 (code, type, expr);
 	}
 
@@ -784,10 +842,17 @@ convert_to_integer (tree type, tree expr)
 			if (TYPE_UNSIGNED (typex))
 			  typex = signed_type_for (typex);
 		      }
-		    return convert (type,
-				    fold_build2 (ex_form, typex,
-						 convert (typex, arg0),
-						 convert (typex, arg1)));
+		    /* We should do away with all this once we have a proper
+		       type promotion/demotion pass, see PR45397.  */
+		    if (dofold)
+		      return convert (type,
+				      fold_build2 (ex_form, typex,
+						   convert (typex, arg0),
+						   convert (typex, arg1)));
+		    arg0 = build1 (CONVERT_EXPR, typex, arg0);
+		    arg1 = build1 (CONVERT_EXPR, typex, arg1);
+		    expr = build2 (ex_form, typex, arg0, arg1);
+		    return build1 (CONVERT_EXPR, type, expr);
 		  }
 	      }
 	  }
@@ -798,6 +863,9 @@ convert_to_integer (tree type, tree expr)
 	  /* This is not correct for ABS_EXPR,
 	     since we must test the sign before truncation.  */
 	  {
+	    if (!dofold)
+	      break;
+
 	    /* Do the arithmetic in type TYPEX,
 	       then convert result to TYPE.  */
 	    tree typex = type;
@@ -813,7 +881,7 @@ convert_to_integer (tree type, tree expr)
 	      typex = unsigned_type_for (typex);
 	    return convert (type,
 			    fold_build1 (ex_form, typex,
-					 convert (typex,
+					  convert (typex,
 						  TREE_OPERAND (expr, 0))));
 	  }
 
@@ -833,13 +901,15 @@ convert_to_integer (tree type, tree expr)
 	     the conditional and never loses.  A COND_EXPR may have a throw
 	     as one operand, which then has void type.  Just leave void
 	     operands as they are.  */
-	  return fold_build3 (COND_EXPR, type, TREE_OPERAND (expr, 0),
-			      VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1)))
-			      ? TREE_OPERAND (expr, 1)
-			      : convert (type, TREE_OPERAND (expr, 1)),
-			      VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 2)))
-			      ? TREE_OPERAND (expr, 2)
-			      : convert (type, TREE_OPERAND (expr, 2)));
+	  if (dofold)
+	    return
+	      fold_build3 (COND_EXPR, type, TREE_OPERAND (expr, 0),
+			   VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1)))
+			   ? TREE_OPERAND (expr, 1)
+			   : convert (type, TREE_OPERAND (expr, 1)),
+			   VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 2)))
+			   ? TREE_OPERAND (expr, 2)
+			   : convert (type, TREE_OPERAND (expr, 2)));
 
 	default:
 	  break;
@@ -860,6 +930,8 @@ convert_to_integer (tree type, tree expr)
 	  expr = build1 (FIX_TRUNC_EXPR, type, expr);
 	  if (check == NULL)
 	    return expr;
+	  if (!dofold)
+	    return build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
 	  return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
 	}
       else
@@ -869,6 +941,10 @@ convert_to_integer (tree type, tree expr)
       return build1 (FIXED_CONVERT_EXPR, type, expr);
 
     case COMPLEX_TYPE:
+      if (!dofold)
+	return convert (type,
+			build1 (REALPART_EXPR,
+				TREE_TYPE (TREE_TYPE (expr)), expr));
       return convert (type,
 		      fold_build1 (REALPART_EXPR,
 				   TREE_TYPE (TREE_TYPE (expr)), expr));
@@ -889,11 +965,42 @@ convert_to_integer (tree type, tree expr)
     }
 }
 
-/* Convert EXPR to the complex type TYPE in the usual ways.  */
+/* Convert EXPR to some integer (or enum) type TYPE.
+
+   EXPR must be pointer, integer, discrete (enum, char, or bool), float,
+   fixed-point or vector; in other cases error is called.
+
+   The result of this is always supposed to be a newly created tree node
+   not in use in any existing structure.  */
 
 tree
-convert_to_complex (tree type, tree expr)
+convert_to_integer (tree type, tree expr)
+{
+  return convert_to_integer_1 (type, expr, true);
+}
+
+/* Convert EXPR to some integer (or enum) type TYPE.
+
+   EXPR must be pointer, integer, discrete (enum, char, or bool), float,
+   fixed-point or vector; in other cases error is called.
+
+   The result of this is always supposed to be a newly created tree node
+   not in use in any existing structure.  The tree node isn't folded,
+   beside EXPR is of constant class.  */
+
+tree
+convert_to_integer_nofold (tree type, tree expr)
+{
+  return convert_to_integer_1 (type, expr, CONSTANT_CLASS_P (expr));
+}
+
+/* Convert EXPR to the complex type TYPE in the usual ways.  If FOLD_P is
+   true, try to fold the expression.  */
+
+static tree
+convert_to_complex_1 (tree type, tree expr, bool fold_p)
 {
+  location_t loc = EXPR_LOCATION (expr);
   tree subtype = TREE_TYPE (type);
 
   switch (TREE_CODE (TREE_TYPE (expr)))
@@ -914,43 +1021,63 @@ convert_to_complex (tree type, tree expr)
 	  return expr;
 	else if (TREE_CODE (expr) == COMPOUND_EXPR)
 	  {
-	    tree t = convert_to_complex (type, TREE_OPERAND (expr, 1));
+	    tree t = convert_to_complex_1 (type, TREE_OPERAND (expr, 1),
+					   fold_p);
 	    if (t == TREE_OPERAND (expr, 1))
 	      return expr;
 	    return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR,
 			       TREE_TYPE (t), TREE_OPERAND (expr, 0), t);
-	  }    
+	  }
 	else if (TREE_CODE (expr) == COMPLEX_EXPR)
-	  return fold_build2 (COMPLEX_EXPR, type,
-			      convert (subtype, TREE_OPERAND (expr, 0)),
-			      convert (subtype, TREE_OPERAND (expr, 1)));
+	  return maybe_fold_build2_loc (fold_p, loc, COMPLEX_EXPR, type,
+					convert (subtype,
+						 TREE_OPERAND (expr, 0)),
+					convert (subtype,
+						 TREE_OPERAND (expr, 1)));
 	else
 	  {
 	    expr = save_expr (expr);
-	    return
-	      fold_build2 (COMPLEX_EXPR, type,
-			   convert (subtype,
-				    fold_build1 (REALPART_EXPR,
-						 TREE_TYPE (TREE_TYPE (expr)),
-						 expr)),
-			   convert (subtype,
-				    fold_build1 (IMAGPART_EXPR,
-						 TREE_TYPE (TREE_TYPE (expr)),
-						 expr)));
+	    tree realp = maybe_fold_build1_loc (fold_p, loc, REALPART_EXPR,
+						TREE_TYPE (TREE_TYPE (expr)),
+						expr);
+	    tree imagp = maybe_fold_build1_loc (fold_p, loc, IMAGPART_EXPR,
+						TREE_TYPE (TREE_TYPE (expr)),
+						expr);
+	    return maybe_fold_build2_loc (fold_p, loc, COMPLEX_EXPR, type,
+					  convert (subtype, realp),
+					  convert (subtype, imagp));
 	  }
       }
 
     case POINTER_TYPE:
     case REFERENCE_TYPE:
       error ("pointer value used where a complex was expected");
-      return convert_to_complex (type, integer_zero_node);
+      return convert_to_complex_1 (type, integer_zero_node, fold_p);
 
     default:
       error ("aggregate value used where a complex was expected");
-      return convert_to_complex (type, integer_zero_node);
+      return convert_to_complex_1 (type, integer_zero_node, fold_p);
     }
 }
 
+/* A wrapper around convert_to_complex_1 that always folds the
+   expression.  */
+
+tree
+convert_to_complex (tree type, tree expr)
+{
+  return convert_to_complex_1 (type, expr, true);
+}
+
+/* A wrapper around convert_to_complex_1 that only folds the
+   expression if it is CONSTANT_CLASS_P.  */
+
+tree
+convert_to_complex_nofold (tree type, tree expr)
+{
+  return convert_to_complex_1 (type, expr, CONSTANT_CLASS_P (expr));
+}
+
 /* Convert EXPR to the vector type TYPE in the usual ways.  */
 
 tree
diff --git a/gcc/convert.h b/gcc/convert.h
index f2e4a65..7cc3168 100644
--- a/gcc/convert.h
+++ b/gcc/convert.h
@@ -21,10 +21,14 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_CONVERT_H
 
 extern tree convert_to_integer (tree, tree);
+extern tree convert_to_integer_nofold (tree, tree);
 extern tree convert_to_pointer (tree, tree);
+extern tree convert_to_pointer_nofold (tree, tree);
 extern tree convert_to_real (tree, tree);
+extern tree convert_to_real_nofold (tree, tree);
 extern tree convert_to_fixed (tree, tree);
 extern tree convert_to_complex (tree, tree);
+extern tree convert_to_complex_nofold (tree, tree);
 extern tree convert_to_vector (tree, tree);
 
 #endif /* GCC_CONVERT_H */
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 0b7d143..536989b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4747,7 +4747,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 	  tree cmp_type = build_same_sized_truth_vector_type (arg1_type);
 	  arg1 = build2 (NE_EXPR, cmp_type, arg1, build_zero_cst (arg1_type));
 	}
-      return fold_build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
+      return build3_loc (loc, VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
     }
 
   /* [expr.cond]
@@ -5151,9 +5151,6 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 
  valid_operands:
   result = build3_loc (loc, COND_EXPR, result_type, arg1, arg2, arg3);
-  if (!cp_unevaluated_operand)
-    /* Avoid folding within decltype (c++/42013) and noexcept.  */
-    result = fold_if_not_in_template (result);
 
   /* We can't use result_type below, as fold might have returned a
      throw_expr.  */
@@ -5689,8 +5686,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
 		 decaying an enumerator to its value.  */
 	      if (complain & tf_warning)
 		warn_logical_operator (loc, code, boolean_type_node,
-				       code_orig_arg1, arg1,
-				       code_orig_arg2, arg2);
+				       code_orig_arg1, fold (arg1),
+				       code_orig_arg2, fold (arg2));
 
 	      arg2 = convert_like (conv, arg2, complain);
 	    }
@@ -5728,7 +5725,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
     case TRUTH_OR_EXPR:
       if (complain & tf_warning)
 	warn_logical_operator (loc, code, boolean_type_node,
-			       code_orig_arg1, arg1, code_orig_arg2, arg2);
+			       code_orig_arg1, fold (arg1), code_orig_arg2, fold (arg2));
       /* Fall through.  */
     case GT_EXPR:
     case LT_EXPR:
@@ -5739,9 +5736,10 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
       if ((complain & tf_warning)
 	  && ((code_orig_arg1 == BOOLEAN_TYPE)
 	      ^ (code_orig_arg2 == BOOLEAN_TYPE)))
-	maybe_warn_bool_compare (loc, code, arg1, arg2);
+	maybe_warn_bool_compare (loc, code, fold (arg1),
+				 fold (arg2));
       if (complain & tf_warning && warn_tautological_compare)
-	warn_tautological_cmp (loc, code, arg1, arg2);
+	warn_tautological_cmp (loc, code, fold (arg1), fold (arg2));
       /* Fall through.  */
     case PLUS_EXPR:
     case MINUS_EXPR:
@@ -6495,7 +6493,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  imag = perform_implicit_conversion (TREE_TYPE (totype),
 					      imag, complain);
 	  expr = build2 (COMPLEX_EXPR, totype, real, imag);
-	  return fold_if_not_in_template (expr);
+	  return expr;
 	}
       expr = reshape_init (totype, expr, complain);
       expr = get_target_expr_sfinae (digest_init (totype, expr, complain),
@@ -6736,7 +6734,7 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
 		    "implicit conversion from %qT to %qT when passing "
 		    "argument to function",
 		    arg_type, double_type_node);
-      arg = convert_to_real (double_type_node, arg);
+      arg = convert_to_real_nofold (double_type_node, arg);
     }
   else if (NULLPTR_TYPE_P (arg_type))
     arg = null_pointer_node;
@@ -6981,7 +6979,7 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
   bitfield_type = is_bitfield_expr_with_lowered_type (val);
   if (bitfield_type 
       && TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type))
-    val = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type), val);
+    val = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type), val);
 
   if (val == error_mark_node)
     ;
@@ -7501,7 +7499,19 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
   gcc_assert (j <= nargs);
   nargs = j;
 
-  check_function_arguments (TREE_TYPE (fn), nargs, argarray);
+  /* Avoid to do argument-transformation, if warnings for format, and for
+     nonnull are disabled.  Just in case that at least one of them is active
+     the check_function_arguments function might warn about something.  */
+
+  if (warn_nonnull || warn_format || warn_suggest_attribute_format)
+    {
+      tree *fargs = (!nargs ? argarray
+			    : (tree *) alloca (nargs * sizeof (tree)));
+      for (j = 0; j < nargs; j++)
+	fargs[j] = maybe_constant_value (argarray[j]);
+
+      check_function_arguments (TREE_TYPE (fn), nargs, fargs);
+    }
 
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
@@ -7692,7 +7702,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
 		tsubst_flags_t complain)
 {
   tree fndecl;
-  int optimize_sav;
 
   /* Remember roughly where this call is.  */
   location_t loc = EXPR_LOC_OR_LOC (fn, input_location);
@@ -7704,9 +7713,18 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
   /* Check that arguments to builtin functions match the expectations.  */
   if (fndecl
       && DECL_BUILT_IN (fndecl)
-      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-      && !check_builtin_function_arguments (fndecl, nargs, argarray))
-    return error_mark_node;
+      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+    {
+      int i;
+
+      /* We need to take care that values to BUILT_IN_NORMAL
+         are reduced.  */
+      for (i = 0; i < nargs; i++)
+	argarray[i] = maybe_constant_value (argarray[i]);
+
+      if (!check_builtin_function_arguments (fndecl, nargs, argarray))
+	return error_mark_node;
+    }
 
     /* If it is a built-in array notation function, then the return type of
      the function is the element type of the array passed in as array 
@@ -7740,17 +7758,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
 	}
     }
 
-  /* Some built-in function calls will be evaluated at compile-time in
-     fold ().  Set optimize to 1 when folding __builtin_constant_p inside
-     a constexpr function so that fold_builtin_1 doesn't fold it to 0.  */
-  optimize_sav = optimize;
-  if (!optimize && fndecl && DECL_IS_BUILTIN_CONSTANT_P (fndecl)
-      && current_function_decl
-      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
-    optimize = 1;
-  fn = fold_if_not_in_template (fn);
-  optimize = optimize_sav;
-
   if (VOID_TYPE_P (TREE_TYPE (fn)))
     return fn;
 
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b123932..b5cf996 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -423,7 +423,7 @@ build_base_path (enum tree_code code,
 
 	  t = TREE_TYPE (TYPE_VFIELD (current_class_type));
 	  t = build_pointer_type (t);
-	  v_offset = convert (t, current_vtt_parm);
+	  v_offset = fold_convert (t, current_vtt_parm);
 	  v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
 	}
       else
@@ -556,8 +556,6 @@ build_simple_base_path (tree expr, tree binfo)
 	expr = build3 (COMPONENT_REF,
 		       cp_build_qualified_type (type, type_quals),
 		       expr, field, NULL_TREE);
-	expr = fold_if_not_in_template (expr);
-
 	/* Mark the expression const or volatile, as appropriate.
 	   Even though we've dealt with the type above, we still have
 	   to mark the expression itself.  */
@@ -1849,9 +1847,9 @@ determine_primary_bases (tree t)
 		 another hierarchy. As we're about to use it as a
 		 primary base, make sure the offsets match.  */
 	      delta = size_diffop_loc (input_location,
-				   convert (ssizetype,
+				   fold_convert (ssizetype,
 					    BINFO_OFFSET (base_binfo)),
-				   convert (ssizetype,
+				   fold_convert (ssizetype,
 					    BINFO_OFFSET (this_primary)));
 
 	      propagate_binfo_offsets (this_primary, delta);
@@ -1913,7 +1911,7 @@ determine_primary_bases (tree t)
 	     another hierarchy. As we're about to use it as a primary
 	     base, make sure the offsets match.  */
 	  delta = size_diffop_loc (input_location, ssize_int (0),
-			       convert (ssizetype, BINFO_OFFSET (primary)));
+			       fold_convert (ssizetype, BINFO_OFFSET (primary)));
 
 	  propagate_binfo_offsets (primary, delta);
 	}
@@ -2637,7 +2635,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
 	  if (virtual_offset
 	      || (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo)))
 	    {
-	      tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo));
+	      tree offset = fold_convert (ssizetype, BINFO_OFFSET (thunk_binfo));
 
 	      if (virtual_offset)
 		{
@@ -2645,7 +2643,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
 		     offset to be from there.  */
 		  offset = 
 		    size_diffop (offset,
-				 convert (ssizetype,
+				 fold_convert (ssizetype,
 					  BINFO_OFFSET (virtual_offset)));
 		}
 	      if (fixed_offset)
@@ -2734,8 +2732,8 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
     /* The `this' pointer needs to be adjusted from the declaration to
        the nearest virtual base.  */
     delta = size_diffop_loc (input_location,
-			 convert (ssizetype, BINFO_OFFSET (virtual_base)),
-			 convert (ssizetype, BINFO_OFFSET (first_defn)));
+			 fold_convert (ssizetype, BINFO_OFFSET (virtual_base)),
+			 fold_convert (ssizetype, BINFO_OFFSET (first_defn)));
   else if (lost)
     /* If the nearest definition is in a lost primary, we don't need an
        entry in our vtable.  Except possibly in a constructor vtable,
@@ -2747,9 +2745,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
        BINFO to pointing at the base where the final overrider
        appears.  */
     delta = size_diffop_loc (input_location,
-			 convert (ssizetype,
+			 fold_convert (ssizetype,
 				  BINFO_OFFSET (TREE_VALUE (overrider))),
-			 convert (ssizetype, BINFO_OFFSET (binfo)));
+			 fold_convert (ssizetype, BINFO_OFFSET (binfo)));
 
   modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
 
@@ -3471,7 +3469,7 @@ check_bitfield_decl (tree field)
 
   if (w != error_mark_node)
     {
-      DECL_SIZE (field) = convert (bitsizetype, w);
+      DECL_SIZE (field) = fold_convert (bitsizetype, w);
       DECL_BIT_FIELD (field) = 1;
       return true;
     }
@@ -4316,8 +4314,8 @@ layout_nonempty_base_or_field (record_layout_info rli,
        OFFSET.  */
     propagate_binfo_offsets (binfo,
 			     size_diffop_loc (input_location,
-					  convert (ssizetype, offset),
-					  convert (ssizetype,
+					  fold_convert (ssizetype, offset),
+					  fold_convert (ssizetype,
 						   BINFO_OFFSET (binfo))));
 }
 
@@ -4364,7 +4362,7 @@ layout_empty_base (record_layout_info rli, tree binfo,
       /* That didn't work.  Now, we move forward from the next
 	 available spot in the class.  */
       atend = true;
-      propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
+      propagate_binfo_offsets (binfo, fold_convert (ssizetype, eoc));
       while (1)
 	{
 	  if (!layout_conflict_p (binfo,
@@ -5978,9 +5976,9 @@ propagate_binfo_offsets (tree binfo, tree offset)
 
   /* Update BINFO's offset.  */
   BINFO_OFFSET (binfo)
-    = convert (sizetype,
+    = fold_convert (sizetype,
 	       size_binop (PLUS_EXPR,
-			   convert (ssizetype, BINFO_OFFSET (binfo)),
+			   fold_convert (ssizetype, BINFO_OFFSET (binfo)),
 			   offset));
 
   /* Find the primary base class.  */
@@ -6185,7 +6183,7 @@ include_empty_classes (record_layout_info rli)
 	= size_binop (PLUS_EXPR,
 		      rli->bitpos,
 		      size_binop (MULT_EXPR,
-				  convert (bitsizetype,
+				  fold_convert (bitsizetype,
 					   size_binop (MINUS_EXPR,
 						       eoc, rli_size)),
 				  bitsize_int (BITS_PER_UNIT)));
@@ -6459,7 +6457,7 @@ layout_class_type (tree t, tree *virtuals_p)
       eoc = end_of_class (t, /*include_virtuals_p=*/0);
       TYPE_SIZE_UNIT (base_t)
 	= size_binop (MAX_EXPR,
-		      convert (sizetype,
+		      fold_convert (sizetype,
 			       size_binop (CEIL_DIV_EXPR,
 					   rli_size_so_far (rli),
 					   bitsize_int (BITS_PER_UNIT))),
@@ -6468,7 +6466,7 @@ layout_class_type (tree t, tree *virtuals_p)
 	= size_binop (MAX_EXPR,
 		      rli_size_so_far (rli),
 		      size_binop (MULT_EXPR,
-				  convert (bitsizetype, eoc),
+				  fold_convert (bitsizetype, eoc),
 				  bitsize_int (BITS_PER_UNIT)));
       TYPE_ALIGN (base_t) = rli->record_align;
       TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
@@ -9304,7 +9302,7 @@ build_vbase_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
       /* Figure out where we can find this vbase offset.  */
       delta = size_binop (MULT_EXPR,
 			  vid->index,
-			  convert (ssizetype,
+			  fold_convert (ssizetype,
 				   TYPE_SIZE_UNIT (vtable_entry_type)));
       if (vid->primary_vtbl_p)
 	BINFO_VPTR_FIELD (b) = delta;
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 51fae5a..eefe322 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1037,6 +1037,8 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
   force_folding_builtin_constant_p = true;
   new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
 					CALL_EXPR_FN (t), nargs, args);
+  /* Fold away the NOP_EXPR from fold_builtin_n.  */
+  new_call = fold (new_call);
   force_folding_builtin_constant_p = save_ffbcp;
   VERIFY_CONSTANT (new_call);
   return new_call;
@@ -1277,6 +1279,15 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
       ctx->values->put (new_ctx.object, ctor);
       ctx = &new_ctx;
     }
+  else if (DECL_BY_REFERENCE (DECL_RESULT (fun))
+	   && TREE_CODE (t) != AGGR_INIT_EXPR)
+    {
+      /* convert_to_void stripped our AGGR_INIT_EXPR, in which case we don't
+	 care about a constant value.  */
+      gcc_assert (ctx->quiet && !ctx->object);
+      *non_constant_p = true;
+      return t;
+    }
 
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
@@ -2542,6 +2553,17 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
   tree orig_op0 = TREE_OPERAND (t, 0);
   bool empty_base = false;
 
+  /* We can handle a MEM_REF like an INDIRECT_REF, if MEM_REF's second
+     operand is an integer-zero.  Otherwise reject the MEM_REF for now.  */
+
+  if (TREE_CODE (t) == MEM_REF
+      && (!TREE_OPERAND (t, 1) || !integer_zerop (TREE_OPERAND (t, 1))))
+    {
+      gcc_assert (ctx->quiet);
+      *non_constant_p = true;
+      return t;
+    }
+
   /* First try to simplify it directly.  */
   tree r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), orig_op0,
 				  &empty_base);
@@ -3075,6 +3097,8 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
   if (TREE_CODE (op00) != ADDR_EXPR)
     return NULL_TREE;
 
+  op01 = cxx_eval_constant_expression (ctx, op01, lval,
+				       non_constant_p, overflow_p);
   op00 = TREE_OPERAND (op00, 0);
 
   /* &A[i] p+ j => &A[i + j] */
@@ -3112,6 +3136,26 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
   return NULL_TREE;
 }
 
+/* Reduce a SIZEOF_EXPR to its value.  */
+
+tree
+fold_sizeof_expr (tree t)
+{
+  tree r;
+  if (SIZEOF_EXPR_TYPE_P (t))
+    r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+				    SIZEOF_EXPR, false);
+  else if (TYPE_P (TREE_OPERAND (t, 0)))
+    r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+				    false);
+  else
+    r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
+				    false);
+  if (r == error_mark_node)
+    r = size_one_node;
+  return r;
+}
+
 /* Attempt to reduce the expression T to a constant value.
    On failure, issue diagnostic and return error_mark_node.  */
 /* FIXME unify with c_fully_fold */
@@ -3335,6 +3379,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       /* These differ from cxx_eval_unary_expression in that this doesn't
 	 check for a constant operand or result; an address can be
 	 constant without its operand being, and vice versa.  */
+    case MEM_REF:
     case INDIRECT_REF:
       r = cxx_eval_indirect_ref (ctx, t, lval,
 				 non_constant_p, overflow_p);
@@ -3372,17 +3417,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       break;
 
     case SIZEOF_EXPR:
-      if (SIZEOF_EXPR_TYPE_P (t))
-	r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
-					SIZEOF_EXPR, false);
-      else if (TYPE_P (TREE_OPERAND (t, 0)))
-	r = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0), SIZEOF_EXPR,
-					false);
-      else
-	r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0), SIZEOF_EXPR,
-					false);
-      if (r == error_mark_node)
-	r = size_one_node;
+      r = fold_sizeof_expr (t);
       VERIFY_CONSTANT (r);
       break;
 
@@ -3540,8 +3575,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
     case NOP_EXPR:
+    case UNARY_PLUS_EXPR:
       {
+	enum tree_code tcode = TREE_CODE (t);
 	tree oldop = TREE_OPERAND (t, 0);
+
 	tree op = cxx_eval_constant_expression (ctx, oldop,
 						lval,
 						non_constant_p, overflow_p);
@@ -3561,11 +3599,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 	    *non_constant_p = true;
 	    return t;
 	  }
-	if (op == oldop)
+	if (op == oldop && tcode != UNARY_PLUS_EXPR)
 	  /* We didn't fold at the top so we could check for ptr-int
 	     conversion.  */
 	  return fold (t);
-	r = fold_build1 (TREE_CODE (t), type, op);
+	if (tcode == UNARY_PLUS_EXPR)
+	  r = fold_convert (TREE_TYPE (t), op);
+	else
+	  r = fold_build1 (tcode, type, op);
 	/* Conversion of an out-of-range value has implementation-defined
 	   behavior; the language considers it different from arithmetic
 	   overflow, which is undefined.  */
@@ -3833,12 +3874,86 @@ cxx_constant_value (tree t, tree decl)
   return cxx_eval_outermost_constant_expr (t, false, true, decl);
 }
 
+/* Helper routine for fold_simple function.  Either return simplified
+   expression T, otherwise NULL_TREE.
+   In contrast to cp_fully_fold, and to maybe_constant_value, we try to fold
+   even if we are within template-declaration.  So be careful on call, as in
+   such case types can be undefined.  */
+
+static tree
+fold_simple_1 (tree t)
+{
+  tree op1;
+  enum tree_code code = TREE_CODE (t);
+
+  switch (code)
+    {
+    case INTEGER_CST:
+    case REAL_CST:
+    case VECTOR_CST:
+    case FIXED_CST:
+    case COMPLEX_CST:
+      return t;
+
+    case SIZEOF_EXPR:
+      return fold_sizeof_expr (t);
+
+    case ABS_EXPR:
+    case CONJ_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case NEGATE_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case NOP_EXPR:
+    case VIEW_CONVERT_EXPR:
+    case CONVERT_EXPR:
+    case FLOAT_EXPR:
+    case FIX_TRUNC_EXPR:
+    case FIXED_CONVERT_EXPR:
+    case ADDR_SPACE_CONVERT_EXPR:
+
+      op1 = TREE_OPERAND (t, 0);
+
+      t = const_unop (code, TREE_TYPE (t), op1);
+      if (!t)
+	return NULL_TREE;
+
+      if (CONVERT_EXPR_CODE_P (code)
+	  && TREE_OVERFLOW_P (t) && !TREE_OVERFLOW_P (op1))
+	TREE_OVERFLOW (t) = false;
+      return t;
+
+    default:
+      return NULL_TREE;
+    }
+}
+
+/* If T is a simple constant expression, returns its simplified value.
+   Otherwise returns T.  In contrast to maybe_constant_value do we
+   simplify only few operations on constant-expressions, and we don't
+   try to simplify constexpressions.  */
+
+tree
+fold_simple (tree t)
+{
+  tree r = NULL_TREE;
+  if (processing_template_decl)
+    return t;
+
+  r = fold_simple_1 (t);
+  if (!r)
+    r = t;
+
+  return r;
+}
+
 /* If T is a constant expression, returns its reduced value.
    Otherwise, if T does not have TREE_CONSTANT set, returns T.
    Otherwise, returns a version of T without TREE_CONSTANT.  */
 
-tree
-maybe_constant_value (tree t, tree decl)
+static tree
+maybe_constant_value_1 (tree t, tree decl)
 {
   tree r;
 
@@ -3864,6 +3979,56 @@ maybe_constant_value (tree t, tree decl)
   return r;
 }
 
+/* If T is a constant expression, returns its reduced value.
+   Otherwise, if T does not have TREE_CONSTANT set, returns T.
+   Otherwise, returns a version of T without TREE_CONSTANT.  */
+
+tree
+maybe_constant_value (tree t, tree decl)
+{
+  tree ret;
+  hash_map<tree, tree> *ctx = (scope_chain ? scope_chain->fold_map : NULL);
+  hash_map<tree, tree> *cv = (scope_chain ? scope_chain->cv_map : NULL);
+
+  /* If current scope has a hash_map, but it was for different CFUN,
+     then destroy hash_map to avoid issues with ggc_collect.  */
+  if ((cv || ctx) && scope_chain->act_cfun != cfun)
+    {
+      if (ctx)
+	delete ctx;
+      if (cv)
+	delete cv;
+      ctx = NULL;
+      scope_chain->act_cfun = NULL;
+      scope_chain->fold_map = NULL;
+      scope_chain->cv_map = NULL;
+    }
+  if (cv && scope_chain && cfun)
+    {
+      cv = scope_chain->cv_map = new hash_map <tree, tree>;
+      scope_chain->act_cfun = cfun;
+    }
+
+  if (cv)
+    {
+      tree *slot = cv->get (t);
+      if (slot && *slot)
+	return *slot;
+    }
+
+  ret = maybe_constant_value_1 (t, decl);
+
+  if (cv)
+    {
+      /* We don't need to cache RET, as it is a
+	 constant-value if it differs.  */
+      tree *slot = &cv->get_or_insert (t);
+      *slot = ret;
+    }
+
+  return ret;
+}
+
 /* Like maybe_constant_value but first fully instantiate the argument.
 
    Note: this is equivalent to instantiate_non_dependent_expr_sfinae
@@ -3929,6 +4094,8 @@ fold_non_dependent_expr (tree t)
 tree
 maybe_constant_init (tree t, tree decl)
 {
+  if (!t)
+    return t;
   if (TREE_CODE (t) == EXPR_STMT)
     t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == CONVERT_EXPR
@@ -4039,6 +4206,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
       /* We can see a FIELD_DECL in a pointer-to-member expression.  */
     case FIELD_DECL:
     case PARM_DECL:
+    case RESULT_DECL:
     case USING_DECL:
     case USING_STMT:
     case PLACEHOLDER_EXPR:
@@ -4627,6 +4795,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
       /* We can see these in statement-expressions.  */
       return true;
 
+    case EMPTY_CLASS_EXPR:
+      return false;
+
     default:
       if (objc_is_property_ref (t))
 	return false;
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
index 9fd348c..e967c72 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -1382,7 +1382,12 @@ build_array_notation_ref (location_t loc, tree array, tree start, tree length,
     
   if (!stride) 
     stride = build_one_cst (ptrdiff_type_node);
-  
+
+  stride = maybe_constant_value (stride);
+  length = maybe_constant_value (length);
+  if (start)
+    start = maybe_constant_value (start);
+
   /* When dealing with templates, triplet type-checking will be done in pt.c 
      after type substitution.  */
   if (processing_template_decl 
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index e4b50e5..88baa40 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -41,7 +41,9 @@ along with GCC; see the file COPYING3.  If not see
 /* Forward declarations.  */
 
 static tree cp_genericize_r (tree *, int *, void *);
+static tree cp_fold_r (tree *, int *, void *);
 static void cp_genericize_tree (tree*);
+static tree cp_fold (tree, hash_map<tree, tree> *);
 
 /* Local declarations.  */
 
@@ -181,13 +183,13 @@ genericize_eh_spec_block (tree *stmt_p)
 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
 
 static void
-genericize_if_stmt (tree *stmt_p)
+genericize_if_stmt (tree *stmt_p, hash_map<tree, tree> *fold_hash)
 {
   tree stmt, cond, then_, else_;
   location_t locus = EXPR_LOCATION (*stmt_p);
 
   stmt = *stmt_p;
-  cond = IF_COND (stmt);
+  cond = cp_fold (IF_COND (stmt), fold_hash);
   then_ = THEN_CLAUSE (stmt);
   else_ = ELSE_CLAUSE (stmt);
 
@@ -916,9 +918,76 @@ struct cp_genericize_data
   vec<tree> bind_expr_stack;
   struct cp_genericize_omp_taskreg *omp_ctx;
   tree try_block;
+  hash_map<tree, tree> *fold_hash;
   bool no_sanitize_p;
 };
 
+/* Perform any pre-gimplification folding of C++ front end trees to
+   GENERIC.
+   Note:  The folding of none-omp cases is something to move into
+     the middle-end.  As for now we have most foldings only on GENERIC
+     in fold-const, we need to perform this before transformation to
+     GIMPLE-form.  */
+
+static tree
+cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data)
+{
+  tree stmt;
+  struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
+  enum tree_code code;
+
+  *stmt_p = stmt = cp_fold (*stmt_p, wtd->fold_hash);
+
+  code = TREE_CODE (stmt);
+  if (code == OMP_FOR || code == OMP_SIMD || code == OMP_DISTRIBUTE
+      || code == OMP_TASKLOOP || code == CILK_FOR || code == CILK_SIMD)
+    {
+      tree x;
+      int i, n;
+
+      cp_walk_tree (&OMP_FOR_BODY (stmt), cp_fold_r, data, NULL);
+      cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_fold_r, data, NULL);
+      cp_walk_tree (&OMP_FOR_INIT (stmt), cp_fold_r, data, NULL);
+      x = OMP_FOR_COND (stmt);
+      if (x && TREE_CODE_CLASS (TREE_CODE (x)) == tcc_comparison)
+	{
+	  cp_walk_tree (&TREE_OPERAND (x, 0), cp_fold_r, data, NULL);
+	  cp_walk_tree (&TREE_OPERAND (x, 1), cp_fold_r, data, NULL);
+	} 
+      else if (x && TREE_CODE (x) == TREE_VEC)
+	{
+	  n = TREE_VEC_LENGTH (x);
+	  for (i = 0; i < n; i++)
+	    {
+	      tree o = TREE_VEC_ELT (x, i);
+	      if (o && TREE_CODE_CLASS (TREE_CODE (o)) == tcc_comparison)
+		cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
+	    }
+	}
+      x = OMP_FOR_INCR (stmt);
+      if (x && TREE_CODE (x) == TREE_VEC)
+	{
+	  n = TREE_VEC_LENGTH (x);
+	  for (i = 0; i < n; i++)
+	    {
+	      tree o = TREE_VEC_ELT (x, i);
+	      if (o && TREE_CODE (o) == MODIFY_EXPR)
+		o = TREE_OPERAND (o, 1);
+	      if (o && (TREE_CODE (o) == PLUS_EXPR || TREE_CODE (o) == MINUS_EXPR
+			|| TREE_CODE (o) == POINTER_PLUS_EXPR))
+		{
+		  cp_walk_tree (&TREE_OPERAND (o, 0), cp_fold_r, data, NULL);
+		  cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
+		}
+	    }
+	}
+      cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_fold_r, data, NULL);
+      *walk_subtrees = 0;
+    }
+
+  return NULL;
+}
+
 /* Perform any pre-gimplification lowering of C++ front end trees to
    GENERIC.  */
 
@@ -978,7 +1047,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       if (__builtin_expect (wtd->omp_ctx != NULL, 0)
 	  && omp_var_to_track (TREE_OPERAND (stmt, 0)))
 	omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
-      *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
+      *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
       *walk_subtrees = 0;
     }
   else if (TREE_CODE (stmt) == RETURN_EXPR
@@ -1058,7 +1127,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
 
   else if (TREE_CODE (stmt) == IF_STMT)
     {
-      genericize_if_stmt (stmt_p);
+      genericize_if_stmt (stmt_p, wtd->fold_hash);
       /* *stmt_p has changed, tail recurse to handle it again.  */
       return cp_genericize_r (stmt_p, walk_subtrees, data);
     }
@@ -1307,6 +1376,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
 					      SIZEOF_EXPR, false);
       if (*stmt_p == error_mark_node)
 	*stmt_p = size_one_node;
+      *stmt_p = cp_fold (*stmt_p,  wtd->fold_hash);
       return NULL;
     }
   else if ((flag_sanitize
@@ -1349,12 +1419,15 @@ cp_genericize_tree (tree* t_p)
 {
   struct cp_genericize_data wtd;
 
+  wtd.fold_hash = new hash_map<tree, tree>;
   wtd.p_set = new hash_set<tree>;
   wtd.bind_expr_stack.create (0);
   wtd.omp_ctx = NULL;
   wtd.try_block = NULL_TREE;
   wtd.no_sanitize_p = false;
   cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
+  cp_walk_tree (t_p, cp_fold_r, &wtd, NULL);
+  delete wtd.fold_hash;
   delete wtd.p_set;
   wtd.bind_expr_stack.release ();
   if (flag_sanitize & SANITIZE_VPTR)
@@ -1782,3 +1855,472 @@ cxx_omp_disregard_value_expr (tree decl, bool shared)
 	 && DECL_LANG_SPECIFIC (decl)
 	 && DECL_OMP_PRIVATIZED_MEMBER (decl);
 }
+
+/* Callback for walk_tree, looking for LABEL_EXPR.  Return *TP if it is
+   a LABEL_EXPR; otherwise return NULL_TREE.  Do not check the subtrees
+   of GOTO_EXPR.  */
+
+static tree
+contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+{
+  switch (TREE_CODE (*tp))
+    {
+    case LABEL_EXPR:
+      return *tp;
+
+    case GOTO_EXPR:
+      *walk_subtrees = 0;
+
+      /* ... fall through ...  */
+
+    default:
+      return NULL_TREE;
+    }
+}
+
+/* Return whether the sub-tree ST contains a label which is accessible from
+   outside the sub-tree.  */
+
+static bool
+contains_label_p (tree st)
+{
+  return
+   walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE;
+}
+
+/* Perform folding on expression X.  */
+
+tree
+cp_fully_fold (tree x)
+{
+  hash_map<tree, tree> *ctx = (scope_chain ? scope_chain->fold_map : NULL);
+  hash_map<tree, tree> *cv = (scope_chain ? scope_chain->cv_map : NULL);
+
+  /* If current scope has a hash_map, but it was for different CFUN,
+     then destroy hash_map to avoid issues with ggc_collect.  */
+  if ((cv || ctx) && scope_chain->act_cfun != cfun)
+    {
+      if (ctx)
+	delete ctx;
+      if (cv)
+	delete cv;
+      ctx = NULL;
+      scope_chain->act_cfun = NULL;
+      scope_chain->fold_map = NULL;
+      scope_chain->cv_map = NULL;
+    }
+
+  /* If there is no hash_map, but there is a scope, and a set CFUN,
+     then create the hash_map for scope.  */
+  if (!ctx && scope_chain && cfun)
+    {
+      ctx = scope_chain->fold_map = new hash_map <tree, tree>;
+      scope_chain->act_cfun = cfun;
+    }
+  /* Otherwise if there is no hash_map, use for folding temporary
+     hash_map.  */
+  else if (!ctx)
+    {
+      hash_map<tree, tree> fold_hash;
+      return cp_fold (x, &fold_hash);
+    }
+
+  return cp_fold (x, ctx);
+}
+
+/*  This function tries to fold given expression X in GENERIC-form.
+    For performance-reason, and for avoiding endless-recursion the
+    function uses given tree-hash FOLD_HASH.
+    If FOLD_HASH is 0, or we are processing within template-declaration,
+    or X is no valid expression, or has no valid type, we don't fold at all.
+    For performance-reason we don't hash on expressions representing a
+    declaration, or being of constant-class.
+    Function returns X, or its folded variant.  */
+
+static tree
+cp_fold (tree x, hash_map<tree, tree> *fold_hash)
+{
+  tree *slot, op0, op1, op2, op3;
+  tree org_x = x, r = NULL_TREE;
+  enum tree_code code;
+  location_t loc;
+
+  if (!x || x == error_mark_node)
+    return x;
+
+  if (!fold_hash
+      || processing_template_decl
+      || (EXPR_P (x) && !TREE_TYPE (x)))
+    return x;
+
+  /* Don't even try to hash on DECLs or constants.  */
+  if (DECL_P (x) || CONSTANT_CLASS_P (x))
+    return x;
+
+  slot = fold_hash->get (x);
+  if (slot && *slot)
+    return *slot;
+
+  code = TREE_CODE (x);
+  switch (code)
+    {
+    case SIZEOF_EXPR:
+      x = fold_sizeof_expr (x);
+      break;
+
+    case VIEW_CONVERT_EXPR:
+    case CONVERT_EXPR:
+    case NOP_EXPR:
+
+      if (VOID_TYPE_P (TREE_TYPE (x)))
+	return x;
+
+      if (!TREE_OPERAND (x, 0)
+	  || TREE_CODE (TREE_OPERAND (x, 0)) == NON_LVALUE_EXPR)
+	return x;
+
+      loc = EXPR_LOCATION (x);
+      op0 = TREE_OPERAND (x, 0);
+
+      if (TREE_CODE (x) == NOP_EXPR
+	  && TREE_OVERFLOW_P (op0)
+	  && TREE_TYPE (x) == TREE_TYPE (op0))
+	return x;
+
+      op0 = cp_fold (op0, fold_hash);
+
+      if (op0 != TREE_OPERAND (x, 0))
+        x = build1_loc (loc, code, TREE_TYPE (x), op0);
+
+      x = fold (x);
+
+      /* Conversion of an out-of-range value has implementation-defined
+	 behavior; the language considers it different from arithmetic
+	 overflow, which is undefined.  */
+      if (TREE_CODE (op0) == INTEGER_CST
+	  && TREE_OVERFLOW_P (x) && !TREE_OVERFLOW_P (op0))
+	TREE_OVERFLOW (x) = false;
+      
+      break;
+
+    case ALIGNOF_EXPR:
+    case SAVE_EXPR:
+    case ADDR_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case CONJ_EXPR:
+    case FIX_TRUNC_EXPR:
+    case FLOAT_EXPR:
+    case NEGATE_EXPR:
+    case ABS_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case FIXED_CONVERT_EXPR:
+    case UNARY_PLUS_EXPR:
+    case CLEANUP_POINT_EXPR:
+    case INDIRECT_REF:
+    /* case NON_LVALUE_EXPR: */
+    case RETURN_EXPR:
+    case EXPR_STMT:
+    case STMT_EXPR:
+    case GOTO_EXPR:
+    case EXIT_EXPR:
+    case LOOP_EXPR:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+
+      if (op0 != TREE_OPERAND (x, 0))
+        x = build1_loc (loc, code, TREE_TYPE (x), op0);
+
+      x = fold (x);
+
+      gcc_assert (TREE_CODE (x) != COND_EXPR
+		  || !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))));
+      break;
+
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case INIT_EXPR:
+
+	loc = EXPR_LOCATION (x);
+	op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+	op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+
+	if (TREE_OPERAND (x, 0) != op0 || TREE_OPERAND (x, 1) != op1)
+	  x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
+
+	break;
+
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case COMPOUND_EXPR:
+    case POINTER_PLUS_EXPR:
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case TRUNC_MOD_EXPR:
+    case CEIL_MOD_EXPR:
+    case ROUND_MOD_EXPR:
+    case RDIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case MIN_EXPR:
+    case MAX_EXPR:
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+    case LROTATE_EXPR:
+    case RROTATE_EXPR:
+    case BIT_AND_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_XOR_EXPR:
+    case LT_EXPR: case LE_EXPR:
+    case GT_EXPR: case GE_EXPR:
+    case EQ_EXPR: case NE_EXPR:
+    case UNORDERED_EXPR: case ORDERED_EXPR:
+    case UNLT_EXPR: case UNLE_EXPR:
+    case UNGT_EXPR: case UNGE_EXPR:
+    case UNEQ_EXPR: case LTGT_EXPR:
+    case RANGE_EXPR: case COMPLEX_EXPR:
+    case MODIFY_EXPR:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+      op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+      if ((code == COMPOUND_EXPR || code == MODIFY_EXPR)
+	  && ((op1 && TREE_SIDE_EFFECTS (op1))
+	       || (op0 && TREE_SIDE_EFFECTS (op0))))
+	break;
+      if (TREE_CODE (x) == COMPOUND_EXPR && !op0)
+	op0 = build_empty_stmt (loc);
+
+      if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
+	x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
+
+      x = fold (x);
+
+      if (TREE_CODE (x) == COMPOUND_EXPR && TREE_OPERAND (x, 0) == NULL_TREE
+	  && TREE_OPERAND (x, 1))
+	return TREE_OPERAND (x, 1);
+      break;
+
+    case VEC_COND_EXPR:
+    case COND_EXPR:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+
+      if (TREE_SIDE_EFFECTS (op0))
+	break;
+
+      op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+      op2 = cp_fold (TREE_OPERAND (x, 2), fold_hash);
+
+      if (TREE_CODE (op0) == INTEGER_CST)
+	{
+	  tree un;
+
+	  if (integer_zerop (op0))
+	    {
+	      un = op1;
+	      r = op2;
+	    }
+	  else
+	    {
+	      un = op2;
+	      r = op1;
+	    }
+
+          if ((!TREE_SIDE_EFFECTS (un) || !contains_label_p (un))
+              && (! VOID_TYPE_P (TREE_TYPE (r)) || VOID_TYPE_P (x)))
+            {
+	      if (CAN_HAVE_LOCATION_P (r)
+		  && EXPR_LOCATION (r) != loc
+		  && !(TREE_CODE (r) == SAVE_EXPR
+		       || TREE_CODE (r) == TARGET_EXPR
+		       || TREE_CODE (r) == BIND_EXPR))
+	        {
+		  r = copy_node (r);
+		  SET_EXPR_LOCATION (r, loc);
+	        }
+	      x = r;
+	    }
+
+	  break;
+	}
+
+      if (VOID_TYPE_P (TREE_TYPE (x)))
+	break;
+
+      x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
+
+      if (code != COND_EXPR)
+	x = fold (x);
+
+      break;
+
+    case CALL_EXPR:
+      {
+	int i, m, sv = optimize, nw = sv, changed = 0;
+	tree callee = get_callee_fndecl (x);
+
+	if (callee && DECL_BUILT_IN (callee) && !optimize
+	    && DECL_IS_BUILTIN_CONSTANT_P (callee)
+	    && current_function_decl
+	    && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+	  nw = 1;
+	optimize = nw;
+	r = fold (x);
+	optimize = sv;
+
+	if (TREE_CODE (r) != CALL_EXPR)
+	  {
+	    x = cp_fold (r, fold_hash);
+	    break;
+	  }
+
+	x = copy_node (x);
+
+	m = call_expr_nargs (x);
+	for (i = 0; i < m; i++)
+	  {
+	    r = cp_fold (CALL_EXPR_ARG (x, i), fold_hash);
+	    if (r != CALL_EXPR_ARG (x, i))
+	      changed = 1;
+	    CALL_EXPR_ARG (x, i) = r;
+	  }
+
+	optimize = nw;
+	r = fold (x);
+	optimize = sv;
+
+	if (TREE_CODE (r) != CALL_EXPR)
+	  {
+	    x = cp_fold (r, fold_hash);
+	    break;
+	  }
+
+	optimize = nw;
+
+	/* Invoke maybe_constant_value for functions being declared
+	   constexpr, and are no AGGR_INIT_EXPRs ...
+	   TODO:
+	   Due issues in maybe_constant_value for CALL_EXPR with
+	   arguments passed by reference, it is disabled.  */
+	if (callee && DECL_DECLARED_CONSTEXPR_P (callee))
+          r = maybe_constant_value (x);
+	optimize = sv;
+
+        if (TREE_CODE (r) != CALL_EXPR)
+	  {
+	    x = r;
+	    break;
+	  }
+
+	if (!changed)
+	  x = org_x;
+	break;
+      }
+
+    case BIND_EXPR:
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+      op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+      op2 = cp_fold (TREE_OPERAND (x, 2), fold_hash);
+
+      if (TREE_OPERAND (x, 0) != op0 || TREE_OPERAND (x, 1) != op1 || TREE_OPERAND (x, 2) != op2)
+	{
+	  x = copy_node (x);
+	  TREE_OPERAND (x, 0) = op0;
+	  TREE_OPERAND (x, 1) = op1;
+	  TREE_OPERAND (x, 2) = op2;
+	}
+      break;
+
+    case CONSTRUCTOR:
+      {
+	unsigned i;
+	constructor_elt *p;
+	vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (x);
+	FOR_EACH_VEC_SAFE_ELT (elts, i, p)
+	  p->value = cp_fold (p->value, fold_hash);
+	break;
+      }
+    case TREE_VEC:
+      {
+	bool changed = false;
+	vec<tree, va_gc> *vec = make_tree_vector ();
+	int i, n = TREE_VEC_LENGTH (x);
+	vec_safe_reserve (vec, n);
+
+	for (i = 0; i < n; i++)
+	  {
+	    tree op = cp_fold (TREE_VEC_ELT (x, i), fold_hash);
+	    vec->quick_push (op);
+	    if (op != TREE_VEC_ELT (x, i))
+	      changed = true;
+	  }
+
+	if (changed)
+	  {
+	    r = copy_node (x);
+	    for (i = 0; i < n; i++)
+	      TREE_VEC_ELT (r, i) = (*vec)[i];
+	    x = r;
+	  }
+
+	release_tree_vector (vec);
+      }
+
+      break;
+
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+      op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+      op2 = cp_fold (TREE_OPERAND (x, 2), fold_hash);
+      op3 = cp_fold (TREE_OPERAND (x, 3), fold_hash);
+
+      if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1)
+	  || op2 != TREE_OPERAND (x, 2) || op3 != TREE_OPERAND (x, 3))
+	x = build4_loc (loc, code, TREE_TYPE (x), op0, op1, op2, op3);
+
+      x = fold (x);
+      break;
+
+    case DECL_EXPR:
+
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+
+      if (op0 == TREE_OPERAND (x, 0))
+	break;
+
+      x = copy_node (x);
+      TREE_OPERAND (x, 0) = op0;
+      break;
+
+    default:
+      return org_x;
+    }
+
+  slot = &fold_hash->get_or_insert (org_x);
+  *slot = x;
+
+  /* Prevent that we try to fold an already folded result again.  */
+  if (x != org_x)
+    {
+      slot = &fold_hash->get_or_insert (x);
+      *slot = x;
+    }
+
+  return x;
+}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 828f268..cc4148e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1239,6 +1239,11 @@ struct GTY(()) saved_scope {
 
   hash_map<tree, tree> *GTY((skip)) x_local_specializations;
 
+  hash_map<tree, tree> *GTY((skip)) fold_map;
+  hash_map<tree, tree> *GTY((skip)) cv_map;
+
+  struct function *GTY((skip)) act_cfun;
+
   struct saved_scope *prev;
 };
 
@@ -6474,7 +6479,6 @@ extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
 	walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
 #define cp_walk_tree_without_duplicates(tp,func,data) \
 	walk_tree_without_duplicates_1 (tp, func, data, cp_walk_subtrees)
-extern tree fold_if_not_in_template		(tree);
 extern tree rvalue				(tree);
 extern tree convert_bitfield_to_declared_type   (tree);
 extern tree cp_save_expr			(tree);
@@ -6705,6 +6709,7 @@ extern tree cxx_omp_clause_dtor			(tree, tree);
 extern void cxx_omp_finish_clause		(tree, gimple_seq *);
 extern bool cxx_omp_privatize_by_reference	(const_tree);
 extern bool cxx_omp_disregard_value_expr	(tree, bool);
+extern tree cp_fully_fold			(tree);
 
 /* in name-lookup.c */
 extern void suggest_alternatives_for            (location_t, tree);
@@ -6796,12 +6801,14 @@ extern tree cxx_constant_value			(tree, tree = NULL_TREE);
 extern tree maybe_constant_value		(tree, tree = NULL_TREE);
 extern tree maybe_constant_init			(tree, tree = NULL_TREE);
 extern tree fold_non_dependent_expr		(tree);
+extern tree fold_simple				(tree);
 extern bool is_sub_constant_expr                (tree);
 extern bool reduced_constant_expression_p       (tree);
 extern bool is_instantiation_of_constexpr       (tree);
 extern bool var_in_constexpr_fn                 (tree);
 extern void explain_invalid_constexpr_fn        (tree);
 extern vec<tree> cx_error_context               (void);
+extern tree fold_sizeof_expr			(tree);
 
 /* In c-family/cilk.c */
 extern bool cilk_valid_spawn                    (tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index e764ee1..51b992c 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -53,7 +53,7 @@ static void diagnose_ref_binding (location_t, tree, tree, tree);
 
    Here is a list of all the functions that assume that widening and
    narrowing is always done with a NOP_EXPR:
-     In convert.c, convert_to_integer.
+     In convert.c, convert_to_integer[_nofold].
      In c-typeck.c, build_binary_op_nodefault (boolean ops),
 	and c_common_truthvalue_conversion.
      In expr.c: expand_expr, for operands of a MULT_EXPR.
@@ -240,7 +240,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
       gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
 		  == GET_MODE_SIZE (TYPE_MODE (type)));
 
-      return convert_to_pointer (type, expr);
+      return convert_to_pointer_nofold (type, expr);
     }
 
   if (type_unknown_p (expr))
@@ -608,6 +608,7 @@ cp_fold_convert (tree type, tree expr)
       conv = fold_convert (type, expr);
       conv = ignore_overflows (conv, expr);
     }
+
   return conv;
 }
 
@@ -633,7 +634,8 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
 
   if (TREE_TYPE (expr) == type)
     return expr;
-  
+  if (expr == error_mark_node)
+    return expr;
   result = cp_convert (type, expr, complain);
 
   if ((complain & tf_warning)
@@ -641,13 +643,14 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
     {
       tree folded = maybe_constant_value (expr);
       tree stripped = folded;
-      tree folded_result
+      tree folded_result;
+      folded_result
 	= folded != expr ? cp_convert (type, folded, complain) : result;
-
-      /* maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW in a
-	 NOP_EXPR so that it isn't TREE_CONSTANT anymore.  */
+      folded_result = cp_fully_fold (folded_result);
+      /* The maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW
+	 in a NOP_EXPR so that it isn't TREE_CONSTANT anymore.  */
       STRIP_NOPS (stripped);
-
+      folded = cp_fully_fold (folded);
       if (!TREE_OVERFLOW_P (stripped)
 	  && folded_result != error_mark_node)
 	warnings_for_convert_and_check (input_location, type, folded,
@@ -706,9 +709,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       /* For complex data types, we need to perform componentwise
 	 conversion.  */
       else if (TREE_CODE (type) == COMPLEX_TYPE)
-	return fold_if_not_in_template (convert_to_complex (type, e));
+	return convert_to_complex_nofold (type, e);
       else if (VECTOR_TYPE_P (type))
-	return fold_if_not_in_template (convert_to_vector (type, e));
+	return convert_to_vector (type, e);
       else if (TREE_CODE (e) == TARGET_EXPR)
 	{
 	  /* Don't build a NOP_EXPR of class type.  Instead, change the
@@ -721,7 +724,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 	  /* We shouldn't be treating objects of ADDRESSABLE type as
 	     rvalues.  */
 	  gcc_assert (!TREE_ADDRESSABLE (type));
-	  return fold_if_not_in_template (build_nop (type, e));
+	  return build_nop (type, e);
 	}
     }
 
@@ -799,7 +802,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 	  return cp_truthvalue_conversion (e);
 	}
 
-      converted = fold_if_not_in_template (convert_to_integer (type, e));
+      converted = convert_to_integer_nofold (type, e);
 
       /* Ignore any integer overflow caused by the conversion.  */
       return ignore_overflows (converted, e);
@@ -811,7 +814,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       return nullptr_node;
     }
   if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type))
-    return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain));
+    return cp_convert_to_pointer (type, e, complain);
   if (code == VECTOR_TYPE)
     {
       tree in_vtype = TREE_TYPE (e);
@@ -826,7 +829,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 		      in_vtype, type);
 	  return error_mark_node;
 	}
-      return fold_if_not_in_template (convert_to_vector (type, e));
+      return convert_to_vector (type, e);
     }
   if (code == REAL_TYPE || code == COMPLEX_TYPE)
     {
@@ -842,9 +845,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 		      TREE_TYPE (e));
 	}
       if (code == REAL_TYPE)
-	return fold_if_not_in_template (convert_to_real (type, e));
+	return convert_to_real_nofold (type, e);
       else if (code == COMPLEX_TYPE)
-	return fold_if_not_in_template (convert_to_complex (type, e));
+	return convert_to_complex_nofold (type, e);
     }
 
   /* New C++ semantics:  since assignment is now based on
@@ -1457,7 +1460,7 @@ convert (tree type, tree expr)
   intype = TREE_TYPE (expr);
 
   if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
-    return fold_if_not_in_template (build_nop (type, expr));
+    return build_nop (type, expr);
 
   return ocp_convert (type, expr, CONV_OLD_CONVERT,
 		      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
@@ -1475,13 +1478,11 @@ convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain)
   enum tree_code code = TREE_CODE (type);
 
   if (code == REFERENCE_TYPE)
-    return (fold_if_not_in_template
-	    (convert_to_reference (type, e, CONV_C_CAST, 0,
-				   NULL_TREE, complain)));
+    return convert_to_reference (type, e, CONV_C_CAST, 0,
+				 NULL_TREE, complain);
 
   if (code == POINTER_TYPE)
-    return fold_if_not_in_template (convert_to_pointer_force (type, e,
-							      complain));
+    return convert_to_pointer_force (type, e, complain);
 
   /* From typeck.c convert_for_assignment */
   if (((TYPE_PTR_P (TREE_TYPE (e)) && TREE_CODE (e) == ADDR_EXPR
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bd3f2bc..484f4f2 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8580,35 +8580,6 @@ stabilize_vla_size (tree size)
   cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
 }
 
-/* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
-   not inside of SAVE_EXPR and fold them.  */
-
-static tree
-fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
-{
-  tree expr = *expr_p;
-  if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
-    *walk_subtrees = 0;
-  else if (TREE_CODE (expr) == SIZEOF_EXPR)
-    {
-      *(bool *)data = true;
-      if (SIZEOF_EXPR_TYPE_P (expr))
-	expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
-					   SIZEOF_EXPR, false);
-      else if (TYPE_P (TREE_OPERAND (expr, 0)))
-	expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
-					   false);
-      else
-        expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
-					   false);
-      if (expr == error_mark_node)
-        expr = size_one_node;
-      *expr_p = expr;
-      *walk_subtrees = 0;
-    }
-  return NULL;
-}
-
 /* Given the SIZE (i.e., number of elements) in an array, compute an
    appropriate index type for the array.  If non-NULL, NAME is the
    name of the thing being declared.  */
@@ -8699,7 +8670,18 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
       SET_TYPE_STRUCTURAL_EQUALITY (itype);
       return itype;
     }
-  
+
+  if (TREE_CODE (size) != INTEGER_CST)
+    {
+      tree folded = cp_fully_fold (size);
+      if (TREE_CODE (folded) == INTEGER_CST)
+	pedwarn (location_of (size), OPT_Wpedantic,
+		 "size of array is not an integral constant-expression");
+      /* Use the folded result for VLAs, too; it will have resolved
+	 SIZEOF_EXPR.  */
+      size = folded;
+    }
+
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
     {
@@ -8786,7 +8768,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
 				  cp_convert (ssizetype, integer_one_node,
 					      complain),
 				  complain);
-      itype = fold (itype);
+      itype = maybe_constant_value (itype);
       processing_template_decl = saved_processing_template_decl;
 
       if (!TREE_CONSTANT (itype))
@@ -8794,18 +8776,6 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
 	  /* A variable sized array.  */
 	  itype = variable_size (itype);
 
-	  if (TREE_CODE (itype) != SAVE_EXPR)
-	    {
-	      /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
-		 they might survive till gimplification.  */
-	      tree newitype = itype;
-	      bool found = false;
-	      cp_walk_tree_without_duplicates (&newitype,
-					       fold_sizeof_expr_r, &found);
-	      if (found)
-		itype = variable_size (fold (newitype));
-	    }
-
 	  stabilize_vla_size (itype);
 
 	  if (flag_sanitize & SANITIZE_VLA
@@ -13515,7 +13485,7 @@ incremented enumerator value is too large for %<long%>");
 		   "type %<%T%>", value, ENUM_UNDERLYING_TYPE (enumtype));
 
           /* Convert the value to the appropriate type.  */
-          value = convert (ENUM_UNDERLYING_TYPE (enumtype), value);
+          value = fold_convert (ENUM_UNDERLYING_TYPE (enumtype), value);
         }
     }
 
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a2d31a3..89859e9 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3116,7 +3116,7 @@ get_guard_cond (tree guard, bool thread_safe)
     {
       guard_value = integer_one_node;
       if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
-	guard_value = convert (TREE_TYPE (guard), guard_value);
+	guard_value = fold_convert (TREE_TYPE (guard), guard_value);
       guard = cp_build_binary_op (input_location,
 				  BIT_AND_EXPR, guard, guard_value,
 				  tf_warning_or_error);
@@ -3124,7 +3124,7 @@ get_guard_cond (tree guard, bool thread_safe)
 
   guard_value = integer_zero_node;
   if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
-    guard_value = convert (TREE_TYPE (guard), guard_value);
+    guard_value = fold_convert (TREE_TYPE (guard), guard_value);
   return cp_build_binary_op (input_location,
 			     EQ_EXPR, guard, guard_value,
 			     tf_warning_or_error);
@@ -3142,7 +3142,7 @@ set_guard (tree guard)
   guard = get_guard_bits (guard);
   guard_init = integer_one_node;
   if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard)))
-    guard_init = convert (TREE_TYPE (guard), guard_init);
+    guard_init = fold_convert (TREE_TYPE (guard), guard_init);
   return cp_build_modify_expr (guard, NOP_EXPR, guard_init, 
 			       tf_warning_or_error);
 }
@@ -4573,6 +4573,19 @@ c_parse_final_cleanups (void)
       /* If there are templates that we've put off instantiating, do
 	 them now.  */
       instantiate_pending_templates (retries);
+      /* Clear fold_map and/or cv_map of current scope, if present.  */
+      if (scope_chain && (scope_chain->fold_map || scope_chain->cv_map))
+	{
+	  hash_map<tree,tree> *fm = scope_chain->fold_map;
+	  hash_map<tree,tree> *cv = scope_chain->cv_map;
+	  scope_chain->fold_map = NULL;
+	  scope_chain->cv_map = NULL;
+	  scope_chain->act_cfun = NULL;
+	  if (fm)
+	    delete fm;
+	  if (cv)
+	    delete cv;
+	}
       ggc_collect ();
 
       /* Write out virtual tables as required.  Note that writing out
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index b45281f..fd9ae0d 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -178,9 +178,9 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
        initialized are initialized to zero.  */
     ;
   else if (TYPE_PTR_OR_PTRMEM_P (type))
-    init = convert (type, nullptr_node);
+    init = fold (convert (type, nullptr_node));
   else if (SCALAR_TYPE_P (type))
-    init = convert (type, integer_zero_node);
+    init = fold (convert (type, integer_zero_node));
   else if (RECORD_OR_UNION_CODE_P (TREE_CODE (type)))
     {
       tree field;
@@ -794,7 +794,6 @@ perform_member_init (tree member, tree init)
 	   in that case.  */
 	init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
 						tf_warning_or_error);
-
       if (init)
 	finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init,
 						tf_warning_or_error));
@@ -2712,7 +2711,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
       }
       max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
 
-      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
+      size = size_binop (MULT_EXPR, size, fold_convert (sizetype, nelts));
       outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
 				       outer_nelts,
 				       max_outer_nelts_tree);
@@ -2872,7 +2871,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	{
 	  placement_expr = get_target_expr (placement_first);
 	  CALL_EXPR_ARG (alloc_call, 1)
-	    = convert (TREE_TYPE (placement), placement_expr);
+	    = fold_convert (TREE_TYPE (placement), placement_expr);
 	}
 
       if (!member_new_p
@@ -3464,7 +3463,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
   /* The below is short by the cookie size.  */
   virtual_size = size_binop (MULT_EXPR, size_exp,
-			     convert (sizetype, maxindex));
+			     fold_convert (sizetype, maxindex));
 
   tbase = create_temporary_var (ptype);
   tbase_init
@@ -3507,7 +3506,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
       /* The below is short by the cookie size.  */
       virtual_size = size_binop (MULT_EXPR, size_exp,
-				 convert (sizetype, maxindex));
+				 fold_convert (sizetype, maxindex));
 
       if (! TYPE_VEC_NEW_USES_COOKIE (type))
 	/* no header */
@@ -3553,8 +3552,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
 		      fold_build2_loc (input_location,
 				   NE_EXPR, boolean_type_node, base,
-				   convert (TREE_TYPE (base),
-					    nullptr_node)),
+				   fold_convert (TREE_TYPE (base),
+						 nullptr_node)),
 		      body, integer_zero_node);
   body = build1 (NOP_EXPR, void_type_node, body);
 
@@ -3676,6 +3675,7 @@ build_vec_init (tree base, tree maxindex, tree init,
   if (maxindex == NULL_TREE || maxindex == error_mark_node)
     return error_mark_node;
 
+  maxindex = maybe_constant_value (maxindex);
   if (explicit_value_init_p)
     gcc_assert (!init);
 
@@ -3717,6 +3717,8 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
 
   maxindex = cp_convert (ptrdiff_type_node, maxindex, complain);
+  maxindex = fold_simple (maxindex);
+
   if (TREE_CODE (atype) == ARRAY_TYPE)
     {
       ptype = build_pointer_type (type);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8744fff..61a352a 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -6182,6 +6182,19 @@ push_to_top_level (void)
   s->unevaluated_operand = cp_unevaluated_operand;
   s->inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
   s->x_stmt_tree.stmts_are_full_exprs_p = true;
+  if (current_function_decl
+      && scope_chain && scope_chain->function_decl == current_function_decl
+      && cfun && scope_chain->act_cfun == cfun)
+    {
+      s->fold_map = scope_chain->fold_map;
+      s->cv_map = scope_chain->cv_map;
+    }
+  else
+    {
+      s->fold_map = NULL;
+      s->cv_map = NULL;
+    }
+  s->act_cfun = cfun;
 
   scope_chain = s;
   current_function_decl = NULL_TREE;
@@ -6199,7 +6212,10 @@ pop_from_top_level_1 (void)
 {
   struct saved_scope *s = scope_chain;
   cxx_saved_binding *saved;
+  hash_map<tree, tree> *fm = s->fold_map;
+  hash_map<tree, tree> *cv = s->cv_map;
   size_t i;
+  bool same_fold_map = false;
 
   /* Clear out class-level bindings cache.  */
   if (previous_class_level)
@@ -6221,9 +6237,32 @@ pop_from_top_level_1 (void)
      state.  */
   if (s->need_pop_function_context)
     pop_function_context ();
+
+  /* If 'current_function_decl' isn't NULL and is equal to prior pushed,
+     we are within a nested function.
+     If additionally saved 'cfun' is identical to current, we can use
+     the same 'fold_map'.  */
+     
+  if (current_function_decl && s->function_decl == current_function_decl
+      && scope_chain && s->fold_map == scope_chain->fold_map
+      && scope_chain->act_cfun && scope_chain->act_cfun == cfun)
+    same_fold_map = true;
+
   current_function_decl = s->function_decl;
   cp_unevaluated_operand = s->unevaluated_operand;
   c_inhibit_evaluation_warnings = s->inhibit_evaluation_warnings;
+
+  /* If we have a new 'fold_map', and it isn't equal, or outside of
+     scope_chain, then invalidate it.  */
+  if (fm && (!same_fold_map || !scope_chain))
+    delete fm;
+  if (cv && (!same_fold_map || !scope_chain))
+    delete cv;
+
+  /* Invalidate explicit.  */
+  s->fold_map = NULL;
+  s->cv_map = NULL;
+  s->act_cfun = NULL;
 }
 
 /* Wrapper for pop_from_top_level_1.  */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d1f4970..24a77f8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6769,7 +6769,7 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree *init_index,
 	 2. ARRAY [ EXP : EXP ]
 	 3. ARRAY [ EXP : EXP : EXP ]  */
 
-      *init_index = cp_parser_expression (parser);	
+      *init_index = cp_parser_expression (parser);
       if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
 	{  
 	  /* This indicates that we have a normal array expression.  */
@@ -8513,9 +8513,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
       /* For "false && x" or "true || x", x will never be executed;
 	 disable warnings while evaluating it.  */
       if (current.tree_type == TRUTH_ANDIF_EXPR)
-	c_inhibit_evaluation_warnings += current.lhs == truthvalue_false_node;
+	c_inhibit_evaluation_warnings +=
+	  cp_fully_fold (current.lhs) == truthvalue_false_node;
       else if (current.tree_type == TRUTH_ORIF_EXPR)
-	c_inhibit_evaluation_warnings += current.lhs == truthvalue_true_node;
+	c_inhibit_evaluation_warnings +=
+	  cp_fully_fold (current.lhs) == truthvalue_true_node;
 
       /* Extract another operand.  It may be the RHS of this expression
 	 or the LHS of a new, higher priority expression.  */
@@ -8562,9 +8564,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 
       /* Undo the disabling of warnings done above.  */
       if (current.tree_type == TRUTH_ANDIF_EXPR)
-	c_inhibit_evaluation_warnings -= current.lhs == truthvalue_false_node;
+	c_inhibit_evaluation_warnings -=
+	  cp_fully_fold (current.lhs) == truthvalue_false_node;
       else if (current.tree_type == TRUTH_ORIF_EXPR)
-	c_inhibit_evaluation_warnings -= current.lhs == truthvalue_true_node;
+	c_inhibit_evaluation_warnings -=
+	  cp_fully_fold (current.lhs) == truthvalue_true_node;
 
       if (warn_logical_not_paren
 	  && TREE_CODE_CLASS (current.tree_type) == tcc_comparison
@@ -8650,7 +8654,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 static tree
 cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
 {
-  tree expr;
+  tree expr, folded_logical_or_expr = cp_fully_fold (logical_or_expr);
   tree assignment_expr;
   struct cp_token *token;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -8665,7 +8669,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
                "ISO C++ does not allow ?: with omitted middle operand");
       /* Implicit true clause.  */
       expr = NULL_TREE;
-      c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
+      c_inhibit_evaluation_warnings +=
+	folded_logical_or_expr == truthvalue_true_node;
       warn_for_omitted_condop (token->location, logical_or_expr);
     }
   else
@@ -8673,11 +8678,12 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
       bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
       parser->colon_corrects_to_scope_p = false;
       /* Parse the expression.  */
-      c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
+      c_inhibit_evaluation_warnings +=
+	folded_logical_or_expr == truthvalue_false_node;
       expr = cp_parser_expression (parser);
       c_inhibit_evaluation_warnings +=
-	((logical_or_expr == truthvalue_true_node)
-	 - (logical_or_expr == truthvalue_false_node));
+	((folded_logical_or_expr == truthvalue_true_node)
+	 - (folded_logical_or_expr == truthvalue_false_node));
       parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
     }
 
@@ -8685,7 +8691,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
   cp_parser_require (parser, CPP_COLON, RT_COLON);
   /* Parse the assignment-expression.  */
   assignment_expr = cp_parser_assignment_expression (parser);
-  c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
+  c_inhibit_evaluation_warnings -=
+    folded_logical_or_expr == truthvalue_true_node;
 
   /* Build the conditional-expression.  */
   return build_x_conditional_expr (loc, logical_or_expr,
@@ -20330,8 +20337,8 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
     {
       initializer
 	= cp_parser_constant_expression (parser,
-					/*allow_non_constant_p=*/true,
-					non_constant_p);
+					 /*allow_non_constant_p=*/true,
+					 non_constant_p);
     }
   else
     initializer = cp_parser_braced_list (parser, non_constant_p);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bfea8e2..fb9cdf8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6217,7 +6217,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
   /* 14.3.2/5: The null pointer{,-to-member} conversion is applied
      to a non-type argument of "nullptr".  */
   if (expr == nullptr_node && TYPE_PTR_OR_PTRMEM_P (type))
-    expr = convert (type, expr);
+    expr = fold_simple (convert (type, expr));
 
   /* In C++11, integral or enumeration non-type template arguments can be
      arbitrary constant expressions.  Pointer and pointer to
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 7702a41..73f05f0 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2569,9 +2569,26 @@ finish_unary_op_expr (location_t loc, enum tree_code code, tree expr,
 		      tsubst_flags_t complain)
 {
   tree result = build_x_unary_op (loc, code, expr, complain);
-  if ((complain & tf_warning)
-      && TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
-    overflow_warning (input_location, result);
+  tree result_ovl, expr_ovl;
+
+  if (!(complain & tf_warning))
+    return result;
+
+  result_ovl = result;
+  expr_ovl = expr;
+
+  if (!processing_template_decl)
+    expr_ovl = cp_fully_fold (expr_ovl);
+
+  if (!CONSTANT_CLASS_P (expr_ovl)
+      || TREE_OVERFLOW_P (expr_ovl))
+    return result;
+
+  if (!processing_template_decl)
+    result_ovl = cp_fully_fold (result_ovl);
+
+  if (CONSTANT_CLASS_P (result_ovl) && TREE_OVERFLOW_P (result_ovl))
+    overflow_warning (input_location, result_ovl);
 
   return result;
 }
@@ -3895,6 +3912,7 @@ finish_offsetof (tree expr, location_t loc)
 	      TREE_OPERAND (expr, 2));
       return error_mark_node;
     }
+
   if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
       || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
       || TREE_TYPE (expr) == unknown_type_node)
@@ -4049,6 +4067,22 @@ emit_associated_thunks (tree fn)
 bool
 expand_or_defer_fn_1 (tree fn)
 {
+  if (!function_depth)
+    {
+      if (scope_chain && (scope_chain->fold_map || scope_chain->cv_map))
+	{
+	  hash_map<tree, tree> *fm = scope_chain->fold_map;
+	  hash_map<tree, tree> *cv = scope_chain->cv_map;
+	  if (fm)
+	    delete fm;
+	  if (cv)
+	    delete cv;
+	  scope_chain->fold_map = NULL;
+	  scope_chain->cv_map = NULL;
+	  scope_chain->act_cfun = NULL;
+	}
+    }
+
   /* When the parser calls us after finishing the body of a template
      function, we don't really want to expand the body.  */
   if (processing_template_decl)
@@ -4129,6 +4163,19 @@ expand_or_defer_fn (tree fn)
       emit_associated_thunks (fn);
 
       function_depth--;
+      if (function_depth == 0
+	  && scope_chain && (scope_chain->fold_map || scope_chain->cv_map))
+	{
+	  hash_map<tree, tree> *fm = scope_chain->fold_map;
+	  hash_map<tree, tree> *cv = scope_chain->cv_map;
+	  scope_chain->fold_map = NULL;
+	  scope_chain->cv_map = NULL;
+	  scope_chain->act_cfun = NULL;
+	  if (fm)
+	    delete fm;
+	  if (cv)
+	    delete cv;
+	}
     }
 }
 
@@ -4483,6 +4530,11 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
     low_bound = mark_rvalue_use (low_bound);
   if (length)
     length = mark_rvalue_use (length);
+  /* We need to reduce to real constant-values for checks below.  */
+  if (length)
+    length = fold_simple (length);
+  if (low_bound)
+    low_bound = fold_simple (low_bound);
   if (low_bound
       && TREE_CODE (low_bound) == INTEGER_CST
       && TYPE_PRECISION (TREE_TYPE (low_bound))
@@ -6178,7 +6230,8 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 		  if (OMP_CLAUSE_SCHEDULE_KIND (c)
 		      == OMP_CLAUSE_SCHEDULE_CILKFOR)
 		    {
-		      t = convert_to_integer (long_integer_type_node, t);
+		      t = convert_to_integer_nofold (long_integer_type_node,
+						     t);
 		      if (t == error_mark_node)
 			{
 			  remove = true;
@@ -7447,6 +7500,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   if (init && EXPR_HAS_LOCATION (init))
     elocus = EXPR_LOCATION (init);
 
+  cond = cp_fully_fold (cond);
   switch (TREE_CODE (cond))
     {
     case GT_EXPR:
@@ -7482,6 +7536,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   diff = build_x_binary_op (elocus, MINUS_EXPR, TREE_OPERAND (cond, 1),
 			    ERROR_MARK, iter, ERROR_MARK, NULL,
 			    tf_warning_or_error);
+  diff = cp_fully_fold (diff);
   if (error_operand_p (diff))
     return true;
   if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE)
@@ -7543,8 +7598,9 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
 		  if (TREE_CODE (rhs) == MINUS_EXPR)
 		    {
 		      incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr);
-		      incr = fold_if_not_in_template (incr);
+		      incr = fold_simple (incr);
 		    }
+
 		  if (TREE_CODE (incr) != INTEGER_CST
 		      && (TREE_CODE (incr) != NOP_EXPR
 			  || (TREE_CODE (TREE_OPERAND (incr, 0))
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 4311212..dd4daed 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -308,9 +308,19 @@ xvalue_p (const_tree ref)
 bool
 builtin_valid_in_constant_expr_p (const_tree decl)
 {
-  /* At present BUILT_IN_CONSTANT_P is the only builtin we're allowing
-     in constant-expressions.  We may want to add other builtins later. */
-  return DECL_IS_BUILTIN_CONSTANT_P (decl);
+  if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)))
+    /* Not a built-in.  */
+    return false;
+  switch (DECL_FUNCTION_CODE (decl))
+    {
+    case BUILT_IN_CONSTANT_P:
+    case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
+      /* These have constant results even if their operands are
+	 non-constant.  */
+      return true;
+    default:
+      return false;
+    }
 }
 
 /* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
@@ -686,8 +696,8 @@ convert_bitfield_to_declared_type (tree expr)
 
   bitfield_type = is_bitfield_expr_with_lowered_type (expr);
   if (bitfield_type)
-    expr = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type),
-			       expr);
+    expr = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type),
+				      expr);
   return expr;
 }
 
@@ -3484,10 +3494,13 @@ handle_init_priority_attribute (tree* node,
 
   STRIP_NOPS (initp_expr);
   initp_expr = default_conversion (initp_expr);
+  if (initp_expr)
+    initp_expr = maybe_constant_value (initp_expr);
 
   if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
     {
       error ("requested init_priority is not an integer constant");
+      cxx_constant_value (initp_expr);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -4262,26 +4275,6 @@ stabilize_init (tree init, tree *initp)
   return !TREE_SIDE_EFFECTS (init);
 }
 
-/* Like "fold", but should be used whenever we might be processing the
-   body of a template.  */
-
-tree
-fold_if_not_in_template (tree expr)
-{
-  /* In the body of a template, there is never any need to call
-     "fold".  We will call fold later when actually instantiating the
-     template.  Integral constant expressions in templates will be
-     evaluated via instantiate_non_dependent_expr, as necessary.  */
-  if (processing_template_decl)
-    return expr;
-
-  /* Fold C++ front-end specific tree codes.  */
-  if (TREE_CODE (expr) == UNARY_PLUS_EXPR)
-    return fold_convert (TREE_TYPE (expr), TREE_OPERAND (expr, 0));
-
-  return fold (expr);
-}
-
 /* Returns true if a cast to TYPE may appear in an integral constant
    expression.  */
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0501e4d..4e7ef58 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1948,8 +1948,6 @@ decay_conversion (tree exp,
 
   code = TREE_CODE (type);
 
-  /* FIXME remove for delayed folding.  */
-  exp = scalar_constant_value (exp);
   if (error_operand_p (exp))
     return error_mark_node;
 
@@ -2442,7 +2440,6 @@ build_class_member_access_expr (tree object, tree member,
 
       result = build3_loc (input_location, COMPONENT_REF, member_type,
 			   object, member, NULL_TREE);
-      result = fold_if_not_in_template (result);
 
       /* Mark the expression const or volatile, as appropriate.  Even
 	 though we've dealt with the type above, we still have to mark the
@@ -2855,9 +2852,9 @@ build_simple_component_ref (tree object, tree member)
 {
   tree type = cp_build_qualified_type (TREE_TYPE (member),
 				       cp_type_quals (TREE_TYPE (object)));
-  return fold_build3_loc (input_location,
-			  COMPONENT_REF, type,
-			  object, member, NULL_TREE);
+  return build3_loc (input_location,
+		     COMPONENT_REF, type,
+		     object, member, NULL_TREE);
 }
 
 /* Return an expression for the MEMBER_NAME field in the internal
@@ -3176,8 +3173,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
 	|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
       TREE_THIS_VOLATILE (rval)
 	|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
-      ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
-					  complain);
+      ret = require_complete_type_sfinae (rval, complain);
       protected_set_expr_location (ret, loc);
       if (non_lvalue)
 	ret = non_lvalue_loc (loc, ret);
@@ -3924,7 +3920,6 @@ build_vec_cmp (tree_code code, tree type,
   tree minus_one_vec = build_minus_one_cst (type);
   tree cmp_type = build_same_sized_truth_vector_type(type);
   tree cmp = build2 (code, cmp_type, arg0, arg1);
-  cmp = fold_if_not_in_template (cmp);
   return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
 }
 
@@ -3979,7 +3974,7 @@ cp_build_binary_op (location_t location,
      convert it to this type.  */
   tree final_type = 0;
 
-  tree result;
+  tree result, result_ovl;
   tree orig_type = NULL;
 
   /* Nonzero if this is an operation like MIN or MAX which can
@@ -4602,7 +4597,7 @@ cp_build_binary_op (location_t location,
 	      op0 = cp_build_binary_op (location,
 					TRUTH_ANDIF_EXPR, e1, e2,
 					complain);
-	      op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain); 
+	      op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain);
 	    }
      	  else 
 	    {
@@ -4643,10 +4638,12 @@ cp_build_binary_op (location_t location,
 	    op1 = save_expr (op1);
 
 	  pfn0 = pfn_from_ptrmemfunc (op0);
+	  pfn0 = cp_fully_fold (pfn0);
 	  /* Avoid -Waddress warnings (c++/64877).  */
 	  if (TREE_CODE (pfn0) == ADDR_EXPR)
 	    TREE_NO_WARNING (pfn0) = 1;
 	  pfn1 = pfn_from_ptrmemfunc (op1);
+	  pfn1 = cp_fully_fold (pfn1);
 	  delta0 = delta_from_ptrmemfunc (op0);
 	  delta1 = delta_from_ptrmemfunc (op1);
 	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION
@@ -5000,10 +4997,7 @@ cp_build_binary_op (location_t location,
 		  gcc_unreachable();
 		}
 	    }
-	  real = fold_if_not_in_template (real);
-	  imag = fold_if_not_in_template (imag);
 	  result = build2 (COMPLEX_EXPR, result_type, real, imag);
-	  result = fold_if_not_in_template (result);
 	  return result;
 	}
 
@@ -5031,20 +5025,12 @@ cp_build_binary_op (location_t location,
 
       if (short_compare)
 	{
-	  /* Don't write &op0, etc., because that would prevent op0
-	     from being kept in a register.
-	     Instead, make copies of the our local variables and
-	     pass the copies by reference, then copy them back afterward.  */
-	  tree xop0 = op0, xop1 = op1, xresult_type = result_type;
+	  /* We call shorten_compare only for diagnostic-reason.  */
+	  tree xop0 = fold_simple (op0), xop1 = fold_simple (op1),
+	       xresult_type = result_type;
 	  enum tree_code xresultcode = resultcode;
-	  tree val
-	    = shorten_compare (location, &xop0, &xop1, &xresult_type,
+	  shorten_compare (location, &xop0, &xop1, &xresult_type,
 			       &xresultcode);
-	  if (val != 0)
-	    return cp_convert (boolean_type_node, val, complain);
-	  op0 = xop0, op1 = xop1;
-	  converted = 1;
-	  resultcode = xresultcode;
 	}
 
       if ((short_compare || code == MIN_EXPR || code == MAX_EXPR)
@@ -5063,9 +5049,9 @@ cp_build_binary_op (location_t location,
 	  tree oop1 = maybe_constant_value (orig_op1);
 
 	  if (TREE_CODE (oop0) != INTEGER_CST)
-	    oop0 = orig_op0;
+	    oop0 = cp_fully_fold (orig_op0);
 	  if (TREE_CODE (oop1) != INTEGER_CST)
-	    oop1 = orig_op1;
+	    oop1 = cp_fully_fold (orig_op1);
 	  warn_for_sign_compare (location, oop0, oop1, op0, op1, 
 				 result_type, resultcode);
 	}
@@ -5120,18 +5106,30 @@ cp_build_binary_op (location_t location,
     }
 
   result = build2 (resultcode, build_type, op0, op1);
-  result = fold_if_not_in_template (result);
   if (final_type != 0)
     result = cp_convert (final_type, result, complain);
 
-  if (TREE_OVERFLOW_P (result) 
-      && !TREE_OVERFLOW_P (op0) 
-      && !TREE_OVERFLOW_P (op1))
-    overflow_warning (location, result);
-
   if (instrument_expr != NULL)
-    result = fold_build2 (COMPOUND_EXPR, TREE_TYPE (result),
-			  instrument_expr, result);
+    result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
+		     instrument_expr, result);
+
+  if (!processing_template_decl)
+    {
+      op0 = cp_fully_fold (op0);
+      /* Only consider the second argument if the first isn't overflowed.  */
+      if (!CONSTANT_CLASS_P (op0) || TREE_OVERFLOW_P (op0))
+	return result;
+      op1 = cp_fully_fold (op1);
+      if (!CONSTANT_CLASS_P (op1) || TREE_OVERFLOW_P (op1))
+	return result;
+    }
+  else if (!CONSTANT_CLASS_P (op0) || !CONSTANT_CLASS_P (op1)
+	   || TREE_OVERFLOW_P (op0) || TREE_OVERFLOW_P (op1))
+    return result;
+
+  result_ovl = fold_build2 (resultcode, build_type, op0, op1);
+  if (TREE_OVERFLOW_P (result_ovl))
+    overflow_warning (location, result_ovl);
 
   return result;
 }
@@ -5181,8 +5179,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop,
   complete_type (TREE_TYPE (res_type));
 
   return pointer_int_sum (input_location, resultcode, ptrop,
-			  fold_if_not_in_template (intop),
-			  complain & tf_warning_or_error);
+			  intop, complain & tf_warning_or_error);
 }
 
 /* Return a tree for the difference of pointers OP0 and OP1.
@@ -5258,7 +5255,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain)
 
   result = build2 (EXACT_DIV_EXPR, restype, op0,
 		   cp_convert (restype, op1, complain));
-  return fold_if_not_in_template (result);
+  return result;
 }
 
 /* Construct and perhaps optimize a tree representation
@@ -5774,6 +5771,10 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
 	    /* Make sure the result is not an lvalue: a unary plus or minus
 	       expression is always a rvalue.  */
 	    arg = rvalue (arg);
+
+	    if (code == NEGATE_EXPR && CONSTANT_CLASS_P (arg))
+	      /* Immediately fold negation of a constant.  */
+	      return fold_build1 (code, TREE_TYPE (arg), arg);
 	  }
       }
       break;
@@ -5838,10 +5839,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       arg = build_real_imag_expr (input_location, code, arg);
-      if (arg == error_mark_node)
-	return arg;
-      else
-	return fold_if_not_in_template (arg);
+      return arg;
 
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
@@ -6008,7 +6006,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     {
       if (argtype == 0)
 	argtype = TREE_TYPE (arg);
-      return fold_if_not_in_template (build1 (code, argtype, arg));
+      return build1 (code, argtype, arg);
     }
 
   if (complain & tf_error)
@@ -7002,7 +7000,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
     return rvalue (expr);
   else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
 	   || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
-    return fold_if_not_in_template (build_nop (type, expr));
+    return build_nop (type, expr);
   else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype))
 	   || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
     {
@@ -7030,7 +7028,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
       if (warn_strict_aliasing <= 2)
 	strict_aliasing_warning (intype, type, sexpr);
 
-      return fold_if_not_in_template (build_nop (type, expr));
+      return build_nop (type, expr);
     }
   else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
 	   || (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type)))
@@ -7041,13 +7039,13 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
 	warning (OPT_Wconditionally_supported,
 		 "casting between pointer-to-function and pointer-to-object "
 		 "is conditionally-supported");
-      return fold_if_not_in_template (build_nop (type, expr));
+      return build_nop (type, expr);
     }
   else if (VECTOR_TYPE_P (type))
-    return fold_if_not_in_template (convert_to_vector (type, expr));
+    return convert_to_vector (type, expr);
   else if (VECTOR_TYPE_P (intype)
 	   && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-    return fold_if_not_in_template (convert_to_integer (type, expr));
+    return convert_to_integer_nofold (type, expr);
   else
     {
       if (valid_p)
@@ -7899,8 +7897,7 @@ get_delta_difference (tree from, tree to,
       }
   }
 
-  return fold_if_not_in_template (convert_to_integer (ptrdiff_type_node,
-						      result));
+  return convert_to_integer (ptrdiff_type_node, result);
 }
 
 /* Return a constructor for the pointer-to-member-function TYPE using
@@ -8081,41 +8078,35 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
 	 fn; the call will do the opposite adjustment.  */
       tree orig_class = DECL_CONTEXT (fn);
       tree binfo = binfo_or_else (orig_class, fn_class);
-      *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
-		       *delta, BINFO_OFFSET (binfo));
-      *delta = fold_if_not_in_template (*delta);
+      *delta = fold_build2 (PLUS_EXPR, TREE_TYPE (*delta),
+			    *delta, BINFO_OFFSET (binfo));
 
       /* We set PFN to the vtable offset at which the function can be
 	 found, plus one (unless ptrmemfunc_vbit_in_delta, in which
 	 case delta is shifted left, and then incremented).  */
       *pfn = DECL_VINDEX (fn);
-      *pfn = build2 (MULT_EXPR, integer_type_node, *pfn,
-		     TYPE_SIZE_UNIT (vtable_entry_type));
-      *pfn = fold_if_not_in_template (*pfn);
+      *pfn = fold_build2 (MULT_EXPR, integer_type_node, *pfn,
+			  TYPE_SIZE_UNIT (vtable_entry_type));
 
       switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
 	{
 	case ptrmemfunc_vbit_in_pfn:
-	  *pfn = build2 (PLUS_EXPR, integer_type_node, *pfn,
-			 integer_one_node);
-	  *pfn = fold_if_not_in_template (*pfn);
+	  *pfn = fold_build2 (PLUS_EXPR, integer_type_node, *pfn,
+			      integer_one_node);
 	  break;
 
 	case ptrmemfunc_vbit_in_delta:
-	  *delta = build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
-			   *delta, integer_one_node);
-	  *delta = fold_if_not_in_template (*delta);
-	  *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
-			   *delta, integer_one_node);
-	  *delta = fold_if_not_in_template (*delta);
+	  *delta = fold_build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
+				*delta, integer_one_node);
+	  *delta = fold_build2 (PLUS_EXPR, TREE_TYPE (*delta),
+				*delta, integer_one_node);
 	  break;
 
 	default:
 	  gcc_unreachable ();
 	}
 
-      *pfn = build_nop (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
-      *pfn = fold_if_not_in_template (*pfn);
+      *pfn = fold_convert (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
     }
 }
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e73ea13..7544333 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -742,6 +742,7 @@ split_nonconstant_init (tree dest, tree init)
     init = TARGET_EXPR_INITIAL (init);
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
+      init = cp_fully_fold (init);
       code = push_stmt_list ();
       if (split_nonconstant_init_1 (dest, init))
 	init = NULL_TREE;
@@ -832,6 +833,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
       TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
     }
+  value = cp_fully_fold (value);
 
   if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
     /* Handle aggregate NSDMI in non-constant initializers, too.  */
@@ -930,19 +932,35 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
 	}
     }
 
+  bool almost_ok = ok;
+  if (!ok && !CONSTANT_CLASS_P (init) && (complain & tf_warning_or_error))
+    {
+      tree folded = cp_fully_fold (init);
+      if (TREE_CONSTANT (folded) && check_narrowing (type, folded, tf_none))
+	almost_ok = true;
+    }
+
   if (!ok)
     {
+      location_t loc = EXPR_LOC_OR_LOC (init, input_location);
       if (cxx_dialect == cxx98)
-	warning_at (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
-		    "narrowing conversion of %qE from %qT to %qT inside { } "
-		    "is ill-formed in C++11", init, ftype, type);
-      else if (!TREE_CONSTANT (init))
+	{
+	  if (complain & tf_warning)
+	    warning_at (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
+			"from %qT to %qT inside { } is ill-formed in C++11",
+			init, ftype, type);
+	  ok = true;
+	}
+      else if (!CONSTANT_CLASS_P (init))
 	{
 	  if (complain & tf_warning_or_error)
 	    {
-	      pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
-		       "narrowing conversion of %qE from %qT to %qT inside { }",
-		       init, ftype, type);
+	      if (!almost_ok || pedantic)
+		pedwarn (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
+			 "from %qT to %qT inside { }", init, ftype, type);
+	      if (pedantic && almost_ok)
+		inform (loc, " the expression has a constant value but is not "
+			"a C++ constant-expression");
 	      ok = true;
 	    }
 	}
@@ -950,7 +968,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
 	{
 	  int savederrorcount = errorcount;
 	  global_dc->pedantic_errors = 1;
-	  pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
+	  pedwarn (loc, OPT_Wnarrowing,
 		   "narrowing conversion of %qE from %qT to %qT "
 		   "inside { }", init, ftype, type);
 	  if (errorcount == savederrorcount)
@@ -959,7 +977,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
 	}
     }
 
-  return cxx_dialect == cxx98 || ok; 
+  return ok;
 }
 
 /* Process the initializer INIT for a variable of type TYPE, emitting
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 5e32901..d754a90 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -2091,6 +2091,17 @@ fold_convert_const (enum tree_code code, tree type, tree arg1)
       else if (TREE_CODE (arg1) == REAL_CST)
 	return fold_convert_const_fixed_from_real (type, arg1);
     }
+  else if (TREE_CODE (type) == VECTOR_TYPE)
+    {
+      if (TREE_CODE (arg1) == VECTOR_CST
+	  && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (arg1))
+	  && TYPE_VECTOR_SUBPARTS (type) == VECTOR_CST_NELTS (arg1))
+	{
+	  tree r = copy_node (arg1);
+	  TREE_TYPE (arg1) = type;
+	  return r;
+	}
+    }
   return NULL_TREE;
 }
 
diff --git a/gcc/testsuite/c-c++-common/Wshift-negative-value-1.c b/gcc/testsuite/c-c++-common/Wshift-negative-value-1.c
index 5d803ad..8f14034 100644
--- a/gcc/testsuite/c-c++-common/Wshift-negative-value-1.c
+++ b/gcc/testsuite/c-c++-common/Wshift-negative-value-1.c
@@ -47,3 +47,5 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
diff --git a/gcc/testsuite/c-c++-common/Wshift-negative-value-2.c b/gcc/testsuite/c-c++-common/Wshift-negative-value-2.c
index fc89af1..55523a5 100644
--- a/gcc/testsuite/c-c++-common/Wshift-negative-value-2.c
+++ b/gcc/testsuite/c-c++-common/Wshift-negative-value-2.c
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
diff --git a/gcc/testsuite/c-c++-common/Wshift-negative-value-3.c b/gcc/testsuite/c-c++-common/Wshift-negative-value-3.c
index bf9b1a0..1295b72 100644
--- a/gcc/testsuite/c-c++-common/Wshift-negative-value-3.c
+++ b/gcc/testsuite/c-c++-common/Wshift-negative-value-3.c
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
diff --git a/gcc/testsuite/c-c++-common/Wshift-negative-value-4.c b/gcc/testsuite/c-c++-common/Wshift-negative-value-4.c
index 85fbd0e..3088220 100644
--- a/gcc/testsuite/c-c++-common/Wshift-negative-value-4.c
+++ b/gcc/testsuite/c-c++-common/Wshift-negative-value-4.c
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
diff --git a/gcc/testsuite/c-c++-common/fold-bitand-4.c b/gcc/testsuite/c-c++-common/fold-bitand-4.c
index 1b9c388..a658ff1 100644
--- a/gcc/testsuite/c-c++-common/fold-bitand-4.c
+++ b/gcc/testsuite/c-c++-common/fold-bitand-4.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c } } } */
 /* { dg-options "-fdump-tree-original" } */
 /* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
index 26c9293..a5e3c1f1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
@@ -18,7 +18,7 @@ public:
   {
     /* I am surprised this is considered a constexpr */
     return *((Inner *)4);
-  } // { dg-error "reinterpret_cast" "" { xfail *-*-* } }
+  } // { dg-error "reinterpret_cast" "" }
 };
 
 B B::instance;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr53792.C b/gcc/testsuite/g++.dg/cpp0x/pr53792.C
new file mode 100644
index 0000000..deb5c1a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr53792.C
@@ -0,0 +1,29 @@
+// PR c++/53792
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump "return 0" "optimized" } }
+
+struct entry {
+  char const* label;
+  int         value;
+};
+
+constexpr bool same(char const *x, char const *y) {
+  return !*x && !*y ? true
+    : /* default */    (*x == *y && same(x+1, y+1));
+}
+
+constexpr int keyToValue(char const *label, entry const *entries) {
+  return !entries->label ? entries->value
+       : same(entries->label, label) ? entries->value
+       : /*default*/                   keyToValue(label, entries+1);
+}
+
+constexpr entry foo[] = {{"Foo", 0}, {"Bar", 1}, {"FooBar", 2}, {0, -1}};
+
+int
+bar()
+{
+  int result = keyToValue("Foo", foo);
+  return result;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr56868.cpp b/gcc/testsuite/g++.dg/cpp0x/pr56868.cpp
new file mode 100644
index 0000000..afa7edb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr56868.cpp
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+
+constexpr int f(void *) { return 0; }
+constexpr int f(...) { return 1; }
+constexpr int g1() { return f(0); }
+constexpr int g2(int n) { return f(n); }
+constexpr int g3(int n) { return f(n*0); }
+
+int main()
+{
+    static_assert(g1() == 0, "g1 failed");
+    static_assert(g2(0) == 1, "g2 failed");
+    static_assert(g3(0) == 1, "g3 failed");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C b/gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C
new file mode 100644
index 0000000..e340de4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Woverflow" }
+
+#include <climits>
+
+constexpr int f() { return INT_MIN; }
+
+int main()
+{
+  return -f(); // { dg-warning "overflow" }
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C b/gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C
new file mode 100644
index 0000000..6b5dff8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Woverflow" }
+
+#include <climits>
+
+constexpr int f() { return INT_MAX; }
+
+int main()
+{
+  return f() + 2; // { dg-warning "overflow" }
+}
+
diff --git a/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C
new file mode 100644
index 0000000..39b3557
--- /dev/null
+++ b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Werror" }  */
+
+extern int fl;
+
+#define MAK (fl < 0 ? 1 : (fl ? -1 : 0))
+
+int foo (int sz)
+{
+  if (MAK) return 1;
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C
new file mode 100644
index 0000000..fa91a4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Werror" }  */
+
+extern int fl;
+extern int arr[];
+
+#define MAK (fl < 0 ? 1 : (fl ? 2 : 0))
+
+int foo (int sz)
+{
+  unsigned i;
+  int r = 0;
+  for (i = 0; i < MAK; i++)
+    r += arr[i];
+  return r;
+}
+
diff --git a/gcc/testsuite/g++.dg/ext/attr-aligned01.C b/gcc/testsuite/g++.dg/ext/attr-aligned01.C
index c8ec07d..0c5df6d 100644
--- a/gcc/testsuite/g++.dg/ext/attr-aligned01.C
+++ b/gcc/testsuite/g++.dg/ext/attr-aligned01.C
@@ -5,8 +5,8 @@
 
 template<typename T>
 void type_alignment(const T&) {
-  struct { char c; T t; } s;
-  SA((char*)&s.t - (char*)&s.c == 1);
+  struct S { char c; T t; } s;
+  SA(__builtin_offsetof (S,t) - __builtin_offsetof (S,c) == 1);
 }
 
 template <class T> struct A { char c; T t; };
@@ -17,7 +17,8 @@ int main() {
 
   A<aligned> a;			// { dg-warning "ignoring attributes" }
 
-  SA((char*)&a.t - (char*)&a.c == 1);
+  SA(  __builtin_offsetof (__typeof(a),t)
+     - __builtin_offsetof (__typeof(a),c) == 1);
 
   aligned z;
   type_alignment(z);		// { dg-warning "ignoring attributes" "" { xfail *-*-* } }
diff --git a/gcc/testsuite/g++.dg/ext/offsetof1.C b/gcc/testsuite/g++.dg/ext/offsetof1.C
index 1468c0a..23f3537 100644
--- a/gcc/testsuite/g++.dg/ext/offsetof1.C
+++ b/gcc/testsuite/g++.dg/ext/offsetof1.C
@@ -1,6 +1,7 @@
 // PR c++/27601
 // Origin: Patrik Hägglund  <patrik.hagglund@bredband.net>
 // { dg-do compile }
+// { dg-options "-Wno-pointer-arith" }
 
 struct bar {
   static int foo;
@@ -10,7 +11,7 @@ struct bar {
 int a = __builtin_offsetof(bar, foo);  // { dg-error "static data member" }
 int av = __builtin_offsetof(volatile bar, foo);  // { dg-error "static data member" }
 int b = __builtin_offsetof(bar, baz);  // { dg-error "member function" }
-int b0 = __builtin_offsetof(bar, baz[0]);  // { dg-error "function" }
+int b0 = __builtin_offsetof(bar, baz[0]);  // { dg-error "single identifier nor|member function" }
 int bv0 = __builtin_offsetof(volatile bar, baz[0]);  // { dg-error "function" }
 int c = __builtin_offsetof(bar, ~bar);  // { dg-error "member function" }
 
diff --git a/gcc/testsuite/g++.dg/init/const7.C b/gcc/testsuite/g++.dg/init/const7.C
index dbc60b3..e1f31bc 100644
--- a/gcc/testsuite/g++.dg/init/const7.C
+++ b/gcc/testsuite/g++.dg/init/const7.C
@@ -1,9 +1,9 @@
 // { dg-do compile }
-// { dg-options "-fdump-tree-gimple" }
+// { dg-options "-fdump-tree-gimple -pedantic" }
 
 struct s { int x, y; };
 short offsets[1] = {
-  ((char*) &(((struct s*)16)->y) - (char *)16),
+  ((char*) &(((struct s*)16)->y) - (char *)16), // { dg-message "narrowing" "" { target c++11 } }
 };
 
 // This ensures that we get a dump whether or not the bug is present.
diff --git a/gcc/testsuite/g++.dg/init/self1.C b/gcc/testsuite/g++.dg/init/self1.C
index dd37c8e..7620833 100644
--- a/gcc/testsuite/g++.dg/init/self1.C
+++ b/gcc/testsuite/g++.dg/init/self1.C
@@ -10,7 +10,7 @@ void f(__SIZE_TYPE__) {
 
 int main()
 {
-  int* const savepos = sizeof(*savepos) ? 0 : 0;
+  int* const savepos = sizeof(*savepos) ? 0 : 0;  /* { dg-error "invalid conversion" "convert" { target c++11 }  } */
 
   f (sizeof (*savepos));
 
diff --git a/gcc/testsuite/g++.dg/other/error22.C b/gcc/testsuite/g++.dg/other/error22.C
index 225dcae..eba0746 100644
--- a/gcc/testsuite/g++.dg/other/error22.C
+++ b/gcc/testsuite/g++.dg/other/error22.C
@@ -5,5 +5,5 @@ extern "C" double fabs (double);
 
 void foo (double x)
 {
-  fabs (x) ();	// { dg-error "__builtin_abs" }
+  fabs (x) ();	// { dg-error "function" }
 }
diff --git a/gcc/testsuite/g++.dg/other/error24.C b/gcc/testsuite/g++.dg/other/error24.C
index 54343c5..e5e6a4f 100644
--- a/gcc/testsuite/g++.dg/other/error24.C
+++ b/gcc/testsuite/g++.dg/other/error24.C
@@ -8,6 +8,6 @@ void
 bar (int i, int j, double k)
 {
   foo (i && j) ();	// { dg-error "\\(\\(?i != 0\\)? \\&\\& \\(?j != 0\\)?\\)" }
-  foo (!i || !j) ();	// { dg-error "\\(\\(?i == 0\\)? \\|\\| \\(?j == 0\\)?\\)" }
-  foo (!i == !j) ();	// { dg-error "\\(\\(?i != 0\\)? \\^ \\(?j == 0\\)?\\)" }
+  foo (!i || !j) ();	// { dg-error "function" }
+  foo (!i == !j) ();	// { dg-error "function" }
 }
diff --git a/gcc/testsuite/g++.dg/other/error26.C b/gcc/testsuite/g++.dg/other/error26.C
index fb2c8b7..ffe2728 100644
--- a/gcc/testsuite/g++.dg/other/error26.C
+++ b/gcc/testsuite/g++.dg/other/error26.C
@@ -2,5 +2,5 @@
 
 void foo(__complex__ double x)
 {
-  __builtin_conj(x)(); // { dg-error "~x" }
+  __builtin_conj(x)(); // { dg-error "function" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/array-size2.C b/gcc/testsuite/g++.dg/parse/array-size2.C
index 355ed61..3c83347 100644
--- a/gcc/testsuite/g++.dg/parse/array-size2.C
+++ b/gcc/testsuite/g++.dg/parse/array-size2.C
@@ -14,7 +14,7 @@ extern void bar (char *, char *);
 void
 foo (void)
 {
-  char g[(char *) &((struct S *) 0)->b - (char *) 0];
-  char h[(__SIZE_TYPE__) &((struct S *) 8)->b];
+  char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant" }
+  char h[(__SIZE_TYPE__) &((struct S *) 8)->b];	      // { dg-error "constant" "" { xfail *-*-* } }
   bar (g, h);
 }
diff --git a/gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C b/gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C
index 946f2e6..8014705 100644
--- a/gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C
+++ b/gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C
@@ -1,14 +1,10 @@
 /* { dg-do compile } */
 /* { dg-options "-fsanitize=integer-divide-by-zero" } */
 
-/* TODO: We expect an error on the invalid case here, because that
-   must be a constant-expression.  This will be fixed when we have
-   proper delayed folding.  */
-
 void
 foo (int i)
 {
   switch (i)
   case 0 * (1 / 0): /* { dg-warning "division by zero" } */
-    ;  /* { dg-error "division by zero" "" { xfail *-*-* } 10 } */
+    ;  /* { dg-error "is not a constant.expression" "" { target *-*-* } 8 } */
 }
diff --git a/gcc/testsuite/g++.dg/ubsan/shift-1.C b/gcc/testsuite/g++.dg/ubsan/shift-1.C
index 05e049e..493a55c 100644
--- a/gcc/testsuite/g++.dg/ubsan/shift-1.C
+++ b/gcc/testsuite/g++.dg/ubsan/shift-1.C
@@ -8,10 +8,10 @@ foo (int x)
   /* None of the following should pass.  */
   switch (x)
     {
-    case 1 >> -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case -1 >> -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case 1 << -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case -1 << -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
+    case 1 >> -1: /* { dg-error "operand of shift" "" } */
+    case -1 >> -1: /* { dg-error "operand of shift" "" } */
+    case 1 << -1: /* { dg-error "operand of shift" "" } */
+    case -1 << -1: /* { dg-error "operand of shift" "" } */
       return 1;
     }
   return 0;
@@ -23,8 +23,8 @@ bar (int x)
   /* None of the following should pass.  */
   switch (x)
     {
-    case -1 >> 200: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case 1 << 200: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
+    case -1 >> 200: /* { dg-error "operand of shift" "" } */
+    case 1 << 200: /* { dg-error "operand of shift" "" } */
       return 1;
     }
   return 0;
diff --git a/gcc/testsuite/g++.dg/warn/overflow-warn-1.C b/gcc/testsuite/g++.dg/warn/overflow-warn-1.C
index 7cd76e7..a10e15b 100644
--- a/gcc/testsuite/g++.dg/warn/overflow-warn-1.C
+++ b/gcc/testsuite/g++.dg/warn/overflow-warn-1.C
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* Again, overflow in evaluated subexpression.  */
@@ -126,3 +126,11 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 32 } */
+/* { dg-warning "invalid conversion from" "convert" { target *-*-* } 56 } */
+/* { dg-warning "invalid conversion from" "convert" { target c++11 } 58 } */
+/* { dg-error "is not a constant expression" "const" { target *-*-* } 65 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 65 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 32 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 32 } */
diff --git a/gcc/testsuite/g++.dg/warn/overflow-warn-3.C b/gcc/testsuite/g++.dg/warn/overflow-warn-3.C
index 73c0e00..c73a28c 100644
--- a/gcc/testsuite/g++.dg/warn/overflow-warn-3.C
+++ b/gcc/testsuite/g++.dg/warn/overflow-warn-3.C
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* Again, overflow in evaluated subexpression.  */
@@ -56,7 +56,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
 /* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 55 } */
 
 void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-warning "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */
+/* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
 void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
 
 void
@@ -65,7 +65,7 @@ g (int i)
   switch (i)
     {
     case 0 * (1/0): /* { dg-warning "division by zero" } */
-      ;
+      ;  /* { dg-error "is not a constant expression" "const" { target *-*-* } 67 }  */
     case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
       /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 69 } */
       ;
@@ -128,3 +128,9 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 32 } */
+/* { dg-warning "invalid conversion from" "convert" { target c++11 } 60 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 67 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 32 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 32 } */
diff --git a/gcc/testsuite/g++.dg/warn/overflow-warn-4.C b/gcc/testsuite/g++.dg/warn/overflow-warn-4.C
index 24b3959..23a2585 100644
--- a/gcc/testsuite/g++.dg/warn/overflow-warn-4.C
+++ b/gcc/testsuite/g++.dg/warn/overflow-warn-4.C
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* { dg-error "enumerator value for 'E5' is not an integer constant" "enum error" { target *-*-* } 21 } */
@@ -59,7 +59,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
 /* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
 
 void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 61 } */
+/* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 61 } */
 void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
 
 void
@@ -68,7 +68,7 @@ g (int i)
   switch (i)
     {
     case 0 * (1/0): /* { dg-warning "division by zero" } */
-      ;
+      ;  /* { dg-error "is not a constant expression" "const" { target *-*-* } 70 } */
     case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
       /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 72 } */
       ;
@@ -131,3 +131,9 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "invalid conversion from" "convert" { target c++11 } 63 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 34 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 70 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 34 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 34 } */
diff --git a/gcc/testsuite/g++.old-deja/g++.other/null3.C b/gcc/testsuite/g++.old-deja/g++.other/null3.C
index ff1d0669..96691d3 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/null3.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/null3.C
@@ -3,5 +3,5 @@
 void x()
 {
  int* p = 1==0;	// { dg-warning "converting 'false' to pointer" "" { target { ! c++11 } } }
-// { dg-error "cannot convert" "" { target c++11 } 5 } 
+// { dg-error "cannot convert" "" { target { c++11 } } 5 }
 }
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 11d5999..0204cfe 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -432,8 +432,8 @@ create_one_component_var (tree type, tree orig, const char *prefix,
   if (DECL_NAME (orig) && !DECL_IGNORED_P (orig))
     {
       const char *name = IDENTIFIER_POINTER (DECL_NAME (orig));
-
-      DECL_NAME (r) = get_identifier (ACONCAT ((name, suffix, NULL)));
+      name = ACONCAT ((name, suffix, NULL));
+      DECL_NAME (r) = get_identifier (name);
 
       SET_DECL_DEBUG_EXPR (r, build1 (code, type, orig));
       DECL_HAS_DEBUG_EXPR_P (r) = 1;
commit 2689ad9313b746c46a952bdec5f214ec737bc12e
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Nov 9 01:14:35 2015 -0500

    Merge c++-delayed-folding branch.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 0b7d143..536989b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4747,7 +4747,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 	  tree cmp_type = build_same_sized_truth_vector_type (arg1_type);
 	  arg1 = build2 (NE_EXPR, cmp_type, arg1, build_zero_cst (arg1_type));
 	}
-      return fold_build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
+      return build3_loc (loc, VEC_COND_EXPR, arg2_type, arg1, arg2, arg3);
     }
 
   /* [expr.cond]
@@ -5151,9 +5151,6 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3,
 
  valid_operands:
   result = build3_loc (loc, COND_EXPR, result_type, arg1, arg2, arg3);
-  if (!cp_unevaluated_operand)
-    /* Avoid folding within decltype (c++/42013) and noexcept.  */
-    result = fold_if_not_in_template (result);
 
   /* We can't use result_type below, as fold might have returned a
      throw_expr.  */
@@ -5689,8 +5686,8 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
 		 decaying an enumerator to its value.  */
 	      if (complain & tf_warning)
 		warn_logical_operator (loc, code, boolean_type_node,
-				       code_orig_arg1, arg1,
-				       code_orig_arg2, arg2);
+				       code_orig_arg1, fold (arg1),
+				       code_orig_arg2, fold (arg2));
 
 	      arg2 = convert_like (conv, arg2, complain);
 	    }
@@ -5728,7 +5725,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
     case TRUTH_OR_EXPR:
       if (complain & tf_warning)
 	warn_logical_operator (loc, code, boolean_type_node,
-			       code_orig_arg1, arg1, code_orig_arg2, arg2);
+			       code_orig_arg1, fold (arg1), code_orig_arg2, fold (arg2));
       /* Fall through.  */
     case GT_EXPR:
     case LT_EXPR:
@@ -5739,9 +5736,10 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1,
       if ((complain & tf_warning)
 	  && ((code_orig_arg1 == BOOLEAN_TYPE)
 	      ^ (code_orig_arg2 == BOOLEAN_TYPE)))
-	maybe_warn_bool_compare (loc, code, arg1, arg2);
+	maybe_warn_bool_compare (loc, code, fold (arg1),
+				 fold (arg2));
       if (complain & tf_warning && warn_tautological_compare)
-	warn_tautological_cmp (loc, code, arg1, arg2);
+	warn_tautological_cmp (loc, code, fold (arg1), fold (arg2));
       /* Fall through.  */
     case PLUS_EXPR:
     case MINUS_EXPR:
@@ -6495,7 +6493,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
 	  imag = perform_implicit_conversion (TREE_TYPE (totype),
 					      imag, complain);
 	  expr = build2 (COMPLEX_EXPR, totype, real, imag);
-	  return fold_if_not_in_template (expr);
+	  return expr;
 	}
       expr = reshape_init (totype, expr, complain);
       expr = get_target_expr_sfinae (digest_init (totype, expr, complain),
@@ -6736,7 +6734,7 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
 		    "implicit conversion from %qT to %qT when passing "
 		    "argument to function",
 		    arg_type, double_type_node);
-      arg = convert_to_real (double_type_node, arg);
+      arg = convert_to_real_nofold (double_type_node, arg);
     }
   else if (NULLPTR_TYPE_P (arg_type))
     arg = null_pointer_node;
@@ -6981,7 +6979,7 @@ convert_for_arg_passing (tree type, tree val, tsubst_flags_t complain)
   bitfield_type = is_bitfield_expr_with_lowered_type (val);
   if (bitfield_type 
       && TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (type))
-    val = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type), val);
+    val = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type), val);
 
   if (val == error_mark_node)
     ;
@@ -7501,7 +7499,19 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
   gcc_assert (j <= nargs);
   nargs = j;
 
-  check_function_arguments (TREE_TYPE (fn), nargs, argarray);
+  /* Avoid to do argument-transformation, if warnings for format, and for
+     nonnull are disabled.  Just in case that at least one of them is active
+     the check_function_arguments function might warn about something.  */
+
+  if (warn_nonnull || warn_format || warn_suggest_attribute_format)
+    {
+      tree *fargs = (!nargs ? argarray
+			    : (tree *) alloca (nargs * sizeof (tree)));
+      for (j = 0; j < nargs; j++)
+	fargs[j] = maybe_constant_value (argarray[j]);
+
+      check_function_arguments (TREE_TYPE (fn), nargs, fargs);
+    }
 
   /* Avoid actually calling copy constructors and copy assignment operators,
      if possible.  */
@@ -7692,7 +7702,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
 		tsubst_flags_t complain)
 {
   tree fndecl;
-  int optimize_sav;
 
   /* Remember roughly where this call is.  */
   location_t loc = EXPR_LOC_OR_LOC (fn, input_location);
@@ -7704,9 +7713,18 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
   /* Check that arguments to builtin functions match the expectations.  */
   if (fndecl
       && DECL_BUILT_IN (fndecl)
-      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
-      && !check_builtin_function_arguments (fndecl, nargs, argarray))
-    return error_mark_node;
+      && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
+    {
+      int i;
+
+      /* We need to take care that values to BUILT_IN_NORMAL
+         are reduced.  */
+      for (i = 0; i < nargs; i++)
+	argarray[i] = maybe_constant_value (argarray[i]);
+
+      if (!check_builtin_function_arguments (fndecl, nargs, argarray))
+	return error_mark_node;
+    }
 
     /* If it is a built-in array notation function, then the return type of
      the function is the element type of the array passed in as array 
@@ -7740,17 +7758,6 @@ build_cxx_call (tree fn, int nargs, tree *argarray,
 	}
     }
 
-  /* Some built-in function calls will be evaluated at compile-time in
-     fold ().  Set optimize to 1 when folding __builtin_constant_p inside
-     a constexpr function so that fold_builtin_1 doesn't fold it to 0.  */
-  optimize_sav = optimize;
-  if (!optimize && fndecl && DECL_IS_BUILTIN_CONSTANT_P (fndecl)
-      && current_function_decl
-      && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
-    optimize = 1;
-  fn = fold_if_not_in_template (fn);
-  optimize = optimize_sav;
-
   if (VOID_TYPE_P (TREE_TYPE (fn)))
     return fn;
 
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b123932..b5cf996 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -423,7 +423,7 @@ build_base_path (enum tree_code code,
 
 	  t = TREE_TYPE (TYPE_VFIELD (current_class_type));
 	  t = build_pointer_type (t);
-	  v_offset = convert (t, current_vtt_parm);
+	  v_offset = fold_convert (t, current_vtt_parm);
 	  v_offset = cp_build_indirect_ref (v_offset, RO_NULL, complain);
 	}
       else
@@ -556,8 +556,6 @@ build_simple_base_path (tree expr, tree binfo)
 	expr = build3 (COMPONENT_REF,
 		       cp_build_qualified_type (type, type_quals),
 		       expr, field, NULL_TREE);
-	expr = fold_if_not_in_template (expr);
-
 	/* Mark the expression const or volatile, as appropriate.
 	   Even though we've dealt with the type above, we still have
 	   to mark the expression itself.  */
@@ -1849,9 +1847,9 @@ determine_primary_bases (tree t)
 		 another hierarchy. As we're about to use it as a
 		 primary base, make sure the offsets match.  */
 	      delta = size_diffop_loc (input_location,
-				   convert (ssizetype,
+				   fold_convert (ssizetype,
 					    BINFO_OFFSET (base_binfo)),
-				   convert (ssizetype,
+				   fold_convert (ssizetype,
 					    BINFO_OFFSET (this_primary)));
 
 	      propagate_binfo_offsets (this_primary, delta);
@@ -1913,7 +1911,7 @@ determine_primary_bases (tree t)
 	     another hierarchy. As we're about to use it as a primary
 	     base, make sure the offsets match.  */
 	  delta = size_diffop_loc (input_location, ssize_int (0),
-			       convert (ssizetype, BINFO_OFFSET (primary)));
+			       fold_convert (ssizetype, BINFO_OFFSET (primary)));
 
 	  propagate_binfo_offsets (primary, delta);
 	}
@@ -2637,7 +2635,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
 	  if (virtual_offset
 	      || (thunk_binfo && !BINFO_OFFSET_ZEROP (thunk_binfo)))
 	    {
-	      tree offset = convert (ssizetype, BINFO_OFFSET (thunk_binfo));
+	      tree offset = fold_convert (ssizetype, BINFO_OFFSET (thunk_binfo));
 
 	      if (virtual_offset)
 		{
@@ -2645,7 +2643,7 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
 		     offset to be from there.  */
 		  offset = 
 		    size_diffop (offset,
-				 convert (ssizetype,
+				 fold_convert (ssizetype,
 					  BINFO_OFFSET (virtual_offset)));
 		}
 	      if (fixed_offset)
@@ -2734,8 +2732,8 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
     /* The `this' pointer needs to be adjusted from the declaration to
        the nearest virtual base.  */
     delta = size_diffop_loc (input_location,
-			 convert (ssizetype, BINFO_OFFSET (virtual_base)),
-			 convert (ssizetype, BINFO_OFFSET (first_defn)));
+			 fold_convert (ssizetype, BINFO_OFFSET (virtual_base)),
+			 fold_convert (ssizetype, BINFO_OFFSET (first_defn)));
   else if (lost)
     /* If the nearest definition is in a lost primary, we don't need an
        entry in our vtable.  Except possibly in a constructor vtable,
@@ -2747,9 +2745,9 @@ update_vtable_entry_for_fn (tree t, tree binfo, tree fn, tree* virtuals,
        BINFO to pointing at the base where the final overrider
        appears.  */
     delta = size_diffop_loc (input_location,
-			 convert (ssizetype,
+			 fold_convert (ssizetype,
 				  BINFO_OFFSET (TREE_VALUE (overrider))),
-			 convert (ssizetype, BINFO_OFFSET (binfo)));
+			 fold_convert (ssizetype, BINFO_OFFSET (binfo)));
 
   modify_vtable_entry (t, binfo, overrider_fn, delta, virtuals);
 
@@ -3471,7 +3469,7 @@ check_bitfield_decl (tree field)
 
   if (w != error_mark_node)
     {
-      DECL_SIZE (field) = convert (bitsizetype, w);
+      DECL_SIZE (field) = fold_convert (bitsizetype, w);
       DECL_BIT_FIELD (field) = 1;
       return true;
     }
@@ -4316,8 +4314,8 @@ layout_nonempty_base_or_field (record_layout_info rli,
        OFFSET.  */
     propagate_binfo_offsets (binfo,
 			     size_diffop_loc (input_location,
-					  convert (ssizetype, offset),
-					  convert (ssizetype,
+					  fold_convert (ssizetype, offset),
+					  fold_convert (ssizetype,
 						   BINFO_OFFSET (binfo))));
 }
 
@@ -4364,7 +4362,7 @@ layout_empty_base (record_layout_info rli, tree binfo,
       /* That didn't work.  Now, we move forward from the next
 	 available spot in the class.  */
       atend = true;
-      propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
+      propagate_binfo_offsets (binfo, fold_convert (ssizetype, eoc));
       while (1)
 	{
 	  if (!layout_conflict_p (binfo,
@@ -5978,9 +5976,9 @@ propagate_binfo_offsets (tree binfo, tree offset)
 
   /* Update BINFO's offset.  */
   BINFO_OFFSET (binfo)
-    = convert (sizetype,
+    = fold_convert (sizetype,
 	       size_binop (PLUS_EXPR,
-			   convert (ssizetype, BINFO_OFFSET (binfo)),
+			   fold_convert (ssizetype, BINFO_OFFSET (binfo)),
 			   offset));
 
   /* Find the primary base class.  */
@@ -6185,7 +6183,7 @@ include_empty_classes (record_layout_info rli)
 	= size_binop (PLUS_EXPR,
 		      rli->bitpos,
 		      size_binop (MULT_EXPR,
-				  convert (bitsizetype,
+				  fold_convert (bitsizetype,
 					   size_binop (MINUS_EXPR,
 						       eoc, rli_size)),
 				  bitsize_int (BITS_PER_UNIT)));
@@ -6459,7 +6457,7 @@ layout_class_type (tree t, tree *virtuals_p)
       eoc = end_of_class (t, /*include_virtuals_p=*/0);
       TYPE_SIZE_UNIT (base_t)
 	= size_binop (MAX_EXPR,
-		      convert (sizetype,
+		      fold_convert (sizetype,
 			       size_binop (CEIL_DIV_EXPR,
 					   rli_size_so_far (rli),
 					   bitsize_int (BITS_PER_UNIT))),
@@ -6468,7 +6466,7 @@ layout_class_type (tree t, tree *virtuals_p)
 	= size_binop (MAX_EXPR,
 		      rli_size_so_far (rli),
 		      size_binop (MULT_EXPR,
-				  convert (bitsizetype, eoc),
+				  fold_convert (bitsizetype, eoc),
 				  bitsize_int (BITS_PER_UNIT)));
       TYPE_ALIGN (base_t) = rli->record_align;
       TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
@@ -9304,7 +9302,7 @@ build_vbase_offset_vtbl_entries (tree binfo, vtbl_init_data* vid)
       /* Figure out where we can find this vbase offset.  */
       delta = size_binop (MULT_EXPR,
 			  vid->index,
-			  convert (ssizetype,
+			  fold_convert (ssizetype,
 				   TYPE_SIZE_UNIT (vtable_entry_type)));
       if (vid->primary_vtbl_p)
 	BINFO_VPTR_FIELD (b) = delta;
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 51fae5a..5bda494 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1037,6 +1037,8 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
   force_folding_builtin_constant_p = true;
   new_call = fold_build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
 					CALL_EXPR_FN (t), nargs, args);
+  /* Fold away the NOP_EXPR from fold_builtin_n.  */
+  new_call = fold (new_call);
   force_folding_builtin_constant_p = save_ffbcp;
   VERIFY_CONSTANT (new_call);
   return new_call;
@@ -1277,6 +1279,15 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
       ctx->values->put (new_ctx.object, ctor);
       ctx = &new_ctx;
     }
+  else if (DECL_BY_REFERENCE (DECL_RESULT (fun))
+	   && TREE_CODE (t) != AGGR_INIT_EXPR)
+    {
+      /* convert_to_void stripped our AGGR_INIT_EXPR, in which case we don't
+	 care about a constant value.  */
+      gcc_assert (ctx->quiet && !ctx->object);
+      *non_constant_p = true;
+      return t;
+    }
 
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
@@ -2542,6 +2553,17 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
   tree orig_op0 = TREE_OPERAND (t, 0);
   bool empty_base = false;
 
+  /* We can handle a MEM_REF like an INDIRECT_REF, if MEM_REF's second
+     operand is an integer-zero.  Otherwise reject the MEM_REF for now.  */
+
+  if (TREE_CODE (t) == MEM_REF
+      && (!TREE_OPERAND (t, 1) || !integer_zerop (TREE_OPERAND (t, 1))))
+    {
+      gcc_assert (ctx->quiet);
+      *non_constant_p = true;
+      return t;
+    }
+
   /* First try to simplify it directly.  */
   tree r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), orig_op0,
 				  &empty_base);
@@ -3075,6 +3097,8 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
   if (TREE_CODE (op00) != ADDR_EXPR)
     return NULL_TREE;
 
+  op01 = cxx_eval_constant_expression (ctx, op01, lval,
+				       non_constant_p, overflow_p);
   op00 = TREE_OPERAND (op00, 0);
 
   /* &A[i] p+ j => &A[i + j] */
@@ -3335,6 +3359,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
       /* These differ from cxx_eval_unary_expression in that this doesn't
 	 check for a constant operand or result; an address can be
 	 constant without its operand being, and vice versa.  */
+    case MEM_REF:
     case INDIRECT_REF:
       r = cxx_eval_indirect_ref (ctx, t, lval,
 				 non_constant_p, overflow_p);
@@ -3540,8 +3565,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
     case CONVERT_EXPR:
     case VIEW_CONVERT_EXPR:
     case NOP_EXPR:
+    case UNARY_PLUS_EXPR:
       {
+	enum tree_code tcode = TREE_CODE (t);
 	tree oldop = TREE_OPERAND (t, 0);
+
 	tree op = cxx_eval_constant_expression (ctx, oldop,
 						lval,
 						non_constant_p, overflow_p);
@@ -3561,11 +3589,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
 	    *non_constant_p = true;
 	    return t;
 	  }
-	if (op == oldop)
+	if (op == oldop && tcode != UNARY_PLUS_EXPR)
 	  /* We didn't fold at the top so we could check for ptr-int
 	     conversion.  */
 	  return fold (t);
-	r = fold_build1 (TREE_CODE (t), type, op);
+	if (tcode == UNARY_PLUS_EXPR)
+	  r = fold_convert (TREE_TYPE (t), op);
+	else
+	  r = fold_build1 (tcode, type, op);
 	/* Conversion of an out-of-range value has implementation-defined
 	   behavior; the language considers it different from arithmetic
 	   overflow, which is undefined.  */
@@ -3833,12 +3864,187 @@ cxx_constant_value (tree t, tree decl)
   return cxx_eval_outermost_constant_expr (t, false, true, decl);
 }
 
+/* Helper routine for fold_simple function.  Either return simplified
+   expression T, otherwise NULL_TREE.
+   In contrast to cp_fully_fold, and to maybe_constant_value, we try to fold
+   even if we are within template-declaration.  So be careful on call, as in
+   such case types can be undefined.  */
+
+static tree
+fold_simple_1 (tree t)
+{
+  tree op1, op2, op3;
+  enum tree_code code = TREE_CODE (t);
+
+  if (code == VAR_DECL)
+    return NULL_TREE;
+
+  switch (code)
+    {
+    case INTEGER_CST:
+    case REAL_CST:
+    case VECTOR_CST:
+    case FIXED_CST:
+    case COMPLEX_CST:
+      return t;
+
+    case SIZEOF_EXPR:
+      if (SIZEOF_EXPR_TYPE_P (t))
+        t = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (t, 0)),
+                                        SIZEOF_EXPR, false);
+      else if (TYPE_P (TREE_OPERAND (t, 0)))
+        t = cxx_sizeof_or_alignof_type (TREE_OPERAND (t, 0),
+                                        SIZEOF_EXPR, false);
+      else
+        t = cxx_sizeof_or_alignof_expr (TREE_OPERAND (t, 0),
+                                        SIZEOF_EXPR, false);
+      if (t == error_mark_node)
+        t = size_one_node;
+      break;
+
+    case ABS_EXPR:
+    case CONJ_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case NEGATE_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case NOP_EXPR:
+    case VIEW_CONVERT_EXPR:
+    case CONVERT_EXPR:
+    case FLOAT_EXPR:
+    case FIX_TRUNC_EXPR:
+    case FIXED_CONVERT_EXPR:
+    case ADDR_SPACE_CONVERT_EXPR:
+
+      op1 = fold_simple_1 (TREE_OPERAND (t, 0));
+      if (!op1 || (code == NOP_EXPR && TREE_OVERFLOW (op1)))
+	return NULL_TREE;
+
+      t = const_unop (code, TREE_TYPE (t), op1);
+      if (!t)
+	return NULL_TREE;
+
+      if (CONVERT_EXPR_CODE_P (code)
+	  && TREE_OVERFLOW_P (t) && !TREE_OVERFLOW_P (op1))
+	TREE_OVERFLOW (t) = false;
+      break;
+
+    case BIT_AND_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case TRUNC_MOD_EXPR:
+    case CEIL_MOD_EXPR:
+    case ROUND_MOD_EXPR:
+    case RDIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case MIN_EXPR:
+    case MAX_EXPR:
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+    case LROTATE_EXPR:
+    case RROTATE_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_XOR_EXPR:
+    case LT_EXPR: case LE_EXPR:
+    case GT_EXPR: case GE_EXPR:
+    case EQ_EXPR: case NE_EXPR:
+    case UNORDERED_EXPR: case ORDERED_EXPR:
+    case UNLT_EXPR: case UNLE_EXPR:
+    case UNGT_EXPR: case UNGE_EXPR:
+    case UNEQ_EXPR: case LTGT_EXPR:
+
+      op1 = fold_simple_1 (TREE_OPERAND (t, 0));
+      op2 = fold_simple_1 (TREE_OPERAND (t, 1));
+
+      if (!op1 && !op2)
+	return NULL_TREE;
+      if (!op1)
+	op1 = TREE_OPERAND (t, 0);
+      if (!op2)
+	op2 = TREE_OPERAND (t, 1);
+
+      t = fold_build2_loc (EXPR_LOCATION (t), code, TREE_TYPE (t),
+			   op1, op2);
+      break;
+
+    case VEC_COND_EXPR:
+    case COND_EXPR:
+
+      if (VOID_TYPE_P (TREE_TYPE (t)))
+	return NULL_TREE;
+
+      op1 = TREE_OPERAND (t, 0);
+      op1 = fold_simple_1 (op1);
+      op2 = TREE_OPERAND (t, 1);
+      op3 = TREE_OPERAND (t, 2);
+      if (!op1)
+	return NULL_TREE;
+      op1 = fold (build3 (code, TREE_TYPE (t), op1, op2, op3));
+
+      /* We need to recurse into result, if CODE isn't
+         a COND-expression.  */
+      if (TREE_CODE (op1) != code)
+	return fold_simple_1 (op1);
+      return NULL_TREE;
+
+    default:
+      return NULL_TREE;
+    }
+
+  /* Just return folded expression if we got as result
+     a CST-expression.  */
+  switch (TREE_CODE (t))
+    {
+    case STRING_CST:
+    case INTEGER_CST:
+    case REAL_CST:
+    case VECTOR_CST:
+    case FIXED_CST:
+    case COMPLEX_CST:
+      break;
+    default:
+      return NULL_TREE;
+    }
+
+  return t;
+}
+
+/* If T is a simple constant expression, returns its simplified value.
+   Otherwise returns T.  In contrast to maybe_constant_value do we
+   simplify only few operations on constant-expressions, and we don't
+   try to simplify constexpressions.  */
+
+tree
+fold_simple (tree t)
+{
+  tree r = NULL_TREE;
+  if (processing_template_decl)
+    return t;
+
+  r = fold_simple_1 (t);
+  if (!r)
+    r = t;
+
+  return r;
+}
+
 /* If T is a constant expression, returns its reduced value.
    Otherwise, if T does not have TREE_CONSTANT set, returns T.
    Otherwise, returns a version of T without TREE_CONSTANT.  */
 
-tree
-maybe_constant_value (tree t, tree decl)
+static tree
+maybe_constant_value_1 (tree t, tree decl)
 {
   tree r;
 
@@ -3864,6 +4070,56 @@ maybe_constant_value (tree t, tree decl)
   return r;
 }
 
+/* If T is a constant expression, returns its reduced value.
+   Otherwise, if T does not have TREE_CONSTANT set, returns T.
+   Otherwise, returns a version of T without TREE_CONSTANT.  */
+
+tree
+maybe_constant_value (tree t, tree decl)
+{
+  tree ret;
+  hash_map<tree, tree> *ctx = (scope_chain ? scope_chain->fold_map : NULL);
+  hash_map<tree, tree> *cv = (scope_chain ? scope_chain->cv_map : NULL);
+
+  /* If current scope has a hash_map, but it was for different CFUN,
+     then destroy hash_map to avoid issues with ggc_collect.  */
+  if ((cv || ctx) && scope_chain->act_cfun != cfun)
+    {
+      if (ctx)
+	delete ctx;
+      if (cv)
+	delete cv;
+      ctx = NULL;
+      scope_chain->act_cfun = NULL;
+      scope_chain->fold_map = NULL;
+      scope_chain->cv_map = NULL;
+    }
+  if (cv && scope_chain && cfun)
+    {
+      cv = scope_chain->cv_map = new hash_map <tree, tree>;
+      scope_chain->act_cfun = cfun;
+    }
+
+  if (cv)
+    {
+      tree *slot = cv->get (t);
+      if (slot && *slot)
+	return *slot;
+    }
+
+  ret = maybe_constant_value_1 (t, decl);
+
+  if (cv)
+    {
+      /* We don't need to cache RET, as it is a
+	 constant-value if it differs.  */
+      tree *slot = &cv->get_or_insert (t);
+      *slot = ret;
+    }
+
+  return ret;
+}
+
 /* Like maybe_constant_value but first fully instantiate the argument.
 
    Note: this is equivalent to instantiate_non_dependent_expr_sfinae
@@ -3929,6 +4185,8 @@ fold_non_dependent_expr (tree t)
 tree
 maybe_constant_init (tree t, tree decl)
 {
+  if (!t)
+    return t;
   if (TREE_CODE (t) == EXPR_STMT)
     t = TREE_OPERAND (t, 0);
   if (TREE_CODE (t) == CONVERT_EXPR
@@ -4039,6 +4297,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
       /* We can see a FIELD_DECL in a pointer-to-member expression.  */
     case FIELD_DECL:
     case PARM_DECL:
+    case RESULT_DECL:
     case USING_DECL:
     case USING_STMT:
     case PLACEHOLDER_EXPR:
@@ -4627,6 +4886,9 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict,
       /* We can see these in statement-expressions.  */
       return true;
 
+    case EMPTY_CLASS_EXPR:
+      return false;
+
     default:
       if (objc_is_property_ref (t))
 	return false;
diff --git a/gcc/cp/cp-array-notation.c b/gcc/cp/cp-array-notation.c
index 9fd348c..e967c72 100644
--- a/gcc/cp/cp-array-notation.c
+++ b/gcc/cp/cp-array-notation.c
@@ -1382,7 +1382,12 @@ build_array_notation_ref (location_t loc, tree array, tree start, tree length,
     
   if (!stride) 
     stride = build_one_cst (ptrdiff_type_node);
-  
+
+  stride = maybe_constant_value (stride);
+  length = maybe_constant_value (length);
+  if (start)
+    start = maybe_constant_value (start);
+
   /* When dealing with templates, triplet type-checking will be done in pt.c 
      after type substitution.  */
   if (processing_template_decl 
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index e4b50e5..c14ddce 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -41,7 +41,9 @@ along with GCC; see the file COPYING3.  If not see
 /* Forward declarations.  */
 
 static tree cp_genericize_r (tree *, int *, void *);
+static tree cp_fold_r (tree *, int *, void *);
 static void cp_genericize_tree (tree*);
+static tree cp_fold (tree, hash_map<tree, tree> *);
 
 /* Local declarations.  */
 
@@ -181,13 +183,13 @@ genericize_eh_spec_block (tree *stmt_p)
 /* Genericize an IF_STMT by turning it into a COND_EXPR.  */
 
 static void
-genericize_if_stmt (tree *stmt_p)
+genericize_if_stmt (tree *stmt_p, hash_map<tree, tree> *fold_hash)
 {
   tree stmt, cond, then_, else_;
   location_t locus = EXPR_LOCATION (*stmt_p);
 
   stmt = *stmt_p;
-  cond = IF_COND (stmt);
+  cond = cp_fold (IF_COND (stmt), fold_hash);
   then_ = THEN_CLAUSE (stmt);
   else_ = ELSE_CLAUSE (stmt);
 
@@ -916,9 +918,76 @@ struct cp_genericize_data
   vec<tree> bind_expr_stack;
   struct cp_genericize_omp_taskreg *omp_ctx;
   tree try_block;
+  hash_map<tree, tree> *fold_hash;
   bool no_sanitize_p;
 };
 
+/* Perform any pre-gimplification folding of C++ front end trees to
+   GENERIC.
+   Note:  The folding of none-omp cases is something to move into
+     the middle-end.  As for now we have most foldings only on GENERIC
+     in fold-const, we need to perform this before transformation to
+     GIMPLE-form.  */
+
+static tree
+cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data)
+{
+  tree stmt;
+  struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
+  enum tree_code code;
+
+  *stmt_p = stmt = cp_fold (*stmt_p, wtd->fold_hash);
+
+  code = TREE_CODE (stmt);
+  if (code == OMP_FOR || code == OMP_SIMD || code == OMP_DISTRIBUTE
+      || code == OMP_TASKLOOP || code == CILK_FOR || code == CILK_SIMD)
+    {
+      tree x;
+      int i, n;
+
+      cp_walk_tree (&OMP_FOR_BODY (stmt), cp_fold_r, data, NULL);
+      cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_fold_r, data, NULL);
+      cp_walk_tree (&OMP_FOR_INIT (stmt), cp_fold_r, data, NULL);
+      x = OMP_FOR_COND (stmt);
+      if (x && TREE_CODE_CLASS (TREE_CODE (x)) == tcc_comparison)
+	{
+	  cp_walk_tree (&TREE_OPERAND (x, 0), cp_fold_r, data, NULL);
+	  cp_walk_tree (&TREE_OPERAND (x, 1), cp_fold_r, data, NULL);
+	} 
+      else if (x && TREE_CODE (x) == TREE_VEC)
+	{
+	  n = TREE_VEC_LENGTH (x);
+	  for (i = 0; i < n; i++)
+	    {
+	      tree o = TREE_VEC_ELT (x, i);
+	      if (o && TREE_CODE_CLASS (TREE_CODE (o)) == tcc_comparison)
+		cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
+	    }
+	}
+      x = OMP_FOR_INCR (stmt);
+      if (x && TREE_CODE (x) == TREE_VEC)
+	{
+	  n = TREE_VEC_LENGTH (x);
+	  for (i = 0; i < n; i++)
+	    {
+	      tree o = TREE_VEC_ELT (x, i);
+	      if (o && TREE_CODE (o) == MODIFY_EXPR)
+		o = TREE_OPERAND (o, 1);
+	      if (o && (TREE_CODE (o) == PLUS_EXPR || TREE_CODE (o) == MINUS_EXPR
+			|| TREE_CODE (o) == POINTER_PLUS_EXPR))
+		{
+		  cp_walk_tree (&TREE_OPERAND (o, 0), cp_fold_r, data, NULL);
+		  cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
+		}
+	    }
+	}
+      cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_fold_r, data, NULL);
+      *walk_subtrees = 0;
+    }
+
+  return NULL;
+}
+
 /* Perform any pre-gimplification lowering of C++ front end trees to
    GENERIC.  */
 
@@ -978,7 +1047,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
       if (__builtin_expect (wtd->omp_ctx != NULL, 0)
 	  && omp_var_to_track (TREE_OPERAND (stmt, 0)))
 	omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0));
-      *stmt_p = convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
+      *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
       *walk_subtrees = 0;
     }
   else if (TREE_CODE (stmt) == RETURN_EXPR
@@ -1058,7 +1127,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
 
   else if (TREE_CODE (stmt) == IF_STMT)
     {
-      genericize_if_stmt (stmt_p);
+      genericize_if_stmt (stmt_p, wtd->fold_hash);
       /* *stmt_p has changed, tail recurse to handle it again.  */
       return cp_genericize_r (stmt_p, walk_subtrees, data);
     }
@@ -1307,6 +1376,7 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
 					      SIZEOF_EXPR, false);
       if (*stmt_p == error_mark_node)
 	*stmt_p = size_one_node;
+      *stmt_p = cp_fold (*stmt_p,  wtd->fold_hash);
       return NULL;
     }
   else if ((flag_sanitize
@@ -1349,12 +1419,15 @@ cp_genericize_tree (tree* t_p)
 {
   struct cp_genericize_data wtd;
 
+  wtd.fold_hash = new hash_map<tree, tree>;
   wtd.p_set = new hash_set<tree>;
   wtd.bind_expr_stack.create (0);
   wtd.omp_ctx = NULL;
   wtd.try_block = NULL_TREE;
   wtd.no_sanitize_p = false;
   cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
+  cp_walk_tree (t_p, cp_fold_r, &wtd, NULL);
+  delete wtd.fold_hash;
   delete wtd.p_set;
   wtd.bind_expr_stack.release ();
   if (flag_sanitize & SANITIZE_VPTR)
@@ -1782,3 +1855,483 @@ cxx_omp_disregard_value_expr (tree decl, bool shared)
 	 && DECL_LANG_SPECIFIC (decl)
 	 && DECL_OMP_PRIVATIZED_MEMBER (decl);
 }
+
+/* Callback for walk_tree, looking for LABEL_EXPR.  Return *TP if it is
+   a LABEL_EXPR; otherwise return NULL_TREE.  Do not check the subtrees
+   of GOTO_EXPR.  */
+
+static tree
+contains_label_1 (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
+{
+  switch (TREE_CODE (*tp))
+    {
+    case LABEL_EXPR:
+      return *tp;
+
+    case GOTO_EXPR:
+      *walk_subtrees = 0;
+
+      /* ... fall through ...  */
+
+    default:
+      return NULL_TREE;
+    }
+}
+
+/* Return whether the sub-tree ST contains a label which is accessible from
+   outside the sub-tree.  */
+
+static bool
+contains_label_p (tree st)
+{
+  return
+   walk_tree_without_duplicates (&st, contains_label_1 , NULL) != NULL_TREE;
+}
+
+/* Perform folding on expression X.  */
+
+tree
+cp_fully_fold (tree x)
+{
+  hash_map<tree, tree> *ctx = (scope_chain ? scope_chain->fold_map : NULL);
+  hash_map<tree, tree> *cv = (scope_chain ? scope_chain->cv_map : NULL);
+
+  /* If current scope has a hash_map, but it was for different CFUN,
+     then destroy hash_map to avoid issues with ggc_collect.  */
+  if ((cv || ctx) && scope_chain->act_cfun != cfun)
+    {
+      if (ctx)
+	delete ctx;
+      if (cv)
+	delete cv;
+      ctx = NULL;
+      scope_chain->act_cfun = NULL;
+      scope_chain->fold_map = NULL;
+      scope_chain->cv_map = NULL;
+    }
+
+  /* If there is no hash_map, but there is a scope, and a set CFUN,
+     then create the hash_map for scope.  */
+  if (!ctx && scope_chain && cfun)
+    {
+      ctx = scope_chain->fold_map = new hash_map <tree, tree>;
+      scope_chain->act_cfun = cfun;
+    }
+  /* Otherwise if there is no hash_map, use for folding temporary
+     hash_map.  */
+  else if (!ctx)
+    {
+      hash_map<tree, tree> fold_hash;
+      return cp_fold (x, &fold_hash);
+    }
+
+  return cp_fold (x, ctx);
+}
+
+/*  This function tries to fold given expression X in GENERIC-form.
+    For performance-reason, and for avoiding endless-recursion the
+    function uses given tree-hash FOLD_HASH.
+    If FOLD_HASH is 0, or we are processing within template-declaration,
+    or X is no valid expression, or has no valid type, we don't fold at all.
+    For performance-reason we don't hash on expressions representing a
+    declaration, or being of constant-class.
+    Function returns X, or its folded variant.  */
+
+static tree
+cp_fold (tree x, hash_map<tree, tree> *fold_hash)
+{
+  tree *slot, op0, op1, op2, op3;
+  tree org_x = x, r = NULL_TREE;
+  enum tree_code code;
+  location_t loc;
+
+  if (!x || x == error_mark_node)
+    return x;
+
+  if (!fold_hash
+      || processing_template_decl
+      || (EXPR_P (x) && !TREE_TYPE (x)))
+    return x;
+
+  /* Don't even try to hash on DECLs or constants.  */
+  if (DECL_P (x) || CONSTANT_CLASS_P (x))
+    return x;
+
+  slot = fold_hash->get (x);
+  if (slot && *slot)
+    return *slot;
+
+  code = TREE_CODE (x);
+  switch (code)
+    {
+    case SIZEOF_EXPR:
+      if (SIZEOF_EXPR_TYPE_P (x))
+	  r = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (x, 0)),
+					  SIZEOF_EXPR, false);
+      else if (TYPE_P (TREE_OPERAND (x, 0)))
+	r = cxx_sizeof_or_alignof_type (TREE_OPERAND (x, 0),
+					SIZEOF_EXPR, false);
+      else
+	r = cxx_sizeof_or_alignof_expr (TREE_OPERAND (x, 0),
+					SIZEOF_EXPR, false);
+      if (r == error_mark_node)
+	r = size_one_node;
+      x = r;
+      break;
+
+    case VIEW_CONVERT_EXPR:
+    case CONVERT_EXPR:
+    case NOP_EXPR:
+
+      if (VOID_TYPE_P (TREE_TYPE (x)))
+	return x;
+
+      if (!TREE_OPERAND (x, 0)
+	  || TREE_CODE (TREE_OPERAND (x, 0)) == NON_LVALUE_EXPR)
+	return x;
+
+      loc = EXPR_LOCATION (x);
+      op0 = TREE_OPERAND (x, 0);
+
+      if (TREE_CODE (x) == NOP_EXPR
+	  && TREE_OVERFLOW_P (op0)
+	  && TREE_TYPE (x) == TREE_TYPE (op0))
+	return x;
+
+      op0 = cp_fold (op0, fold_hash);
+
+      if (op0 != TREE_OPERAND (x, 0))
+        x = build1_loc (loc, code, TREE_TYPE (x), op0);
+
+      x = fold (x);
+
+      /* Conversion of an out-of-range value has implementation-defined
+	 behavior; the language considers it different from arithmetic
+	 overflow, which is undefined.  */
+      if (TREE_CODE (op0) == INTEGER_CST
+	  && TREE_OVERFLOW_P (x) && !TREE_OVERFLOW_P (op0))
+	TREE_OVERFLOW (x) = false;
+      
+      break;
+
+    case ALIGNOF_EXPR:
+    case SAVE_EXPR:
+    case ADDR_EXPR:
+    case REALPART_EXPR:
+    case IMAGPART_EXPR:
+    case CONJ_EXPR:
+    case FIX_TRUNC_EXPR:
+    case FLOAT_EXPR:
+    case NEGATE_EXPR:
+    case ABS_EXPR:
+    case BIT_NOT_EXPR:
+    case TRUTH_NOT_EXPR:
+    case FIXED_CONVERT_EXPR:
+    case UNARY_PLUS_EXPR:
+    case CLEANUP_POINT_EXPR:
+    case INDIRECT_REF:
+    /* case NON_LVALUE_EXPR: */
+    case RETURN_EXPR:
+    case EXPR_STMT:
+    case STMT_EXPR:
+    case GOTO_EXPR:
+    case EXIT_EXPR:
+    case LOOP_EXPR:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+
+      if (op0 != TREE_OPERAND (x, 0))
+        x = build1_loc (loc, code, TREE_TYPE (x), op0);
+
+      x = fold (x);
+
+      gcc_assert (TREE_CODE (x) != COND_EXPR
+		  || !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))));
+      break;
+
+    case POSTDECREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+    case INIT_EXPR:
+
+	loc = EXPR_LOCATION (x);
+	op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+	op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+
+	if (TREE_OPERAND (x, 0) != op0 || TREE_OPERAND (x, 1) != op1)
+	  x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
+
+	break;
+
+    case PREDECREMENT_EXPR:
+    case PREINCREMENT_EXPR:
+    case COMPOUND_EXPR:
+    case POINTER_PLUS_EXPR:
+    case PLUS_EXPR:
+    case MINUS_EXPR:
+    case MULT_EXPR:
+    case TRUNC_DIV_EXPR:
+    case CEIL_DIV_EXPR:
+    case FLOOR_DIV_EXPR:
+    case ROUND_DIV_EXPR:
+    case TRUNC_MOD_EXPR:
+    case CEIL_MOD_EXPR:
+    case ROUND_MOD_EXPR:
+    case RDIV_EXPR:
+    case EXACT_DIV_EXPR:
+    case MIN_EXPR:
+    case MAX_EXPR:
+    case LSHIFT_EXPR:
+    case RSHIFT_EXPR:
+    case LROTATE_EXPR:
+    case RROTATE_EXPR:
+    case BIT_AND_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_XOR_EXPR:
+    case LT_EXPR: case LE_EXPR:
+    case GT_EXPR: case GE_EXPR:
+    case EQ_EXPR: case NE_EXPR:
+    case UNORDERED_EXPR: case ORDERED_EXPR:
+    case UNLT_EXPR: case UNLE_EXPR:
+    case UNGT_EXPR: case UNGE_EXPR:
+    case UNEQ_EXPR: case LTGT_EXPR:
+    case RANGE_EXPR: case COMPLEX_EXPR:
+    case MODIFY_EXPR:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+      op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+      if ((code == COMPOUND_EXPR || code == MODIFY_EXPR)
+	  && ((op1 && TREE_SIDE_EFFECTS (op1))
+	       || (op0 && TREE_SIDE_EFFECTS (op0))))
+	break;
+      if (TREE_CODE (x) == COMPOUND_EXPR && !op0)
+	op0 = build_empty_stmt (loc);
+
+      if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
+	x = build2_loc (loc, code, TREE_TYPE (x), op0, op1);
+
+      x = fold (x);
+
+      if (TREE_CODE (x) == COMPOUND_EXPR && TREE_OPERAND (x, 0) == NULL_TREE
+	  && TREE_OPERAND (x, 1))
+	return TREE_OPERAND (x, 1);
+      break;
+
+    case VEC_COND_EXPR:
+    case COND_EXPR:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+
+      if (TREE_SIDE_EFFECTS (op0))
+	break;
+
+      op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+      op2 = cp_fold (TREE_OPERAND (x, 2), fold_hash);
+
+      if (TREE_CODE (op0) == INTEGER_CST)
+	{
+	  tree un;
+
+	  if (integer_zerop (op0))
+	    {
+	      un = op1;
+	      r = op2;
+	    }
+	  else
+	    {
+	      un = op2;
+	      r = op1;
+	    }
+
+          if ((!TREE_SIDE_EFFECTS (un) || !contains_label_p (un))
+              && (! VOID_TYPE_P (TREE_TYPE (r)) || VOID_TYPE_P (x)))
+            {
+	      if (CAN_HAVE_LOCATION_P (r)
+		  && EXPR_LOCATION (r) != loc
+		  && !(TREE_CODE (r) == SAVE_EXPR
+		       || TREE_CODE (r) == TARGET_EXPR
+		       || TREE_CODE (r) == BIND_EXPR))
+	        {
+		  r = copy_node (r);
+		  SET_EXPR_LOCATION (r, loc);
+	        }
+	      x = r;
+	    }
+
+	  break;
+	}
+
+      if (VOID_TYPE_P (TREE_TYPE (x)))
+	break;
+
+      x = build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
+
+      if (code != COND_EXPR)
+	x = fold (x);
+
+      break;
+
+    case CALL_EXPR:
+      {
+	int i, m, sv = optimize, nw = sv, changed = 0;
+	tree callee = get_callee_fndecl (x);
+
+	if (callee && DECL_BUILT_IN (callee) && !optimize
+	    && DECL_IS_BUILTIN_CONSTANT_P (callee)
+	    && current_function_decl
+	    && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
+	  nw = 1;
+	optimize = nw;
+	r = fold (x);
+	optimize = sv;
+
+	if (TREE_CODE (r) != CALL_EXPR)
+	  {
+	    x = cp_fold (r, fold_hash);
+	    break;
+	  }
+
+	x = copy_node (x);
+
+	m = call_expr_nargs (x);
+	for (i = 0; i < m; i++)
+	  {
+	    r = cp_fold (CALL_EXPR_ARG (x, i), fold_hash);
+	    if (r != CALL_EXPR_ARG (x, i))
+	      changed = 1;
+	    CALL_EXPR_ARG (x, i) = r;
+	  }
+
+	optimize = nw;
+	r = fold (x);
+	optimize = sv;
+
+	if (TREE_CODE (r) != CALL_EXPR)
+	  {
+	    x = cp_fold (r, fold_hash);
+	    break;
+	  }
+
+	optimize = nw;
+
+	/* Invoke maybe_constant_value for functions being declared
+	   constexpr, and are no AGGR_INIT_EXPRs ...
+	   TODO:
+	   Due issues in maybe_constant_value for CALL_EXPR with
+	   arguments passed by reference, it is disabled.  */
+	if (callee && DECL_DECLARED_CONSTEXPR_P (callee))
+          r = maybe_constant_value (x);
+	optimize = sv;
+
+        if (TREE_CODE (r) != CALL_EXPR)
+	  {
+	    x = r;
+	    break;
+	  }
+
+	if (!changed)
+	  x = org_x;
+	break;
+      }
+
+    case BIND_EXPR:
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+      op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+      op2 = cp_fold (TREE_OPERAND (x, 2), fold_hash);
+
+      if (TREE_OPERAND (x, 0) != op0 || TREE_OPERAND (x, 1) != op1 || TREE_OPERAND (x, 2) != op2)
+	{
+	  x = copy_node (x);
+	  TREE_OPERAND (x, 0) = op0;
+	  TREE_OPERAND (x, 1) = op1;
+	  TREE_OPERAND (x, 2) = op2;
+	}
+      break;
+
+    case CONSTRUCTOR:
+      {
+	unsigned i;
+	constructor_elt *p;
+	vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (x);
+	FOR_EACH_VEC_SAFE_ELT (elts, i, p)
+	  p->value = cp_fold (p->value, fold_hash);
+	break;
+      }
+    case TREE_VEC:
+      {
+	bool changed = false;
+	vec<tree, va_gc> *vec = make_tree_vector ();
+	int i, n = TREE_VEC_LENGTH (x);
+	vec_safe_reserve (vec, n);
+
+	for (i = 0; i < n; i++)
+	  {
+	    tree op = cp_fold (TREE_VEC_ELT (x, i), fold_hash);
+	    vec->quick_push (op);
+	    if (op != TREE_VEC_ELT (x, i))
+	      changed = true;
+	  }
+
+	if (changed)
+	  {
+	    r = copy_node (x);
+	    for (i = 0; i < n; i++)
+	      TREE_VEC_ELT (r, i) = (*vec)[i];
+	    x = r;
+	  }
+
+	release_tree_vector (vec);
+      }
+
+      break;
+
+    case ARRAY_REF:
+    case ARRAY_RANGE_REF:
+
+      loc = EXPR_LOCATION (x);
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+      op1 = cp_fold (TREE_OPERAND (x, 1), fold_hash);
+      op2 = cp_fold (TREE_OPERAND (x, 2), fold_hash);
+      op3 = cp_fold (TREE_OPERAND (x, 3), fold_hash);
+
+      if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1)
+	  || op2 != TREE_OPERAND (x, 2) || op3 != TREE_OPERAND (x, 3))
+	x = build4_loc (loc, code, TREE_TYPE (x), op0, op1, op2, op3);
+
+      x = fold (x);
+      break;
+
+    case DECL_EXPR:
+
+      op0 = cp_fold (TREE_OPERAND (x, 0), fold_hash);
+
+      if (op0 == TREE_OPERAND (x, 0))
+	break;
+
+      x = copy_node (x);
+      TREE_OPERAND (x, 0) = op0;
+      break;
+
+    default:
+      return org_x;
+    }
+
+  slot = &fold_hash->get_or_insert (org_x);
+  *slot = x;
+
+  /* Prevent that we try to fold an already folded result again.  */
+  if (x != org_x)
+    {
+      slot = &fold_hash->get_or_insert (x);
+      *slot = x;
+    }
+
+  return x;
+}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 828f268..5fc017a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1239,6 +1239,11 @@ struct GTY(()) saved_scope {
 
   hash_map<tree, tree> *GTY((skip)) x_local_specializations;
 
+  hash_map<tree, tree> *GTY((skip)) fold_map;
+  hash_map<tree, tree> *GTY((skip)) cv_map;
+
+  struct function *GTY((skip)) act_cfun;
+
   struct saved_scope *prev;
 };
 
@@ -6474,7 +6479,6 @@ extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
 	walk_tree_1 (tp, func, data, pset, cp_walk_subtrees)
 #define cp_walk_tree_without_duplicates(tp,func,data) \
 	walk_tree_without_duplicates_1 (tp, func, data, cp_walk_subtrees)
-extern tree fold_if_not_in_template		(tree);
 extern tree rvalue				(tree);
 extern tree convert_bitfield_to_declared_type   (tree);
 extern tree cp_save_expr			(tree);
@@ -6705,6 +6709,7 @@ extern tree cxx_omp_clause_dtor			(tree, tree);
 extern void cxx_omp_finish_clause		(tree, gimple_seq *);
 extern bool cxx_omp_privatize_by_reference	(const_tree);
 extern bool cxx_omp_disregard_value_expr	(tree, bool);
+extern tree cp_fully_fold			(tree);
 
 /* in name-lookup.c */
 extern void suggest_alternatives_for            (location_t, tree);
@@ -6796,6 +6801,7 @@ extern tree cxx_constant_value			(tree, tree = NULL_TREE);
 extern tree maybe_constant_value		(tree, tree = NULL_TREE);
 extern tree maybe_constant_init			(tree, tree = NULL_TREE);
 extern tree fold_non_dependent_expr		(tree);
+extern tree fold_simple				(tree);
 extern bool is_sub_constant_expr                (tree);
 extern bool reduced_constant_expression_p       (tree);
 extern bool is_instantiation_of_constexpr       (tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index e764ee1..51b992c 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -53,7 +53,7 @@ static void diagnose_ref_binding (location_t, tree, tree, tree);
 
    Here is a list of all the functions that assume that widening and
    narrowing is always done with a NOP_EXPR:
-     In convert.c, convert_to_integer.
+     In convert.c, convert_to_integer[_nofold].
      In c-typeck.c, build_binary_op_nodefault (boolean ops),
 	and c_common_truthvalue_conversion.
      In expr.c: expand_expr, for operands of a MULT_EXPR.
@@ -240,7 +240,7 @@ cp_convert_to_pointer (tree type, tree expr, tsubst_flags_t complain)
       gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
 		  == GET_MODE_SIZE (TYPE_MODE (type)));
 
-      return convert_to_pointer (type, expr);
+      return convert_to_pointer_nofold (type, expr);
     }
 
   if (type_unknown_p (expr))
@@ -608,6 +608,7 @@ cp_fold_convert (tree type, tree expr)
       conv = fold_convert (type, expr);
       conv = ignore_overflows (conv, expr);
     }
+
   return conv;
 }
 
@@ -633,7 +634,8 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
 
   if (TREE_TYPE (expr) == type)
     return expr;
-  
+  if (expr == error_mark_node)
+    return expr;
   result = cp_convert (type, expr, complain);
 
   if ((complain & tf_warning)
@@ -641,13 +643,14 @@ cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain)
     {
       tree folded = maybe_constant_value (expr);
       tree stripped = folded;
-      tree folded_result
+      tree folded_result;
+      folded_result
 	= folded != expr ? cp_convert (type, folded, complain) : result;
-
-      /* maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW in a
-	 NOP_EXPR so that it isn't TREE_CONSTANT anymore.  */
+      folded_result = cp_fully_fold (folded_result);
+      /* The maybe_constant_value wraps an INTEGER_CST with TREE_OVERFLOW
+	 in a NOP_EXPR so that it isn't TREE_CONSTANT anymore.  */
       STRIP_NOPS (stripped);
-
+      folded = cp_fully_fold (folded);
       if (!TREE_OVERFLOW_P (stripped)
 	  && folded_result != error_mark_node)
 	warnings_for_convert_and_check (input_location, type, folded,
@@ -706,9 +709,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       /* For complex data types, we need to perform componentwise
 	 conversion.  */
       else if (TREE_CODE (type) == COMPLEX_TYPE)
-	return fold_if_not_in_template (convert_to_complex (type, e));
+	return convert_to_complex_nofold (type, e);
       else if (VECTOR_TYPE_P (type))
-	return fold_if_not_in_template (convert_to_vector (type, e));
+	return convert_to_vector (type, e);
       else if (TREE_CODE (e) == TARGET_EXPR)
 	{
 	  /* Don't build a NOP_EXPR of class type.  Instead, change the
@@ -721,7 +724,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 	  /* We shouldn't be treating objects of ADDRESSABLE type as
 	     rvalues.  */
 	  gcc_assert (!TREE_ADDRESSABLE (type));
-	  return fold_if_not_in_template (build_nop (type, e));
+	  return build_nop (type, e);
 	}
     }
 
@@ -799,7 +802,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 	  return cp_truthvalue_conversion (e);
 	}
 
-      converted = fold_if_not_in_template (convert_to_integer (type, e));
+      converted = convert_to_integer_nofold (type, e);
 
       /* Ignore any integer overflow caused by the conversion.  */
       return ignore_overflows (converted, e);
@@ -811,7 +814,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
       return nullptr_node;
     }
   if (POINTER_TYPE_P (type) || TYPE_PTRMEM_P (type))
-    return fold_if_not_in_template (cp_convert_to_pointer (type, e, complain));
+    return cp_convert_to_pointer (type, e, complain);
   if (code == VECTOR_TYPE)
     {
       tree in_vtype = TREE_TYPE (e);
@@ -826,7 +829,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 		      in_vtype, type);
 	  return error_mark_node;
 	}
-      return fold_if_not_in_template (convert_to_vector (type, e));
+      return convert_to_vector (type, e);
     }
   if (code == REAL_TYPE || code == COMPLEX_TYPE)
     {
@@ -842,9 +845,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
 		      TREE_TYPE (e));
 	}
       if (code == REAL_TYPE)
-	return fold_if_not_in_template (convert_to_real (type, e));
+	return convert_to_real_nofold (type, e);
       else if (code == COMPLEX_TYPE)
-	return fold_if_not_in_template (convert_to_complex (type, e));
+	return convert_to_complex_nofold (type, e);
     }
 
   /* New C++ semantics:  since assignment is now based on
@@ -1457,7 +1460,7 @@ convert (tree type, tree expr)
   intype = TREE_TYPE (expr);
 
   if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
-    return fold_if_not_in_template (build_nop (type, expr));
+    return build_nop (type, expr);
 
   return ocp_convert (type, expr, CONV_OLD_CONVERT,
 		      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
@@ -1475,13 +1478,11 @@ convert_force (tree type, tree expr, int convtype, tsubst_flags_t complain)
   enum tree_code code = TREE_CODE (type);
 
   if (code == REFERENCE_TYPE)
-    return (fold_if_not_in_template
-	    (convert_to_reference (type, e, CONV_C_CAST, 0,
-				   NULL_TREE, complain)));
+    return convert_to_reference (type, e, CONV_C_CAST, 0,
+				 NULL_TREE, complain);
 
   if (code == POINTER_TYPE)
-    return fold_if_not_in_template (convert_to_pointer_force (type, e,
-							      complain));
+    return convert_to_pointer_force (type, e, complain);
 
   /* From typeck.c convert_for_assignment */
   if (((TYPE_PTR_P (TREE_TYPE (e)) && TREE_CODE (e) == ADDR_EXPR
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bd3f2bc..484f4f2 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -8580,35 +8580,6 @@ stabilize_vla_size (tree size)
   cp_walk_tree (&size, stabilize_save_expr_r, &pset, &pset);
 }
 
-/* Helper function for compute_array_index_type.  Look for SIZEOF_EXPR
-   not inside of SAVE_EXPR and fold them.  */
-
-static tree
-fold_sizeof_expr_r (tree *expr_p, int *walk_subtrees, void *data)
-{
-  tree expr = *expr_p;
-  if (TREE_CODE (expr) == SAVE_EXPR || TYPE_P (expr))
-    *walk_subtrees = 0;
-  else if (TREE_CODE (expr) == SIZEOF_EXPR)
-    {
-      *(bool *)data = true;
-      if (SIZEOF_EXPR_TYPE_P (expr))
-	expr = cxx_sizeof_or_alignof_type (TREE_TYPE (TREE_OPERAND (expr, 0)),
-					   SIZEOF_EXPR, false);
-      else if (TYPE_P (TREE_OPERAND (expr, 0)))
-	expr = cxx_sizeof_or_alignof_type (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
-					   false);
-      else
-        expr = cxx_sizeof_or_alignof_expr (TREE_OPERAND (expr, 0), SIZEOF_EXPR,
-					   false);
-      if (expr == error_mark_node)
-        expr = size_one_node;
-      *expr_p = expr;
-      *walk_subtrees = 0;
-    }
-  return NULL;
-}
-
 /* Given the SIZE (i.e., number of elements) in an array, compute an
    appropriate index type for the array.  If non-NULL, NAME is the
    name of the thing being declared.  */
@@ -8699,7 +8670,18 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
       SET_TYPE_STRUCTURAL_EQUALITY (itype);
       return itype;
     }
-  
+
+  if (TREE_CODE (size) != INTEGER_CST)
+    {
+      tree folded = cp_fully_fold (size);
+      if (TREE_CODE (folded) == INTEGER_CST)
+	pedwarn (location_of (size), OPT_Wpedantic,
+		 "size of array is not an integral constant-expression");
+      /* Use the folded result for VLAs, too; it will have resolved
+	 SIZEOF_EXPR.  */
+      size = folded;
+    }
+
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
     {
@@ -8786,7 +8768,7 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
 				  cp_convert (ssizetype, integer_one_node,
 					      complain),
 				  complain);
-      itype = fold (itype);
+      itype = maybe_constant_value (itype);
       processing_template_decl = saved_processing_template_decl;
 
       if (!TREE_CONSTANT (itype))
@@ -8794,18 +8776,6 @@ compute_array_index_type (tree name, tree size, tsubst_flags_t complain)
 	  /* A variable sized array.  */
 	  itype = variable_size (itype);
 
-	  if (TREE_CODE (itype) != SAVE_EXPR)
-	    {
-	      /* Look for SIZEOF_EXPRs in itype and fold them, otherwise
-		 they might survive till gimplification.  */
-	      tree newitype = itype;
-	      bool found = false;
-	      cp_walk_tree_without_duplicates (&newitype,
-					       fold_sizeof_expr_r, &found);
-	      if (found)
-		itype = variable_size (fold (newitype));
-	    }
-
 	  stabilize_vla_size (itype);
 
 	  if (flag_sanitize & SANITIZE_VLA
@@ -13515,7 +13485,7 @@ incremented enumerator value is too large for %<long%>");
 		   "type %<%T%>", value, ENUM_UNDERLYING_TYPE (enumtype));
 
           /* Convert the value to the appropriate type.  */
-          value = convert (ENUM_UNDERLYING_TYPE (enumtype), value);
+          value = fold_convert (ENUM_UNDERLYING_TYPE (enumtype), value);
         }
     }
 
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index a2d31a3..89859e9 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -3116,7 +3116,7 @@ get_guard_cond (tree guard, bool thread_safe)
     {
       guard_value = integer_one_node;
       if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
-	guard_value = convert (TREE_TYPE (guard), guard_value);
+	guard_value = fold_convert (TREE_TYPE (guard), guard_value);
       guard = cp_build_binary_op (input_location,
 				  BIT_AND_EXPR, guard, guard_value,
 				  tf_warning_or_error);
@@ -3124,7 +3124,7 @@ get_guard_cond (tree guard, bool thread_safe)
 
   guard_value = integer_zero_node;
   if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
-    guard_value = convert (TREE_TYPE (guard), guard_value);
+    guard_value = fold_convert (TREE_TYPE (guard), guard_value);
   return cp_build_binary_op (input_location,
 			     EQ_EXPR, guard, guard_value,
 			     tf_warning_or_error);
@@ -3142,7 +3142,7 @@ set_guard (tree guard)
   guard = get_guard_bits (guard);
   guard_init = integer_one_node;
   if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard)))
-    guard_init = convert (TREE_TYPE (guard), guard_init);
+    guard_init = fold_convert (TREE_TYPE (guard), guard_init);
   return cp_build_modify_expr (guard, NOP_EXPR, guard_init, 
 			       tf_warning_or_error);
 }
@@ -4573,6 +4573,19 @@ c_parse_final_cleanups (void)
       /* If there are templates that we've put off instantiating, do
 	 them now.  */
       instantiate_pending_templates (retries);
+      /* Clear fold_map and/or cv_map of current scope, if present.  */
+      if (scope_chain && (scope_chain->fold_map || scope_chain->cv_map))
+	{
+	  hash_map<tree,tree> *fm = scope_chain->fold_map;
+	  hash_map<tree,tree> *cv = scope_chain->cv_map;
+	  scope_chain->fold_map = NULL;
+	  scope_chain->cv_map = NULL;
+	  scope_chain->act_cfun = NULL;
+	  if (fm)
+	    delete fm;
+	  if (cv)
+	    delete cv;
+	}
       ggc_collect ();
 
       /* Write out virtual tables as required.  Note that writing out
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index b45281f..fd9ae0d 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -178,9 +178,9 @@ build_zero_init_1 (tree type, tree nelts, bool static_storage_p,
        initialized are initialized to zero.  */
     ;
   else if (TYPE_PTR_OR_PTRMEM_P (type))
-    init = convert (type, nullptr_node);
+    init = fold (convert (type, nullptr_node));
   else if (SCALAR_TYPE_P (type))
-    init = convert (type, integer_zero_node);
+    init = fold (convert (type, integer_zero_node));
   else if (RECORD_OR_UNION_CODE_P (TREE_CODE (type)))
     {
       tree field;
@@ -794,7 +794,6 @@ perform_member_init (tree member, tree init)
 	   in that case.  */
 	init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
 						tf_warning_or_error);
-
       if (init)
 	finish_expr_stmt (cp_build_modify_expr (decl, INIT_EXPR, init,
 						tf_warning_or_error));
@@ -2712,7 +2711,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
       }
       max_outer_nelts_tree = wide_int_to_tree (sizetype, max_outer_nelts);
 
-      size = size_binop (MULT_EXPR, size, convert (sizetype, nelts));
+      size = size_binop (MULT_EXPR, size, fold_convert (sizetype, nelts));
       outer_nelts_check = fold_build2 (LE_EXPR, boolean_type_node,
 				       outer_nelts,
 				       max_outer_nelts_tree);
@@ -2872,7 +2871,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 	{
 	  placement_expr = get_target_expr (placement_first);
 	  CALL_EXPR_ARG (alloc_call, 1)
-	    = convert (TREE_TYPE (placement), placement_expr);
+	    = fold_convert (TREE_TYPE (placement), placement_expr);
 	}
 
       if (!member_new_p
@@ -3464,7 +3463,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
   /* The below is short by the cookie size.  */
   virtual_size = size_binop (MULT_EXPR, size_exp,
-			     convert (sizetype, maxindex));
+			     fold_convert (sizetype, maxindex));
 
   tbase = create_temporary_var (ptype);
   tbase_init
@@ -3507,7 +3506,7 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
 
       /* The below is short by the cookie size.  */
       virtual_size = size_binop (MULT_EXPR, size_exp,
-				 convert (sizetype, maxindex));
+				 fold_convert (sizetype, maxindex));
 
       if (! TYPE_VEC_NEW_USES_COOKIE (type))
 	/* no header */
@@ -3553,8 +3552,8 @@ build_vec_delete_1 (tree base, tree maxindex, tree type,
   body = fold_build3_loc (input_location, COND_EXPR, void_type_node,
 		      fold_build2_loc (input_location,
 				   NE_EXPR, boolean_type_node, base,
-				   convert (TREE_TYPE (base),
-					    nullptr_node)),
+				   fold_convert (TREE_TYPE (base),
+						 nullptr_node)),
 		      body, integer_zero_node);
   body = build1 (NOP_EXPR, void_type_node, body);
 
@@ -3676,6 +3675,7 @@ build_vec_init (tree base, tree maxindex, tree init,
   if (maxindex == NULL_TREE || maxindex == error_mark_node)
     return error_mark_node;
 
+  maxindex = maybe_constant_value (maxindex);
   if (explicit_value_init_p)
     gcc_assert (!init);
 
@@ -3717,6 +3717,8 @@ build_vec_init (tree base, tree maxindex, tree init,
     }
 
   maxindex = cp_convert (ptrdiff_type_node, maxindex, complain);
+  maxindex = fold_simple (maxindex);
+
   if (TREE_CODE (atype) == ARRAY_TYPE)
     {
       ptype = build_pointer_type (type);
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 8744fff..61a352a 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -6182,6 +6182,19 @@ push_to_top_level (void)
   s->unevaluated_operand = cp_unevaluated_operand;
   s->inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
   s->x_stmt_tree.stmts_are_full_exprs_p = true;
+  if (current_function_decl
+      && scope_chain && scope_chain->function_decl == current_function_decl
+      && cfun && scope_chain->act_cfun == cfun)
+    {
+      s->fold_map = scope_chain->fold_map;
+      s->cv_map = scope_chain->cv_map;
+    }
+  else
+    {
+      s->fold_map = NULL;
+      s->cv_map = NULL;
+    }
+  s->act_cfun = cfun;
 
   scope_chain = s;
   current_function_decl = NULL_TREE;
@@ -6199,7 +6212,10 @@ pop_from_top_level_1 (void)
 {
   struct saved_scope *s = scope_chain;
   cxx_saved_binding *saved;
+  hash_map<tree, tree> *fm = s->fold_map;
+  hash_map<tree, tree> *cv = s->cv_map;
   size_t i;
+  bool same_fold_map = false;
 
   /* Clear out class-level bindings cache.  */
   if (previous_class_level)
@@ -6221,9 +6237,32 @@ pop_from_top_level_1 (void)
      state.  */
   if (s->need_pop_function_context)
     pop_function_context ();
+
+  /* If 'current_function_decl' isn't NULL and is equal to prior pushed,
+     we are within a nested function.
+     If additionally saved 'cfun' is identical to current, we can use
+     the same 'fold_map'.  */
+     
+  if (current_function_decl && s->function_decl == current_function_decl
+      && scope_chain && s->fold_map == scope_chain->fold_map
+      && scope_chain->act_cfun && scope_chain->act_cfun == cfun)
+    same_fold_map = true;
+
   current_function_decl = s->function_decl;
   cp_unevaluated_operand = s->unevaluated_operand;
   c_inhibit_evaluation_warnings = s->inhibit_evaluation_warnings;
+
+  /* If we have a new 'fold_map', and it isn't equal, or outside of
+     scope_chain, then invalidate it.  */
+  if (fm && (!same_fold_map || !scope_chain))
+    delete fm;
+  if (cv && (!same_fold_map || !scope_chain))
+    delete cv;
+
+  /* Invalidate explicit.  */
+  s->fold_map = NULL;
+  s->cv_map = NULL;
+  s->act_cfun = NULL;
 }
 
 /* Wrapper for pop_from_top_level_1.  */
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index d1f4970..24a77f8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6769,7 +6769,7 @@ cp_parser_array_notation (location_t loc, cp_parser *parser, tree *init_index,
 	 2. ARRAY [ EXP : EXP ]
 	 3. ARRAY [ EXP : EXP : EXP ]  */
 
-      *init_index = cp_parser_expression (parser);	
+      *init_index = cp_parser_expression (parser);
       if (cp_lexer_peek_token (parser->lexer)->type != CPP_COLON)
 	{  
 	  /* This indicates that we have a normal array expression.  */
@@ -8513,9 +8513,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
       /* For "false && x" or "true || x", x will never be executed;
 	 disable warnings while evaluating it.  */
       if (current.tree_type == TRUTH_ANDIF_EXPR)
-	c_inhibit_evaluation_warnings += current.lhs == truthvalue_false_node;
+	c_inhibit_evaluation_warnings +=
+	  cp_fully_fold (current.lhs) == truthvalue_false_node;
       else if (current.tree_type == TRUTH_ORIF_EXPR)
-	c_inhibit_evaluation_warnings += current.lhs == truthvalue_true_node;
+	c_inhibit_evaluation_warnings +=
+	  cp_fully_fold (current.lhs) == truthvalue_true_node;
 
       /* Extract another operand.  It may be the RHS of this expression
 	 or the LHS of a new, higher priority expression.  */
@@ -8562,9 +8564,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 
       /* Undo the disabling of warnings done above.  */
       if (current.tree_type == TRUTH_ANDIF_EXPR)
-	c_inhibit_evaluation_warnings -= current.lhs == truthvalue_false_node;
+	c_inhibit_evaluation_warnings -=
+	  cp_fully_fold (current.lhs) == truthvalue_false_node;
       else if (current.tree_type == TRUTH_ORIF_EXPR)
-	c_inhibit_evaluation_warnings -= current.lhs == truthvalue_true_node;
+	c_inhibit_evaluation_warnings -=
+	  cp_fully_fold (current.lhs) == truthvalue_true_node;
 
       if (warn_logical_not_paren
 	  && TREE_CODE_CLASS (current.tree_type) == tcc_comparison
@@ -8650,7 +8654,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
 static tree
 cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
 {
-  tree expr;
+  tree expr, folded_logical_or_expr = cp_fully_fold (logical_or_expr);
   tree assignment_expr;
   struct cp_token *token;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -8665,7 +8669,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
                "ISO C++ does not allow ?: with omitted middle operand");
       /* Implicit true clause.  */
       expr = NULL_TREE;
-      c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
+      c_inhibit_evaluation_warnings +=
+	folded_logical_or_expr == truthvalue_true_node;
       warn_for_omitted_condop (token->location, logical_or_expr);
     }
   else
@@ -8673,11 +8678,12 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
       bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
       parser->colon_corrects_to_scope_p = false;
       /* Parse the expression.  */
-      c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
+      c_inhibit_evaluation_warnings +=
+	folded_logical_or_expr == truthvalue_false_node;
       expr = cp_parser_expression (parser);
       c_inhibit_evaluation_warnings +=
-	((logical_or_expr == truthvalue_true_node)
-	 - (logical_or_expr == truthvalue_false_node));
+	((folded_logical_or_expr == truthvalue_true_node)
+	 - (folded_logical_or_expr == truthvalue_false_node));
       parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
     }
 
@@ -8685,7 +8691,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
   cp_parser_require (parser, CPP_COLON, RT_COLON);
   /* Parse the assignment-expression.  */
   assignment_expr = cp_parser_assignment_expression (parser);
-  c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
+  c_inhibit_evaluation_warnings -=
+    folded_logical_or_expr == truthvalue_true_node;
 
   /* Build the conditional-expression.  */
   return build_x_conditional_expr (loc, logical_or_expr,
@@ -20330,8 +20337,8 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
     {
       initializer
 	= cp_parser_constant_expression (parser,
-					/*allow_non_constant_p=*/true,
-					non_constant_p);
+					 /*allow_non_constant_p=*/true,
+					 non_constant_p);
     }
   else
     initializer = cp_parser_braced_list (parser, non_constant_p);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bfea8e2..fb9cdf8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6217,7 +6217,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
   /* 14.3.2/5: The null pointer{,-to-member} conversion is applied
      to a non-type argument of "nullptr".  */
   if (expr == nullptr_node && TYPE_PTR_OR_PTRMEM_P (type))
-    expr = convert (type, expr);
+    expr = fold_simple (convert (type, expr));
 
   /* In C++11, integral or enumeration non-type template arguments can be
      arbitrary constant expressions.  Pointer and pointer to
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 7702a41..73f05f0 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2569,9 +2569,26 @@ finish_unary_op_expr (location_t loc, enum tree_code code, tree expr,
 		      tsubst_flags_t complain)
 {
   tree result = build_x_unary_op (loc, code, expr, complain);
-  if ((complain & tf_warning)
-      && TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr))
-    overflow_warning (input_location, result);
+  tree result_ovl, expr_ovl;
+
+  if (!(complain & tf_warning))
+    return result;
+
+  result_ovl = result;
+  expr_ovl = expr;
+
+  if (!processing_template_decl)
+    expr_ovl = cp_fully_fold (expr_ovl);
+
+  if (!CONSTANT_CLASS_P (expr_ovl)
+      || TREE_OVERFLOW_P (expr_ovl))
+    return result;
+
+  if (!processing_template_decl)
+    result_ovl = cp_fully_fold (result_ovl);
+
+  if (CONSTANT_CLASS_P (result_ovl) && TREE_OVERFLOW_P (result_ovl))
+    overflow_warning (input_location, result_ovl);
 
   return result;
 }
@@ -3895,6 +3912,7 @@ finish_offsetof (tree expr, location_t loc)
 	      TREE_OPERAND (expr, 2));
       return error_mark_node;
     }
+
   if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
       || TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
       || TREE_TYPE (expr) == unknown_type_node)
@@ -4049,6 +4067,22 @@ emit_associated_thunks (tree fn)
 bool
 expand_or_defer_fn_1 (tree fn)
 {
+  if (!function_depth)
+    {
+      if (scope_chain && (scope_chain->fold_map || scope_chain->cv_map))
+	{
+	  hash_map<tree, tree> *fm = scope_chain->fold_map;
+	  hash_map<tree, tree> *cv = scope_chain->cv_map;
+	  if (fm)
+	    delete fm;
+	  if (cv)
+	    delete cv;
+	  scope_chain->fold_map = NULL;
+	  scope_chain->cv_map = NULL;
+	  scope_chain->act_cfun = NULL;
+	}
+    }
+
   /* When the parser calls us after finishing the body of a template
      function, we don't really want to expand the body.  */
   if (processing_template_decl)
@@ -4129,6 +4163,19 @@ expand_or_defer_fn (tree fn)
       emit_associated_thunks (fn);
 
       function_depth--;
+      if (function_depth == 0
+	  && scope_chain && (scope_chain->fold_map || scope_chain->cv_map))
+	{
+	  hash_map<tree, tree> *fm = scope_chain->fold_map;
+	  hash_map<tree, tree> *cv = scope_chain->cv_map;
+	  scope_chain->fold_map = NULL;
+	  scope_chain->cv_map = NULL;
+	  scope_chain->act_cfun = NULL;
+	  if (fm)
+	    delete fm;
+	  if (cv)
+	    delete cv;
+	}
     }
 }
 
@@ -4483,6 +4530,11 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
     low_bound = mark_rvalue_use (low_bound);
   if (length)
     length = mark_rvalue_use (length);
+  /* We need to reduce to real constant-values for checks below.  */
+  if (length)
+    length = fold_simple (length);
+  if (low_bound)
+    low_bound = fold_simple (low_bound);
   if (low_bound
       && TREE_CODE (low_bound) == INTEGER_CST
       && TYPE_PRECISION (TREE_TYPE (low_bound))
@@ -6178,7 +6230,8 @@ finish_omp_clauses (tree clauses, bool allow_fields, bool declare_simd)
 		  if (OMP_CLAUSE_SCHEDULE_KIND (c)
 		      == OMP_CLAUSE_SCHEDULE_CILKFOR)
 		    {
-		      t = convert_to_integer (long_integer_type_node, t);
+		      t = convert_to_integer_nofold (long_integer_type_node,
+						     t);
 		      if (t == error_mark_node)
 			{
 			  remove = true;
@@ -7447,6 +7500,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   if (init && EXPR_HAS_LOCATION (init))
     elocus = EXPR_LOCATION (init);
 
+  cond = cp_fully_fold (cond);
   switch (TREE_CODE (cond))
     {
     case GT_EXPR:
@@ -7482,6 +7536,7 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
   diff = build_x_binary_op (elocus, MINUS_EXPR, TREE_OPERAND (cond, 1),
 			    ERROR_MARK, iter, ERROR_MARK, NULL,
 			    tf_warning_or_error);
+  diff = cp_fully_fold (diff);
   if (error_operand_p (diff))
     return true;
   if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE)
@@ -7543,8 +7598,9 @@ handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code,
 		  if (TREE_CODE (rhs) == MINUS_EXPR)
 		    {
 		      incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr);
-		      incr = fold_if_not_in_template (incr);
+		      incr = fold_simple (incr);
 		    }
+
 		  if (TREE_CODE (incr) != INTEGER_CST
 		      && (TREE_CODE (incr) != NOP_EXPR
 			  || (TREE_CODE (TREE_OPERAND (incr, 0))
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 4311212..dd4daed 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -308,9 +308,19 @@ xvalue_p (const_tree ref)
 bool
 builtin_valid_in_constant_expr_p (const_tree decl)
 {
-  /* At present BUILT_IN_CONSTANT_P is the only builtin we're allowing
-     in constant-expressions.  We may want to add other builtins later. */
-  return DECL_IS_BUILTIN_CONSTANT_P (decl);
+  if (!(TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)))
+    /* Not a built-in.  */
+    return false;
+  switch (DECL_FUNCTION_CODE (decl))
+    {
+    case BUILT_IN_CONSTANT_P:
+    case BUILT_IN_ATOMIC_ALWAYS_LOCK_FREE:
+      /* These have constant results even if their operands are
+	 non-constant.  */
+      return true;
+    default:
+      return false;
+    }
 }
 
 /* Build a TARGET_EXPR, initializing the DECL with the VALUE.  */
@@ -686,8 +696,8 @@ convert_bitfield_to_declared_type (tree expr)
 
   bitfield_type = is_bitfield_expr_with_lowered_type (expr);
   if (bitfield_type)
-    expr = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type),
-			       expr);
+    expr = convert_to_integer_nofold (TYPE_MAIN_VARIANT (bitfield_type),
+				      expr);
   return expr;
 }
 
@@ -3484,10 +3494,13 @@ handle_init_priority_attribute (tree* node,
 
   STRIP_NOPS (initp_expr);
   initp_expr = default_conversion (initp_expr);
+  if (initp_expr)
+    initp_expr = maybe_constant_value (initp_expr);
 
   if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
     {
       error ("requested init_priority is not an integer constant");
+      cxx_constant_value (initp_expr);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -4262,26 +4275,6 @@ stabilize_init (tree init, tree *initp)
   return !TREE_SIDE_EFFECTS (init);
 }
 
-/* Like "fold", but should be used whenever we might be processing the
-   body of a template.  */
-
-tree
-fold_if_not_in_template (tree expr)
-{
-  /* In the body of a template, there is never any need to call
-     "fold".  We will call fold later when actually instantiating the
-     template.  Integral constant expressions in templates will be
-     evaluated via instantiate_non_dependent_expr, as necessary.  */
-  if (processing_template_decl)
-    return expr;
-
-  /* Fold C++ front-end specific tree codes.  */
-  if (TREE_CODE (expr) == UNARY_PLUS_EXPR)
-    return fold_convert (TREE_TYPE (expr), TREE_OPERAND (expr, 0));
-
-  return fold (expr);
-}
-
 /* Returns true if a cast to TYPE may appear in an integral constant
    expression.  */
 
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 0501e4d..4e7ef58 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1948,8 +1948,6 @@ decay_conversion (tree exp,
 
   code = TREE_CODE (type);
 
-  /* FIXME remove for delayed folding.  */
-  exp = scalar_constant_value (exp);
   if (error_operand_p (exp))
     return error_mark_node;
 
@@ -2442,7 +2440,6 @@ build_class_member_access_expr (tree object, tree member,
 
       result = build3_loc (input_location, COMPONENT_REF, member_type,
 			   object, member, NULL_TREE);
-      result = fold_if_not_in_template (result);
 
       /* Mark the expression const or volatile, as appropriate.  Even
 	 though we've dealt with the type above, we still have to mark the
@@ -2855,9 +2852,9 @@ build_simple_component_ref (tree object, tree member)
 {
   tree type = cp_build_qualified_type (TREE_TYPE (member),
 				       cp_type_quals (TREE_TYPE (object)));
-  return fold_build3_loc (input_location,
-			  COMPONENT_REF, type,
-			  object, member, NULL_TREE);
+  return build3_loc (input_location,
+		     COMPONENT_REF, type,
+		     object, member, NULL_TREE);
 }
 
 /* Return an expression for the MEMBER_NAME field in the internal
@@ -3176,8 +3173,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
 	|= (CP_TYPE_VOLATILE_P (type) | TREE_SIDE_EFFECTS (array));
       TREE_THIS_VOLATILE (rval)
 	|= (CP_TYPE_VOLATILE_P (type) | TREE_THIS_VOLATILE (array));
-      ret = require_complete_type_sfinae (fold_if_not_in_template (rval),
-					  complain);
+      ret = require_complete_type_sfinae (rval, complain);
       protected_set_expr_location (ret, loc);
       if (non_lvalue)
 	ret = non_lvalue_loc (loc, ret);
@@ -3924,7 +3920,6 @@ build_vec_cmp (tree_code code, tree type,
   tree minus_one_vec = build_minus_one_cst (type);
   tree cmp_type = build_same_sized_truth_vector_type(type);
   tree cmp = build2 (code, cmp_type, arg0, arg1);
-  cmp = fold_if_not_in_template (cmp);
   return build3 (VEC_COND_EXPR, type, cmp, minus_one_vec, zero_vec);
 }
 
@@ -3979,7 +3974,7 @@ cp_build_binary_op (location_t location,
      convert it to this type.  */
   tree final_type = 0;
 
-  tree result;
+  tree result, result_ovl;
   tree orig_type = NULL;
 
   /* Nonzero if this is an operation like MIN or MAX which can
@@ -4602,7 +4597,7 @@ cp_build_binary_op (location_t location,
 	      op0 = cp_build_binary_op (location,
 					TRUTH_ANDIF_EXPR, e1, e2,
 					complain);
-	      op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain); 
+	      op1 = cp_convert (TREE_TYPE (op0), integer_one_node, complain);
 	    }
      	  else 
 	    {
@@ -4643,10 +4638,12 @@ cp_build_binary_op (location_t location,
 	    op1 = save_expr (op1);
 
 	  pfn0 = pfn_from_ptrmemfunc (op0);
+	  pfn0 = cp_fully_fold (pfn0);
 	  /* Avoid -Waddress warnings (c++/64877).  */
 	  if (TREE_CODE (pfn0) == ADDR_EXPR)
 	    TREE_NO_WARNING (pfn0) = 1;
 	  pfn1 = pfn_from_ptrmemfunc (op1);
+	  pfn1 = cp_fully_fold (pfn1);
 	  delta0 = delta_from_ptrmemfunc (op0);
 	  delta1 = delta_from_ptrmemfunc (op1);
 	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION
@@ -5000,10 +4997,7 @@ cp_build_binary_op (location_t location,
 		  gcc_unreachable();
 		}
 	    }
-	  real = fold_if_not_in_template (real);
-	  imag = fold_if_not_in_template (imag);
 	  result = build2 (COMPLEX_EXPR, result_type, real, imag);
-	  result = fold_if_not_in_template (result);
 	  return result;
 	}
 
@@ -5031,20 +5025,12 @@ cp_build_binary_op (location_t location,
 
       if (short_compare)
 	{
-	  /* Don't write &op0, etc., because that would prevent op0
-	     from being kept in a register.
-	     Instead, make copies of the our local variables and
-	     pass the copies by reference, then copy them back afterward.  */
-	  tree xop0 = op0, xop1 = op1, xresult_type = result_type;
+	  /* We call shorten_compare only for diagnostic-reason.  */
+	  tree xop0 = fold_simple (op0), xop1 = fold_simple (op1),
+	       xresult_type = result_type;
 	  enum tree_code xresultcode = resultcode;
-	  tree val
-	    = shorten_compare (location, &xop0, &xop1, &xresult_type,
+	  shorten_compare (location, &xop0, &xop1, &xresult_type,
 			       &xresultcode);
-	  if (val != 0)
-	    return cp_convert (boolean_type_node, val, complain);
-	  op0 = xop0, op1 = xop1;
-	  converted = 1;
-	  resultcode = xresultcode;
 	}
 
       if ((short_compare || code == MIN_EXPR || code == MAX_EXPR)
@@ -5063,9 +5049,9 @@ cp_build_binary_op (location_t location,
 	  tree oop1 = maybe_constant_value (orig_op1);
 
 	  if (TREE_CODE (oop0) != INTEGER_CST)
-	    oop0 = orig_op0;
+	    oop0 = cp_fully_fold (orig_op0);
 	  if (TREE_CODE (oop1) != INTEGER_CST)
-	    oop1 = orig_op1;
+	    oop1 = cp_fully_fold (orig_op1);
 	  warn_for_sign_compare (location, oop0, oop1, op0, op1, 
 				 result_type, resultcode);
 	}
@@ -5120,18 +5106,30 @@ cp_build_binary_op (location_t location,
     }
 
   result = build2 (resultcode, build_type, op0, op1);
-  result = fold_if_not_in_template (result);
   if (final_type != 0)
     result = cp_convert (final_type, result, complain);
 
-  if (TREE_OVERFLOW_P (result) 
-      && !TREE_OVERFLOW_P (op0) 
-      && !TREE_OVERFLOW_P (op1))
-    overflow_warning (location, result);
-
   if (instrument_expr != NULL)
-    result = fold_build2 (COMPOUND_EXPR, TREE_TYPE (result),
-			  instrument_expr, result);
+    result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
+		     instrument_expr, result);
+
+  if (!processing_template_decl)
+    {
+      op0 = cp_fully_fold (op0);
+      /* Only consider the second argument if the first isn't overflowed.  */
+      if (!CONSTANT_CLASS_P (op0) || TREE_OVERFLOW_P (op0))
+	return result;
+      op1 = cp_fully_fold (op1);
+      if (!CONSTANT_CLASS_P (op1) || TREE_OVERFLOW_P (op1))
+	return result;
+    }
+  else if (!CONSTANT_CLASS_P (op0) || !CONSTANT_CLASS_P (op1)
+	   || TREE_OVERFLOW_P (op0) || TREE_OVERFLOW_P (op1))
+    return result;
+
+  result_ovl = fold_build2 (resultcode, build_type, op0, op1);
+  if (TREE_OVERFLOW_P (result_ovl))
+    overflow_warning (location, result_ovl);
 
   return result;
 }
@@ -5181,8 +5179,7 @@ cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop,
   complete_type (TREE_TYPE (res_type));
 
   return pointer_int_sum (input_location, resultcode, ptrop,
-			  fold_if_not_in_template (intop),
-			  complain & tf_warning_or_error);
+			  intop, complain & tf_warning_or_error);
 }
 
 /* Return a tree for the difference of pointers OP0 and OP1.
@@ -5258,7 +5255,7 @@ pointer_diff (tree op0, tree op1, tree ptrtype, tsubst_flags_t complain)
 
   result = build2 (EXACT_DIV_EXPR, restype, op0,
 		   cp_convert (restype, op1, complain));
-  return fold_if_not_in_template (result);
+  return result;
 }
 
 /* Construct and perhaps optimize a tree representation
@@ -5774,6 +5771,10 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
 	    /* Make sure the result is not an lvalue: a unary plus or minus
 	       expression is always a rvalue.  */
 	    arg = rvalue (arg);
+
+	    if (code == NEGATE_EXPR && CONSTANT_CLASS_P (arg))
+	      /* Immediately fold negation of a constant.  */
+	      return fold_build1 (code, TREE_TYPE (arg), arg);
 	  }
       }
       break;
@@ -5838,10 +5839,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     case REALPART_EXPR:
     case IMAGPART_EXPR:
       arg = build_real_imag_expr (input_location, code, arg);
-      if (arg == error_mark_node)
-	return arg;
-      else
-	return fold_if_not_in_template (arg);
+      return arg;
 
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
@@ -6008,7 +6006,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, int noconvert,
     {
       if (argtype == 0)
 	argtype = TREE_TYPE (arg);
-      return fold_if_not_in_template (build1 (code, argtype, arg));
+      return build1 (code, argtype, arg);
     }
 
   if (complain & tf_error)
@@ -7002,7 +7000,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
     return rvalue (expr);
   else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
 	   || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
-    return fold_if_not_in_template (build_nop (type, expr));
+    return build_nop (type, expr);
   else if ((TYPE_PTRDATAMEM_P (type) && TYPE_PTRDATAMEM_P (intype))
 	   || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
     {
@@ -7030,7 +7028,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
       if (warn_strict_aliasing <= 2)
 	strict_aliasing_warning (intype, type, sexpr);
 
-      return fold_if_not_in_template (build_nop (type, expr));
+      return build_nop (type, expr);
     }
   else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
 	   || (TYPE_PTRFN_P (intype) && TYPE_PTROBV_P (type)))
@@ -7041,13 +7039,13 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
 	warning (OPT_Wconditionally_supported,
 		 "casting between pointer-to-function and pointer-to-object "
 		 "is conditionally-supported");
-      return fold_if_not_in_template (build_nop (type, expr));
+      return build_nop (type, expr);
     }
   else if (VECTOR_TYPE_P (type))
-    return fold_if_not_in_template (convert_to_vector (type, expr));
+    return convert_to_vector (type, expr);
   else if (VECTOR_TYPE_P (intype)
 	   && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-    return fold_if_not_in_template (convert_to_integer (type, expr));
+    return convert_to_integer_nofold (type, expr);
   else
     {
       if (valid_p)
@@ -7899,8 +7897,7 @@ get_delta_difference (tree from, tree to,
       }
   }
 
-  return fold_if_not_in_template (convert_to_integer (ptrdiff_type_node,
-						      result));
+  return convert_to_integer (ptrdiff_type_node, result);
 }
 
 /* Return a constructor for the pointer-to-member-function TYPE using
@@ -8081,41 +8078,35 @@ expand_ptrmemfunc_cst (tree cst, tree *delta, tree *pfn)
 	 fn; the call will do the opposite adjustment.  */
       tree orig_class = DECL_CONTEXT (fn);
       tree binfo = binfo_or_else (orig_class, fn_class);
-      *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
-		       *delta, BINFO_OFFSET (binfo));
-      *delta = fold_if_not_in_template (*delta);
+      *delta = fold_build2 (PLUS_EXPR, TREE_TYPE (*delta),
+			    *delta, BINFO_OFFSET (binfo));
 
       /* We set PFN to the vtable offset at which the function can be
 	 found, plus one (unless ptrmemfunc_vbit_in_delta, in which
 	 case delta is shifted left, and then incremented).  */
       *pfn = DECL_VINDEX (fn);
-      *pfn = build2 (MULT_EXPR, integer_type_node, *pfn,
-		     TYPE_SIZE_UNIT (vtable_entry_type));
-      *pfn = fold_if_not_in_template (*pfn);
+      *pfn = fold_build2 (MULT_EXPR, integer_type_node, *pfn,
+			  TYPE_SIZE_UNIT (vtable_entry_type));
 
       switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
 	{
 	case ptrmemfunc_vbit_in_pfn:
-	  *pfn = build2 (PLUS_EXPR, integer_type_node, *pfn,
-			 integer_one_node);
-	  *pfn = fold_if_not_in_template (*pfn);
+	  *pfn = fold_build2 (PLUS_EXPR, integer_type_node, *pfn,
+			      integer_one_node);
 	  break;
 
 	case ptrmemfunc_vbit_in_delta:
-	  *delta = build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
-			   *delta, integer_one_node);
-	  *delta = fold_if_not_in_template (*delta);
-	  *delta = build2 (PLUS_EXPR, TREE_TYPE (*delta),
-			   *delta, integer_one_node);
-	  *delta = fold_if_not_in_template (*delta);
+	  *delta = fold_build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
+				*delta, integer_one_node);
+	  *delta = fold_build2 (PLUS_EXPR, TREE_TYPE (*delta),
+				*delta, integer_one_node);
 	  break;
 
 	default:
 	  gcc_unreachable ();
 	}
 
-      *pfn = build_nop (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
-      *pfn = fold_if_not_in_template (*pfn);
+      *pfn = fold_convert (TYPE_PTRMEMFUNC_FN_TYPE (type), *pfn);
     }
 }
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e73ea13..7544333 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -742,6 +742,7 @@ split_nonconstant_init (tree dest, tree init)
     init = TARGET_EXPR_INITIAL (init);
   if (TREE_CODE (init) == CONSTRUCTOR)
     {
+      init = cp_fully_fold (init);
       code = push_stmt_list ();
       if (split_nonconstant_init_1 (dest, init))
 	init = NULL_TREE;
@@ -832,6 +833,7 @@ store_init_value (tree decl, tree init, vec<tree, va_gc>** cleanups, int flags)
       DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = const_init;
       TREE_CONSTANT (decl) = const_init && decl_maybe_constant_var_p (decl);
     }
+  value = cp_fully_fold (value);
 
   if (cxx_dialect >= cxx14 && CLASS_TYPE_P (strip_array_types (type)))
     /* Handle aggregate NSDMI in non-constant initializers, too.  */
@@ -930,19 +932,35 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
 	}
     }
 
+  bool almost_ok = ok;
+  if (!ok && !CONSTANT_CLASS_P (init) && (complain & tf_warning_or_error))
+    {
+      tree folded = cp_fully_fold (init);
+      if (TREE_CONSTANT (folded) && check_narrowing (type, folded, tf_none))
+	almost_ok = true;
+    }
+
   if (!ok)
     {
+      location_t loc = EXPR_LOC_OR_LOC (init, input_location);
       if (cxx_dialect == cxx98)
-	warning_at (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
-		    "narrowing conversion of %qE from %qT to %qT inside { } "
-		    "is ill-formed in C++11", init, ftype, type);
-      else if (!TREE_CONSTANT (init))
+	{
+	  if (complain & tf_warning)
+	    warning_at (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
+			"from %qT to %qT inside { } is ill-formed in C++11",
+			init, ftype, type);
+	  ok = true;
+	}
+      else if (!CONSTANT_CLASS_P (init))
 	{
 	  if (complain & tf_warning_or_error)
 	    {
-	      pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
-		       "narrowing conversion of %qE from %qT to %qT inside { }",
-		       init, ftype, type);
+	      if (!almost_ok || pedantic)
+		pedwarn (loc, OPT_Wnarrowing, "narrowing conversion of %qE "
+			 "from %qT to %qT inside { }", init, ftype, type);
+	      if (pedantic && almost_ok)
+		inform (loc, " the expression has a constant value but is not "
+			"a C++ constant-expression");
 	      ok = true;
 	    }
 	}
@@ -950,7 +968,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
 	{
 	  int savederrorcount = errorcount;
 	  global_dc->pedantic_errors = 1;
-	  pedwarn (EXPR_LOC_OR_LOC (init, input_location), OPT_Wnarrowing,
+	  pedwarn (loc, OPT_Wnarrowing,
 		   "narrowing conversion of %qE from %qT to %qT "
 		   "inside { }", init, ftype, type);
 	  if (errorcount == savederrorcount)
@@ -959,7 +977,7 @@ check_narrowing (tree type, tree init, tsubst_flags_t complain)
 	}
     }
 
-  return cxx_dialect == cxx98 || ok; 
+  return ok;
 }
 
 /* Process the initializer INIT for a variable of type TYPE, emitting
diff --git a/gcc/testsuite/c-c++-common/Wshift-negative-value-1.c b/gcc/testsuite/c-c++-common/Wshift-negative-value-1.c
index 5d803ad..8f14034 100644
--- a/gcc/testsuite/c-c++-common/Wshift-negative-value-1.c
+++ b/gcc/testsuite/c-c++-common/Wshift-negative-value-1.c
@@ -47,3 +47,5 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
diff --git a/gcc/testsuite/c-c++-common/Wshift-negative-value-2.c b/gcc/testsuite/c-c++-common/Wshift-negative-value-2.c
index fc89af1..55523a5 100644
--- a/gcc/testsuite/c-c++-common/Wshift-negative-value-2.c
+++ b/gcc/testsuite/c-c++-common/Wshift-negative-value-2.c
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
diff --git a/gcc/testsuite/c-c++-common/Wshift-negative-value-3.c b/gcc/testsuite/c-c++-common/Wshift-negative-value-3.c
index bf9b1a0..1295b72 100644
--- a/gcc/testsuite/c-c++-common/Wshift-negative-value-3.c
+++ b/gcc/testsuite/c-c++-common/Wshift-negative-value-3.c
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
diff --git a/gcc/testsuite/c-c++-common/Wshift-negative-value-4.c b/gcc/testsuite/c-c++-common/Wshift-negative-value-4.c
index 85fbd0e..3088220 100644
--- a/gcc/testsuite/c-c++-common/Wshift-negative-value-4.c
+++ b/gcc/testsuite/c-c++-common/Wshift-negative-value-4.c
@@ -47,3 +47,6 @@ right (int x)
   r += -1U >> x;
   return r;
 }
+
+/* { dg-error "not an integer constant" "no constant" { target c++ } 9 } */
+/* { dg-error "left operand of shift expression" "shift" { target c++ } 9 } */
diff --git a/gcc/testsuite/c-c++-common/fold-bitand-4.c b/gcc/testsuite/c-c++-common/fold-bitand-4.c
index 1b9c388..a658ff1 100644
--- a/gcc/testsuite/c-c++-common/fold-bitand-4.c
+++ b/gcc/testsuite/c-c++-common/fold-bitand-4.c
@@ -1,4 +1,4 @@
-/* { dg-do compile } */
+/* { dg-do compile { target { c } } } */
 /* { dg-options "-fdump-tree-original" } */
 /* { dg-additional-options "-fno-common" { target hppa*-*-hpux* } } */
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
index 26c9293..a5e3c1f1 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-reinterpret1.C
@@ -18,7 +18,7 @@ public:
   {
     /* I am surprised this is considered a constexpr */
     return *((Inner *)4);
-  } // { dg-error "reinterpret_cast" "" { xfail *-*-* } }
+  } // { dg-error "reinterpret_cast" "" }
 };
 
 B B::instance;
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr53792.C b/gcc/testsuite/g++.dg/cpp0x/pr53792.C
new file mode 100644
index 0000000..deb5c1a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr53792.C
@@ -0,0 +1,29 @@
+// PR c++/53792
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump "return 0" "optimized" } }
+
+struct entry {
+  char const* label;
+  int         value;
+};
+
+constexpr bool same(char const *x, char const *y) {
+  return !*x && !*y ? true
+    : /* default */    (*x == *y && same(x+1, y+1));
+}
+
+constexpr int keyToValue(char const *label, entry const *entries) {
+  return !entries->label ? entries->value
+       : same(entries->label, label) ? entries->value
+       : /*default*/                   keyToValue(label, entries+1);
+}
+
+constexpr entry foo[] = {{"Foo", 0}, {"Bar", 1}, {"FooBar", 2}, {0, -1}};
+
+int
+bar()
+{
+  int result = keyToValue("Foo", foo);
+  return result;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr56868.cpp b/gcc/testsuite/g++.dg/cpp0x/pr56868.cpp
new file mode 100644
index 0000000..afa7edb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr56868.cpp
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+
+constexpr int f(void *) { return 0; }
+constexpr int f(...) { return 1; }
+constexpr int g1() { return f(0); }
+constexpr int g2(int n) { return f(n); }
+constexpr int g3(int n) { return f(n*0); }
+
+int main()
+{
+    static_assert(g1() == 0, "g1 failed");
+    static_assert(g2(0) == 1, "g2 failed");
+    static_assert(g3(0) == 1, "g3 failed");
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C b/gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C
new file mode 100644
index 0000000..e340de4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/warn-ovl1.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Woverflow" }
+
+#include <climits>
+
+constexpr int f() { return INT_MIN; }
+
+int main()
+{
+  return -f(); // { dg-warning "overflow" }
+}
+
diff --git a/gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C b/gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C
new file mode 100644
index 0000000..6b5dff8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/warn-ovl2.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Woverflow" }
+
+#include <climits>
+
+constexpr int f() { return INT_MAX; }
+
+int main()
+{
+  return f() + 2; // { dg-warning "overflow" }
+}
+
diff --git a/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C
new file mode 100644
index 0000000..39b3557
--- /dev/null
+++ b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned1.C
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Werror" }  */
+
+extern int fl;
+
+#define MAK (fl < 0 ? 1 : (fl ? -1 : 0))
+
+int foo (int sz)
+{
+  if (MAK) return 1;
+  return 0;
+}
+
diff --git a/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C
new file mode 100644
index 0000000..fa91a4f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/delayedfold/df-warn-signedunsigned2.C
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-Wall -Werror" }  */
+
+extern int fl;
+extern int arr[];
+
+#define MAK (fl < 0 ? 1 : (fl ? 2 : 0))
+
+int foo (int sz)
+{
+  unsigned i;
+  int r = 0;
+  for (i = 0; i < MAK; i++)
+    r += arr[i];
+  return r;
+}
+
diff --git a/gcc/testsuite/g++.dg/ext/attr-aligned01.C b/gcc/testsuite/g++.dg/ext/attr-aligned01.C
index c8ec07d..0c5df6d 100644
--- a/gcc/testsuite/g++.dg/ext/attr-aligned01.C
+++ b/gcc/testsuite/g++.dg/ext/attr-aligned01.C
@@ -5,8 +5,8 @@
 
 template<typename T>
 void type_alignment(const T&) {
-  struct { char c; T t; } s;
-  SA((char*)&s.t - (char*)&s.c == 1);
+  struct S { char c; T t; } s;
+  SA(__builtin_offsetof (S,t) - __builtin_offsetof (S,c) == 1);
 }
 
 template <class T> struct A { char c; T t; };
@@ -17,7 +17,8 @@ int main() {
 
   A<aligned> a;			// { dg-warning "ignoring attributes" }
 
-  SA((char*)&a.t - (char*)&a.c == 1);
+  SA(  __builtin_offsetof (__typeof(a),t)
+     - __builtin_offsetof (__typeof(a),c) == 1);
 
   aligned z;
   type_alignment(z);		// { dg-warning "ignoring attributes" "" { xfail *-*-* } }
diff --git a/gcc/testsuite/g++.dg/ext/offsetof1.C b/gcc/testsuite/g++.dg/ext/offsetof1.C
index 1468c0a..23f3537 100644
--- a/gcc/testsuite/g++.dg/ext/offsetof1.C
+++ b/gcc/testsuite/g++.dg/ext/offsetof1.C
@@ -1,6 +1,7 @@
 // PR c++/27601
 // Origin: Patrik Hägglund  <patrik.hagglund@bredband.net>
 // { dg-do compile }
+// { dg-options "-Wno-pointer-arith" }
 
 struct bar {
   static int foo;
@@ -10,7 +11,7 @@ struct bar {
 int a = __builtin_offsetof(bar, foo);  // { dg-error "static data member" }
 int av = __builtin_offsetof(volatile bar, foo);  // { dg-error "static data member" }
 int b = __builtin_offsetof(bar, baz);  // { dg-error "member function" }
-int b0 = __builtin_offsetof(bar, baz[0]);  // { dg-error "function" }
+int b0 = __builtin_offsetof(bar, baz[0]);  // { dg-error "single identifier nor|member function" }
 int bv0 = __builtin_offsetof(volatile bar, baz[0]);  // { dg-error "function" }
 int c = __builtin_offsetof(bar, ~bar);  // { dg-error "member function" }
 
diff --git a/gcc/testsuite/g++.dg/init/const7.C b/gcc/testsuite/g++.dg/init/const7.C
index dbc60b3..e1f31bc 100644
--- a/gcc/testsuite/g++.dg/init/const7.C
+++ b/gcc/testsuite/g++.dg/init/const7.C
@@ -1,9 +1,9 @@
 // { dg-do compile }
-// { dg-options "-fdump-tree-gimple" }
+// { dg-options "-fdump-tree-gimple -pedantic" }
 
 struct s { int x, y; };
 short offsets[1] = {
-  ((char*) &(((struct s*)16)->y) - (char *)16),
+  ((char*) &(((struct s*)16)->y) - (char *)16), // { dg-message "narrowing" "" { target c++11 } }
 };
 
 // This ensures that we get a dump whether or not the bug is present.
diff --git a/gcc/testsuite/g++.dg/init/self1.C b/gcc/testsuite/g++.dg/init/self1.C
index dd37c8e..7620833 100644
--- a/gcc/testsuite/g++.dg/init/self1.C
+++ b/gcc/testsuite/g++.dg/init/self1.C
@@ -10,7 +10,7 @@ void f(__SIZE_TYPE__) {
 
 int main()
 {
-  int* const savepos = sizeof(*savepos) ? 0 : 0;
+  int* const savepos = sizeof(*savepos) ? 0 : 0;  /* { dg-error "invalid conversion" "convert" { target c++11 }  } */
 
   f (sizeof (*savepos));
 
diff --git a/gcc/testsuite/g++.dg/other/error22.C b/gcc/testsuite/g++.dg/other/error22.C
index 225dcae..eba0746 100644
--- a/gcc/testsuite/g++.dg/other/error22.C
+++ b/gcc/testsuite/g++.dg/other/error22.C
@@ -5,5 +5,5 @@ extern "C" double fabs (double);
 
 void foo (double x)
 {
-  fabs (x) ();	// { dg-error "__builtin_abs" }
+  fabs (x) ();	// { dg-error "function" }
 }
diff --git a/gcc/testsuite/g++.dg/other/error24.C b/gcc/testsuite/g++.dg/other/error24.C
index 54343c5..e5e6a4f 100644
--- a/gcc/testsuite/g++.dg/other/error24.C
+++ b/gcc/testsuite/g++.dg/other/error24.C
@@ -8,6 +8,6 @@ void
 bar (int i, int j, double k)
 {
   foo (i && j) ();	// { dg-error "\\(\\(?i != 0\\)? \\&\\& \\(?j != 0\\)?\\)" }
-  foo (!i || !j) ();	// { dg-error "\\(\\(?i == 0\\)? \\|\\| \\(?j == 0\\)?\\)" }
-  foo (!i == !j) ();	// { dg-error "\\(\\(?i != 0\\)? \\^ \\(?j == 0\\)?\\)" }
+  foo (!i || !j) ();	// { dg-error "function" }
+  foo (!i == !j) ();	// { dg-error "function" }
 }
diff --git a/gcc/testsuite/g++.dg/other/error26.C b/gcc/testsuite/g++.dg/other/error26.C
index fb2c8b7..ffe2728 100644
--- a/gcc/testsuite/g++.dg/other/error26.C
+++ b/gcc/testsuite/g++.dg/other/error26.C
@@ -2,5 +2,5 @@
 
 void foo(__complex__ double x)
 {
-  __builtin_conj(x)(); // { dg-error "~x" }
+  __builtin_conj(x)(); // { dg-error "function" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/array-size2.C b/gcc/testsuite/g++.dg/parse/array-size2.C
index 355ed61..3c83347 100644
--- a/gcc/testsuite/g++.dg/parse/array-size2.C
+++ b/gcc/testsuite/g++.dg/parse/array-size2.C
@@ -14,7 +14,7 @@ extern void bar (char *, char *);
 void
 foo (void)
 {
-  char g[(char *) &((struct S *) 0)->b - (char *) 0];
-  char h[(__SIZE_TYPE__) &((struct S *) 8)->b];
+  char g[(char *) &((struct S *) 0)->b - (char *) 0]; // { dg-error "constant" }
+  char h[(__SIZE_TYPE__) &((struct S *) 8)->b];	      // { dg-error "constant" "" { xfail *-*-* } }
   bar (g, h);
 }
diff --git a/gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C b/gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C
index 946f2e6..8014705 100644
--- a/gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C
+++ b/gcc/testsuite/g++.dg/ubsan/div-by-zero-1.C
@@ -1,14 +1,10 @@
 /* { dg-do compile } */
 /* { dg-options "-fsanitize=integer-divide-by-zero" } */
 
-/* TODO: We expect an error on the invalid case here, because that
-   must be a constant-expression.  This will be fixed when we have
-   proper delayed folding.  */
-
 void
 foo (int i)
 {
   switch (i)
   case 0 * (1 / 0): /* { dg-warning "division by zero" } */
-    ;  /* { dg-error "division by zero" "" { xfail *-*-* } 10 } */
+    ;  /* { dg-error "is not a constant.expression" "" { target *-*-* } 8 } */
 }
diff --git a/gcc/testsuite/g++.dg/ubsan/shift-1.C b/gcc/testsuite/g++.dg/ubsan/shift-1.C
index 05e049e..493a55c 100644
--- a/gcc/testsuite/g++.dg/ubsan/shift-1.C
+++ b/gcc/testsuite/g++.dg/ubsan/shift-1.C
@@ -8,10 +8,10 @@ foo (int x)
   /* None of the following should pass.  */
   switch (x)
     {
-    case 1 >> -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case -1 >> -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case 1 << -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case -1 << -1: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
+    case 1 >> -1: /* { dg-error "operand of shift" "" } */
+    case -1 >> -1: /* { dg-error "operand of shift" "" } */
+    case 1 << -1: /* { dg-error "operand of shift" "" } */
+    case -1 << -1: /* { dg-error "operand of shift" "" } */
       return 1;
     }
   return 0;
@@ -23,8 +23,8 @@ bar (int x)
   /* None of the following should pass.  */
   switch (x)
     {
-    case -1 >> 200: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
-    case 1 << 200: /* { dg-error "is not a constant expression" "" { xfail { *-*-* } } } */
+    case -1 >> 200: /* { dg-error "operand of shift" "" } */
+    case 1 << 200: /* { dg-error "operand of shift" "" } */
       return 1;
     }
   return 0;
diff --git a/gcc/testsuite/g++.dg/warn/overflow-warn-1.C b/gcc/testsuite/g++.dg/warn/overflow-warn-1.C
index 7cd76e7..a10e15b 100644
--- a/gcc/testsuite/g++.dg/warn/overflow-warn-1.C
+++ b/gcc/testsuite/g++.dg/warn/overflow-warn-1.C
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* Again, overflow in evaluated subexpression.  */
@@ -126,3 +126,11 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 32 } */
+/* { dg-warning "invalid conversion from" "convert" { target *-*-* } 56 } */
+/* { dg-warning "invalid conversion from" "convert" { target c++11 } 58 } */
+/* { dg-error "is not a constant expression" "const" { target *-*-* } 65 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 65 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 32 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 32 } */
diff --git a/gcc/testsuite/g++.dg/warn/overflow-warn-3.C b/gcc/testsuite/g++.dg/warn/overflow-warn-3.C
index 73c0e00..c73a28c 100644
--- a/gcc/testsuite/g++.dg/warn/overflow-warn-3.C
+++ b/gcc/testsuite/g++.dg/warn/overflow-warn-3.C
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* Again, overflow in evaluated subexpression.  */
@@ -56,7 +56,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
 /* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 55 } */
 
 void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-warning "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 58 } */
+/* { dg-warning "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
 void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
 
 void
@@ -65,7 +65,7 @@ g (int i)
   switch (i)
     {
     case 0 * (1/0): /* { dg-warning "division by zero" } */
-      ;
+      ;  /* { dg-error "is not a constant expression" "const" { target *-*-* } 67 }  */
     case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
       /* { dg-warning "overflow in constant expression" "constant" { target *-*-* } 69 } */
       ;
@@ -128,3 +128,9 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 32 } */
+/* { dg-warning "invalid conversion from" "convert" { target c++11 } 60 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 67 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 32 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 32 } */
diff --git a/gcc/testsuite/g++.dg/warn/overflow-warn-4.C b/gcc/testsuite/g++.dg/warn/overflow-warn-4.C
index 24b3959..23a2585 100644
--- a/gcc/testsuite/g++.dg/warn/overflow-warn-4.C
+++ b/gcc/testsuite/g++.dg/warn/overflow-warn-4.C
@@ -17,7 +17,7 @@ enum e {
   /* But as in DR#031, the 1/0 in an evaluated subexpression means the
      whole expression violates the constraints.  */
   E4 = 0 * (1 / 0), /* { dg-warning "division by zero" } */
-  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { xfail *-*-* } 19 } */
+  /* { dg-error "enumerator value for 'E4' is not an integer constant" "enum error" { target c++ } 19 } */
   E5 = INT_MAX + 1, /* { dg-warning "integer overflow in expression" } */
   /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 21 } */
   /* { dg-error "enumerator value for 'E5' is not an integer constant" "enum error" { target *-*-* } 21 } */
@@ -59,7 +59,7 @@ void *p = 0 * (INT_MAX + 1); /* { dg-warning "integer overflow in expression" }
 /* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 58 } */
 
 void *q = 0 * (1 / 0); /* { dg-warning "division by zero" } */
-/* { dg-error "invalid conversion from 'int' to 'void*'" "null" { xfail *-*-* } 61 } */
+/* { dg-error "invalid conversion from 'int' to 'void" "null" { target *-*-* } 61 } */
 void *r = (1 ? 0 : INT_MAX+1); /* { dg-bogus "integer overflow in expression" "" { xfail *-*-* } } */
 
 void
@@ -68,7 +68,7 @@ g (int i)
   switch (i)
     {
     case 0 * (1/0): /* { dg-warning "division by zero" } */
-      ;
+      ;  /* { dg-error "is not a constant expression" "const" { target *-*-* } 70 } */
     case 1 + 0 * (INT_MAX + 1): /* { dg-warning "integer overflow in expression" } */
       /* { dg-error "overflow in constant expression" "constant" { target *-*-* } 72 } */
       ;
@@ -131,3 +131,9 @@ h2i (int x)
   ui = INT_MIN;
   ui = x ? INT_MIN : 1U;
 }
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 19 } */
+/* { dg-error "invalid conversion from" "convert" { target c++11 } 63 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 34 } */
+/* { dg-error "division by zero is not a constant.expression" "division" { target c++11 } 70 } */
+/* { dg-error "width not an integer constant" "bit.field" { target c++ } 34 } */
+/* { dg-error "is not a constant expression" "division" { target c++ } 34 } */
diff --git a/gcc/testsuite/g++.old-deja/g++.other/null3.C b/gcc/testsuite/g++.old-deja/g++.other/null3.C
index ff1d0669..96691d3 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/null3.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/null3.C
@@ -3,5 +3,5 @@
 void x()
 {
  int* p = 1==0;	// { dg-warning "converting 'false' to pointer" "" { target { ! c++11 } } }
-// { dg-error "cannot convert" "" { target c++11 } 5 } 
+// { dg-error "cannot convert" "" { target { c++11 } } 5 }
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]