From 3f6079ddc5aae102d082591ec23f84925e6f8e8f Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 2 Dec 2008 18:52:02 -0500 Subject: [PATCH] PR c++/35782, c++/37860 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. From-SVN: r142379 --- gcc/cp/ChangeLog | 14 +++++++++++ gcc/cp/call.c | 20 ++++++++++++++-- gcc/cp/cp-tree.h | 6 +++++ gcc/cp/decl.c | 42 +++++++++++++++++++-------------- gcc/testsuite/ChangeLog | 8 +++++++ gcc/testsuite/g++.dg/cpp0x/defaulted5.C | 20 ++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/initlist9.C | 29 +++++++++++++++++++++++ 7 files changed, 119 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/defaulted5.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist9.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 438b3e0..124dc3f 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 bbd6a22..273599e 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 a03fe9b..7f33ff1 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 997c580..d045935 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]) - { - /* 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 (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 77b69ee..6d585a6 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 0000000..b7bd16b --- /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 0000000..61d87f9 --- /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; +} -- 2.7.4