This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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;
+ }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]