diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3be7f7d8f05e4fd836131227e7f17b23ec2eede6..69c0eeb7b6d0781d08051be5671456dd04b65cf8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,24 @@
+2011-10-11  Jason Merrill  <jason@redhat.com>
+
+	PR c++/49855
+	PR c++/49896
+	* cp-tree.def (IMPLICIT_CONV_EXPR): New.
+	* call.c (perform_implicit_conversion_flags): Build it
+	instead of NOP_EXPR.
+	* cp-objcp-common.c (cp_common_init_ts): It's typed.
+	* cxx-pretty-print.c (pp_cxx_cast_expression): Handle it.
+	(pp_cxx_expression): Likewise.
+	* error.c (dump_expr): Likewise.
+	* semantics.c (potential_constant_expression_1): Likewise.
+	* tree.c (cp_tree_equal): Likewise.
+	(cp_walk_subtrees): Likewise.
+	* pt.c (iterative_hash_template_arg): Likewise.
+	(for_each_template_parm_r): Likewise.
+	(type_dependent_expression_p): Likewise.
+	(tsubst_copy, tsubst_copy_and_build): Handle IMPLICIT_CONV_EXPR
+	and CONVERT_EXPR.
+	* cp-tree.h (IMPLICIT_CONV_EXPR_DIRECT_INIT): New.
+
 2011-10-11  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	PR c++/50611
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4c03e76bb0c8a64ccc587438651d914142e08989..7219afe8f59e41ce43bf7ba0451ea1f8f787d5d9 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8397,13 +8397,19 @@ perform_implicit_conversion_flags (tree type, tree expr, tsubst_flags_t complain
 	}
       expr = error_mark_node;
     }
-  else if (processing_template_decl)
+  else if (processing_template_decl
+	   /* As a kludge, we always perform conversions between scalar
+	      types, as IMPLICIT_CONV_EXPR confuses c_finish_omp_for.  */
+	   && !(SCALAR_TYPE_P (type) && SCALAR_TYPE_P (TREE_TYPE (expr))))
     {
       /* In a template, we are only concerned about determining the
 	 type of non-dependent expressions, so we do not have to
-	 perform the actual conversion.  */
-      if (TREE_TYPE (expr) != type)
-	expr = build_nop (type, expr);
+	 perform the actual conversion.  But for initializers, we
+	 need to be able to perform it at instantiation
+	 (or fold_non_dependent_expr) time.  */
+      expr = build1 (IMPLICIT_CONV_EXPR, type, expr);
+      if (!(flags & LOOKUP_ONLYCONVERTING))
+	IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true;
     }
   else
     expr = convert_like (conv, expr, complain);
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 1866b81f802fd8cb3e47a560f1d2ede912fb5684..035fdcd2f4e40cc4ecbc21d8851a4ea7627506d6 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -267,6 +267,7 @@ cp_common_init_ts (void)
   MARK_TS_TYPED (CONST_CAST_EXPR);
   MARK_TS_TYPED (STATIC_CAST_EXPR);
   MARK_TS_TYPED (DYNAMIC_CAST_EXPR);
+  MARK_TS_TYPED (IMPLICIT_CONV_EXPR);
   MARK_TS_TYPED (TEMPLATE_ID_EXPR);
   MARK_TS_TYPED (ARROW_EXPR);
   MARK_TS_TYPED (SIZEOF_EXPR);
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index bb1b753c71bdb69c943278a72382624a935d6652..be29870d93eddcf34e4272446ab830556e24d6be 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -250,6 +250,7 @@ DEFTREECODE (REINTERPRET_CAST_EXPR, "reinterpret_cast_expr", tcc_unary, 1)
 DEFTREECODE (CONST_CAST_EXPR, "const_cast_expr", tcc_unary, 1)
 DEFTREECODE (STATIC_CAST_EXPR, "static_cast_expr", tcc_unary, 1)
 DEFTREECODE (DYNAMIC_CAST_EXPR, "dynamic_cast_expr", tcc_unary, 1)
+DEFTREECODE (IMPLICIT_CONV_EXPR, "implicit_conv_expr", tcc_unary, 1)
 DEFTREECODE (DOTSTAR_EXPR, "dotstar_expr", tcc_expression, 2)
 DEFTREECODE (TYPEID_EXPR, "typeid_expr", tcc_expression, 1)
 DEFTREECODE (NOEXCEPT_EXPR, "noexcept_expr", tcc_unary, 1)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f824f38b74ab8dc04240b1f12a518c7e45f2fcbe..b53accfed65483247376cdb94ed4c5b569a20938 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -72,6 +72,7 @@ c-common.h, not after.
       DECLTYPE_FOR_LAMBDA_CAPTURE (in DECLTYPE_TYPE)
       VEC_INIT_EXPR_IS_CONSTEXPR (in VEC_INIT_EXPR)
       DECL_OVERRIDE_P (in FUNCTION_DECL)
+      IMPLICIT_CONV_EXPR_DIRECT_INIT (in IMPLICIT_CONV_EXPR)
    1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -3233,6 +3234,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
    B b{1,2}, not B b({1,2}) or B b = {1,2}.  */
 #define CONSTRUCTOR_IS_DIRECT_INIT(NODE) (TREE_LANG_FLAG_0 (CONSTRUCTOR_CHECK (NODE)))
 
+/* True if NODE represents a conversion for direct-initialization in a
+   template.  Set by perform_implicit_conversion_flags.  */
+#define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \
+  (TREE_LANG_FLAG_0 (IMPLICIT_CONV_EXPR_CHECK (NODE)))
+
 /* Nonzero means that an object of this type can not be initialized using
    an initializer list.  */
 #define CLASSTYPE_NON_AGGREGATE(NODE) \
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index c5f1ac02cad75daa42fa740774d679574f383bf0..708afc8cdc2b02d611b1140871e323c94ebb3c5a 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -830,6 +830,7 @@ pp_cxx_cast_expression (cxx_pretty_printer *pp, tree t)
   switch (TREE_CODE (t))
     {
     case CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
       pp_cxx_type_id (pp, TREE_TYPE (t));
       pp_cxx_call_argument_list (pp, TREE_OPERAND (t, 0));
       break;
@@ -1084,6 +1085,7 @@ pp_cxx_expression (cxx_pretty_printer *pp, tree t)
       break;
 
     case CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
       pp_cxx_cast_expression (pp, t);
       break;
 
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 4d12a0dd43d36950a661c2ab3a64f1233e604295..7d345c98922fa40457afd78b978bf63364a34a4c 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2052,6 +2052,7 @@ dump_expr (tree t, int flags)
       break;
 
     CASE_CONVERT:
+    case IMPLICIT_CONV_EXPR:
     case VIEW_CONVERT_EXPR:
       {
 	tree op = TREE_OPERAND (t, 0);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2cb478d8053f1846d3709f5932a443e90ea15fa1..bfbd24443254b455515be6810b9cfc0d4e05b99b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1591,6 +1591,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
       return val;
 
     case CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
     case STATIC_CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case CONST_CAST_EXPR:
@@ -7702,6 +7703,7 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
 
     case MODOP_EXPR:
     case CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
     case REINTERPRET_CAST_EXPR:
     case CONST_CAST_EXPR:
     case STATIC_CAST_EXPR:
@@ -11714,7 +11716,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
 
 /* Like tsubst, but deals with expressions.  This function just replaces
    template parms; to finish processing the resultant expression, use
-   tsubst_expr.  */
+   tsubst_copy_and_build or tsubst_expr.  */
 
 static tree
 tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
@@ -11879,6 +11881,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
     case CONST_CAST_EXPR:
     case STATIC_CAST_EXPR:
     case DYNAMIC_CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
+    case CONVERT_EXPR:
     case NOP_EXPR:
       return build1
 	(code, tsubst (TREE_TYPE (t), args, complain, in_decl),
@@ -13081,6 +13085,23 @@ tsubst_copy_and_build (tree t,
 	(tsubst (TREE_TYPE (t), args, complain, in_decl),
 	 RECUR (TREE_OPERAND (t, 0)));
 
+    case IMPLICIT_CONV_EXPR:
+      {
+	tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+	tree expr = RECUR (TREE_OPERAND (t, 0));
+	int flags = LOOKUP_IMPLICIT;
+	if (IMPLICIT_CONV_EXPR_DIRECT_INIT (t))
+	  flags = LOOKUP_NORMAL;
+	return perform_implicit_conversion_flags (type, expr, complain,
+						  flags);
+      }
+
+    case CONVERT_EXPR:
+      return build1
+	(CONVERT_EXPR,
+	 tsubst (TREE_TYPE (t), args, complain, in_decl),
+	 RECUR (TREE_OPERAND (t, 0)));
+
     case CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
     case CONST_CAST_EXPR:
@@ -19176,6 +19197,7 @@ type_dependent_expression_p (tree expression)
       || TREE_CODE (expression) == STATIC_CAST_EXPR
       || TREE_CODE (expression) == CONST_CAST_EXPR
       || TREE_CODE (expression) == REINTERPRET_CAST_EXPR
+      || TREE_CODE (expression) == IMPLICIT_CONV_EXPR
       || TREE_CODE (expression) == CAST_EXPR)
     return dependent_type_p (TREE_TYPE (expression));
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 7ad1e8d5ebd170ad99d48c990250e84a41df4814..189c13ad3e99bb8bf935abf9961e20a367e04a63 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -7481,8 +7481,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
       return t;
 
     case LAMBDA_EXPR:
-    case DYNAMIC_CAST_EXPR:
-    case PSEUDO_DTOR_EXPR:
     case PREINCREMENT_EXPR:
     case POSTINCREMENT_EXPR:
     case PREDECREMENT_EXPR:
@@ -8023,6 +8021,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
     case CONST_CAST_EXPR:
     case STATIC_CAST_EXPR:
     case REINTERPRET_CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
       return (potential_constant_expression_1
 	      (TREE_OPERAND (t, 0),
 	       TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index f23b888f3762caeb113cd062f3d6e3c05b5e065d..75aa26503006e225a6af3eb9994d9cd1424c96c3 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2384,6 +2384,7 @@ cp_tree_equal (tree t1, tree t2)
     case REINTERPRET_CAST_EXPR:
     case CONST_CAST_EXPR:
     case DYNAMIC_CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
     case NEW_EXPR:
       if (!same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
 	return false;
@@ -2994,6 +2995,7 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
     case STATIC_CAST_EXPR:
     case CONST_CAST_EXPR:
     case DYNAMIC_CAST_EXPR:
+    case IMPLICIT_CONV_EXPR:
       if (TREE_TYPE (*tp))
 	WALK_SUBTREE (TREE_TYPE (*tp));
 
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b8e7eba2c373f3a3497bf87691bc5dac77bce5a9..c0684924568c2260d9710e7f8737ffa66f939f25 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2011-10-11  Jason Merrill  <jason@redhat.com>
+
+	PR c++/49855
+	PR c++/49896
+	* g++.dg/template/constant1.C: New.
+	* g++.dg/template/constant2.C: New.
+	* g++.dg/cpp0x/constexpr-template3.C: New.
+
 2011-10-11  Artjoms Sinkarovs  <artyom.shinkaroff@gmail.com>
 
 	* gcc.target/i386/warn-vect-op-3.c: New test.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C
new file mode 100644
index 0000000000000000000000000000000000000000..75b2fc4634e2b283fc0c45a1ca13181234936f53
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C
@@ -0,0 +1,9 @@
+// { dg-options -std=c++0x }
+
+struct A { constexpr operator int() { return 42; } };
+
+template<class T>
+struct B {
+  static const int versionConst = A();
+  enum { versionEnum = versionConst };
+};
diff --git a/gcc/testsuite/g++.dg/template/constant1.C b/gcc/testsuite/g++.dg/template/constant1.C
new file mode 100644
index 0000000000000000000000000000000000000000..a2c5a08d366e55b7869bf298428b60ff4ad00cc8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/constant1.C
@@ -0,0 +1,13 @@
+// PR c++/49855
+
+extern void foo(int);
+
+template <class Key, class Value> void Basic() {
+  const int kT = 1.5e6;        // <--- causes ICE
+  int size = kT*2/3;
+  do {
+    foo(size);
+    size = size * 0.5 - 1;
+  } while (size >= 0 );
+
+}
diff --git a/gcc/testsuite/g++.dg/template/constant2.C b/gcc/testsuite/g++.dg/template/constant2.C
new file mode 100644
index 0000000000000000000000000000000000000000..f71e4f56a22eb4d3a70f0f29467467ca075ddb47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/constant2.C
@@ -0,0 +1,22 @@
+// PR c++/49896
+
+template<class C>
+class test {
+ protected:
+  static const int versionConst = 0x80000000;
+  enum { versionEnum = versionConst };
+ public:
+  int getVersion();
+};
+
+template<class C>
+int test<C>::getVersion() {
+  return versionEnum;
+}
+
+class dummy_class {};
+
+int main() {
+  test<dummy_class> t;
+  return t.getVersion();
+}