On 01/23/2017 05:01 PM, Jason Merrill wrote:

I suppose adding a tsubst flag isn't too horrible.  But then we also
need to audit other uses of build_value_init to decide whether they
should build a cleanup or not.

Not too ugly, I guess. Looking at the other calls that end up at build_target_expr, the only one I found that looked like it might need it is also in call.c:
      if (is_dummy_object (fa))
        {
          if (TREE_CODE (arg) == TARGET_EXPR)
            return arg;
          else if (trivial)
            return force_target_expr (DECL_CONTEXT (fn), arg, complain);

but I convinced myself it didn't.

ok?

nathan

--
Nathan Sidwell
2017-01-24  Nathan Sidwell  <nat...@acm.org>

	PR c++/78469 - defaulted ctor and inaccessible dtor
	* cp-tree.h (tsubst_flags): Add tf_no_cleanup.
	* call.c (build-over_call): Pass tf_no_cleanup for ctor in new-expr.
	* tree.c (build_target_expr): Check tf_no_cleanup.

	PR c++/78469
	* g++.dg/cpp0x/pr78469.C: New.

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 244869)
+++ cp/call.c	(working copy)
@@ -8055,7 +8055,8 @@ build_over_call (struct z_candidate *can
       else if (default_ctor_p (fn))
 	{
 	  if (is_dummy_object (argarray[0]))
-	    return force_target_expr (DECL_CONTEXT (fn), void_node, complain);
+	    return force_target_expr (DECL_CONTEXT (fn), void_node,
+				      complain | tf_no_cleanup);
 	  else
 	    return cp_build_indirect_ref (argarray[0], RO_NULL, complain);
 	}
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h	(revision 244869)
+++ cp/cp-tree.h	(working copy)
@@ -4786,6 +4786,8 @@ enum tsubst_flags {
 				    substitution in fn_type_unification.  */
   tf_fndecl_type = 1 << 9,   /* Substituting the type of a function
 				declaration.  */
+  tf_no_cleanup = 1 << 10,   /* Do not build a cleanup
+				(build_target_expr and friends) */
   /* Convenient substitution flags combinations.  */
   tf_warning_or_error = tf_warning | tf_error
 };
Index: cp/tree.c
===================================================================
--- cp/tree.c	(revision 244869)
+++ cp/tree.c	(working copy)
@@ -404,9 +404,15 @@ build_target_expr (tree decl, tree value
 		       || useless_type_conversion_p (TREE_TYPE (decl),
 						     TREE_TYPE (value)));
 
-  t = cxx_maybe_build_cleanup (decl, complain);
-  if (t == error_mark_node)
-    return error_mark_node;
+  if (complain & tf_no_cleanup)
+    /* The caller is building a new-expr and does not need a cleanup.  */
+    t = NULL_TREE;
+  else
+    {
+      t = cxx_maybe_build_cleanup (decl, complain);
+      if (t == error_mark_node)
+	return error_mark_node;
+    }
   t = build4 (TARGET_EXPR, type, decl, value, t, NULL_TREE);
   if (EXPR_HAS_LOCATION (value))
     SET_EXPR_LOCATION (t, EXPR_LOCATION (value));
Index: testsuite/g++.dg/cpp0x/pr78469.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr78469.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr78469.C	(working copy)
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++11 } }
+// PR78469, bogus error about inaccessible dtor.
+
+struct no_destr {
+  no_destr() = default;
+
+protected:
+  ~no_destr() = default;
+};
+
+void *Foo ()
+{
+  return new no_destr ();
+}

Reply via email to