For the 4.6 branch I'm only making the change for scalars.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit d8978a333ab71a4ad2c38446764c1b37092ea098 Author: Jason Merrill <ja...@redhat.com> Date: Mon Oct 3 17:06:02 2011 -0400 PR c++/49855 PR c++/49896 * call.c (perform_implicit_conversion_flags): Do perform scalar conversions in templates. * pt.c (tsubst_copy, tsubst_copy_and_build): Handle CONVERT_EXPR. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 0ec0a07..c54ce7b 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8068,7 +8068,8 @@ 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 + && !(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 diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2ca1ce4..9a48bb4 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -11486,6 +11486,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case STATIC_CAST_EXPR: case DYNAMIC_CAST_EXPR: case NOP_EXPR: + case CONVERT_EXPR: return build1 (code, tsubst (TREE_TYPE (t), args, complain, in_decl), tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl)); @@ -12637,6 +12638,12 @@ tsubst_copy_and_build (tree t, (tsubst (TREE_TYPE (t), args, complain, in_decl), RECUR (TREE_OPERAND (t, 0))); + 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: 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(); +}