From a4474a3854f4fec4bfccad91706f95a6737e6a79 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 11 Oct 2011 13:53:07 -0400 Subject: [PATCH] re PR c++/49855 (internal compiler error: in fold_convert_const_int_from_real) 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 --- gcc/cp/ChangeLog | 21 +++++++++++++++++++++ gcc/cp/call.c | 14 ++++++++++---- gcc/cp/cp-objcp-common.c | 1 + gcc/cp/cp-tree.def | 1 + gcc/cp/cp-tree.h | 6 ++++++ gcc/cp/cxx-pretty-print.c | 2 ++ gcc/cp/error.c | 1 + gcc/cp/pt.c | 24 +++++++++++++++++++++++- gcc/cp/semantics.c | 3 +-- gcc/cp/tree.c | 2 ++ gcc/testsuite/ChangeLog | 8 ++++++++ gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C | 9 +++++++++ gcc/testsuite/g++.dg/template/constant1.C | 13 +++++++++++++ gcc/testsuite/g++.dg/template/constant2.C | 22 ++++++++++++++++++++++ 14 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-template3.C create mode 100644 gcc/testsuite/g++.dg/template/constant1.C create mode 100644 gcc/testsuite/g++.dg/template/constant2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3be7f7d..69c0eeb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,24 @@ +2011-10-11 Jason Merrill + + 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 PR c++/50611 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 2cb478d..bfbd244 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 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/ChangeLog b/gcc/testsuite/ChangeLog index b8e7eba..c068492 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2011-10-11 Jason Merrill + + 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 * 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 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 +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 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 test { + protected: + static const int versionConst = 0x80000000; + enum { versionEnum = versionConst }; + public: + int getVersion(); +}; + +template +int test::getVersion() { + return versionEnum; +} + +class dummy_class {}; + +int main() { + test t; + return t.getVersion(); +} -- 2.7.4