+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
}
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);
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);
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)
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.
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) \
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;
break;
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
pp_cxx_cast_expression (pp, t);
break;
break;
CASE_CONVERT:
+ case IMPLICIT_CONV_EXPR:
case VIEW_CONVERT_EXPR:
{
tree op = TREE_OPERAND (t, 0);
return val;
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
case STATIC_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case MODOP_EXPR:
case CAST_EXPR:
+ case IMPLICIT_CONV_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case STATIC_CAST_EXPR:
/* 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)
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),
(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:
|| 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));
return t;
case LAMBDA_EXPR:
- case DYNAMIC_CAST_EXPR:
- case PSEUDO_DTOR_EXPR:
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
case PREDECREMENT_EXPR:
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));
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;
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));
+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.
--- /dev/null
+// { 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 };
+};
--- /dev/null
+// 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 );
+
+}
--- /dev/null
+// 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();
+}