commit 6800169668342f9009a1001bddff8b1400245836
Author: Jason Merrill <jason@redhat.com>
Date:   Sun Oct 9 23:27:52 2011 +0100

    	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.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4c03e76..7219afe 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 1866b81..035fdcd 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 bb1b753..be29870 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 f824f38..b53accf 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 c5f1ac0..708afc8 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 4d12a0d..7d345c9 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 c95f1cb..43c4185 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),
@@ -13077,6 +13081,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:
@@ -19172,6 +19193,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 7ad1e8d..189c13a 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 f23b888..75aa265 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/g++.dg/cpp0x/constexpr-template3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C
new file mode 100644
index 0000000..75b2fc4
--- /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 0000000..a2c5a08
--- /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 0000000..f71e4f5
--- /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();
+}
