diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 438b3e0d309..124dc3f959f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,17 @@ +2008-12-02 Jason Merrill + + PR c++/35782, c++/37860 + * call.c (build_user_type_conversion_1): Remember + list-initialization. + (convert_like_real): Likewise. + (build_over_call): Don't require the copy constructor + for copy-list-initialization. + * cp-tree.h (TARGET_EXPR_LIST_INIT_P): New macro. + + PR c++/37234 + * decl.c (cp_finish_decl): Handle =default and =delete for + templates, too. + 2008-12-01 Jakub Jelinek PR c++/38257 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index bbd6a222d90..273599eddfc 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -2871,6 +2871,10 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) build_identity_conv (TREE_TYPE (expr), expr)); conv->cand = cand; + /* Remember that this was a list-initialization. */ + if (flags & LOOKUP_NO_NARROWING) + conv->check_narrowing = true; + /* Combine it with the second conversion sequence. */ cand->second_conv = merge_conversion_sequences (conv, cand->second_conv); @@ -4579,7 +4583,13 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, /* If this is a constructor or a function returning an aggr type, we need to build up a TARGET_EXPR. */ if (DECL_CONSTRUCTOR_P (convfn)) - expr = build_cplus_new (totype, expr); + { + expr = build_cplus_new (totype, expr); + + /* Remember that this was list-initialization. */ + if (convs->check_narrowing) + TARGET_EXPR_LIST_INIT_P (expr) = true; + } return expr; } @@ -5314,9 +5324,15 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) else arg = cp_build_indirect_ref (arg, 0, complain); + if (TREE_CODE (arg) == TARGET_EXPR + && TARGET_EXPR_LIST_INIT_P (arg)) + { + /* Copy-list-initialization doesn't require the copy constructor + to be defined. */ + } /* [class.copy]: the copy constructor is implicitly defined even if the implementation elided its use. */ - if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn))) + else if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn))) { mark_used (fn); already_used = true; diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a03fe9bfae5..7f33ff139b4 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -89,6 +89,7 @@ framework extensions, you must include this file before toplev.h, not after. DECL_INITIALIZED_P (in VAR_DECL) TYPENAME_IS_CLASS_P (in TYPENAME_TYPE) STMT_IS_FULL_EXPR_P (in _STMT) + TARGET_EXPR_LIST_INIT_P (in TARGET_EXPR) 2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE) ICS_THIS_FLAG (in _CONV) DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL) @@ -3463,6 +3464,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define TARGET_EXPR_IMPLICIT_P(NODE) \ TREE_LANG_FLAG_0 (TARGET_EXPR_CHECK (NODE)) +/* True if this TARGET_EXPR is the result of list-initialization of a + temporary. */ +#define TARGET_EXPR_LIST_INIT_P(NODE) \ + TREE_LANG_FLAG_1 (TARGET_EXPR_CHECK (NODE)) + /* An enumeration of the kind of tags that C++ accepts. */ enum tag_types { none_type = 0, /* Not a tag type. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 997c580038c..d045935445e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5504,6 +5504,25 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, } } + if (init && TREE_CODE (decl) == FUNCTION_DECL) + { + if (init == ridpointers[(int)RID_DELETE]) + { + /* FIXME check this is 1st decl. */ + DECL_DELETED_FN (decl) = 1; + DECL_DECLARED_INLINE_P (decl) = 1; + DECL_INITIAL (decl) = error_mark_node; + init = NULL_TREE; + } + else if (init == ridpointers[(int)RID_DEFAULT]) + { + if (!defaultable_fn_p (decl)) + error ("%qD cannot be defaulted", decl); + else + DECL_DEFAULTED_FN (decl) = 1; + } + } + if (processing_template_decl) { bool type_dependent_p; @@ -5765,25 +5784,12 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, { if (init) { - if (init == ridpointers[(int)RID_DELETE]) + if (init == ridpointers[(int)RID_DEFAULT]) { - /* fixme check this is 1st decl */ - DECL_DELETED_FN (decl) = 1; - DECL_DECLARED_INLINE_P (decl) = 1; - DECL_INITIAL (decl) = error_mark_node; - } - else if (init == ridpointers[(int)RID_DEFAULT]) - { - if (!defaultable_fn_p (decl)) - error ("%qD cannot be defaulted", decl); - else - { - /* An out-of-class default definition is defined at - the point where it is explicitly defaulted. */ - DECL_DEFAULTED_FN (decl) = 1; - if (DECL_INITIAL (decl) == error_mark_node) - synthesize_method (decl); - } + /* An out-of-class default definition is defined at + the point where it is explicitly defaulted. */ + if (DECL_INITIAL (decl) == error_mark_node) + synthesize_method (decl); } else error ("function %q#D is initialized like a variable", decl); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 77b69ee59a2..6d585a6ef25 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2008-12-02 Jason Merrill + + PR c++/35782, c++/37860 + * g++.dg/cpp0x/initlist9.C: New test. + + PR c++/37234 + * g++.dg/cpp0x/defaulted5.C: New test. + 2008-12-02 Jack Howarth * gcc.misc-tests/linkage.exp: Correct file type check for Darwin. diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted5.C b/gcc/testsuite/g++.dg/cpp0x/defaulted5.C new file mode 100644 index 00000000000..b7bd16b4063 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted5.C @@ -0,0 +1,20 @@ +// PR c++/37234 +// { dg-do link } +// { dg-options "-std=c++0x" } + +template +class foo { + public: + foo() =default; + ~foo(); +}; + +template +foo::~foo() =default; + +int main() { + + foo fi; + + return 0; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist9.C b/gcc/testsuite/g++.dg/cpp0x/initlist9.C new file mode 100644 index 00000000000..61d87f97945 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist9.C @@ -0,0 +1,29 @@ +// PR c++/37860 +// { dg-options "-std=c++0x" } + +struct b +{ + bool t; + + b() = default; + ~b() = default; + b& operator=(const b&) = delete; + b(const b&) = delete; + + b(bool _t): t (_t) { } +}; + +int main() +{ + // copy list initialization + b tst1 = { false }; + + // copy initialization. + b tst2 = false; // { dg-error "deleted" } + + // direct list initialization + b tst3 { false }; + + // default initialization + b tst4; +}