re PR c++/49855 (internal compiler error: in fold_convert_const_int_from_real)
authorJason Merrill <jason@redhat.com>
Tue, 11 Oct 2011 17:53:07 +0000 (13:53 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 11 Oct 2011 17:53:07 +0000 (13:53 -0400)
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.

From-SVN: r179813

14 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.c
gcc/cp/error.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/constant1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/constant2.C [new file with mode: 0644]

index 3be7f7d..69c0eeb 100644 (file)
@@ -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
index 4c03e76..7219afe 100644 (file)
@@ -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);
index 1866b81..035fdcd 100644 (file)
@@ -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);
index bb1b753..be29870 100644 (file)
@@ -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)
index f824f38..b53accf 100644 (file)
@@ -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) \
index c5f1ac0..708afc8 100644 (file)
@@ -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;
 
index 4d12a0d..7d345c9 100644 (file)
@@ -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);
index 2cb478d..bfbd244 100644 (file)
@@ -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));
 
index 7ad1e8d..189c13a 100644 (file)
@@ -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));
index f23b888..75aa265 100644 (file)
@@ -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));
 
index b8e7eba..c068492 100644 (file)
@@ -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 (file)
index 0000000..75b2fc4
--- /dev/null
@@ -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 (file)
index 0000000..a2c5a08
--- /dev/null
@@ -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 (file)
index 0000000..f71e4f5
--- /dev/null
@@ -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();
+}