This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/35782, 37860
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 02 Dec 2008 18:51:33 -0500
- Subject: C++ PATCH for c++/35782, 37860
The C++0x atomics library wants to disable copying of atomics, but still
support aggregate initialization. Some folks on the committee thought
that the new initializer list extension would make this work; I thought
that it wouldn't, as
struct A
{
A(int);
A(const A&) = delete;
};
A a = { 1 };
would involve a call to the deleted copy constructor, which is
ill-formed. But when I read over the actual standardese, there's no
copy constructor call involved. Which isn't what I had in mind when I
wrote up the proposal, but it seems to be what users want. So I've
fixed the compiler accordingly.
Tested x86_64-pc-linux-gnu, applied to trunk.
2008-12-02 Jason Merrill <jason@redhat.com>
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.
Index: cp/call.c
===================================================================
*** cp/call.c (revision 142371)
--- cp/call.c (working copy)
*************** build_user_type_conversion_1 (tree totyp
*** 2871,2876 ****
--- 2871,2880 ----
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);
*************** convert_like_real (conversion *convs, tr
*** 4579,4585 ****
/* 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);
return expr;
}
--- 4583,4595 ----
/* 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);
!
! /* Remember that this was list-initialization. */
! if (convs->check_narrowing)
! TARGET_EXPR_LIST_INIT_P (expr) = true;
! }
return expr;
}
*************** build_over_call (struct z_candidate *can
*** 5314,5322 ****
else
arg = cp_build_indirect_ref (arg, 0, complain);
/* [class.copy]: the copy constructor is implicitly defined even if
the implementation elided its use. */
! if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))
{
mark_used (fn);
already_used = true;
--- 5324,5338 ----
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. */
! else if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))
{
mark_used (fn);
already_used = true;
Index: cp/cp-tree.h
===================================================================
*** cp/cp-tree.h (revision 142371)
--- cp/cp-tree.h (working copy)
*************** framework extensions, you must include t
*** 89,94 ****
--- 89,95 ----
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)
*************** more_aggr_init_expr_args_p (const aggr_i
*** 3463,3468 ****
--- 3464,3474 ----
#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. */
Index: testsuite/g++.dg/cpp0x/initlist9.C
===================================================================
*** testsuite/g++.dg/cpp0x/initlist9.C (revision 0)
--- testsuite/g++.dg/cpp0x/initlist9.C (revision 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;
+ }