public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-2233] c++: 'new T[N]' and SFINAE [PR82110]
@ 2021-07-10  2:43 Patrick Palka
  0 siblings, 0 replies; only message in thread
From: Patrick Palka @ 2021-07-10  2:43 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:b9119edc09e4660d772dea771578715858f7fbdb

commit r12-2233-gb9119edc09e4660d772dea771578715858f7fbdb
Author: Patrick Palka <ppalka@redhat.com>
Date:   Fri Jul 9 22:40:07 2021 -0400

    c++: 'new T[N]' and SFINAE [PR82110]
    
    Here we're failing to treat 'new T[N]' as erroneous in a SFINAE context
    when T isn't default constructible because expand_aggr_init_1 doesn't
    communicate to build_aggr_init (its only SFINAE caller) whether the
    initialization was actually successful.  To fix this, this patch makes
    expand_aggr_init_1 and its subroutine expand_default_init return true on
    success, false on failure so that build_aggr_init can properly return
    error_mark_node on failure.
    
            PR c++/82110
    
    gcc/cp/ChangeLog:
    
            * init.c (build_aggr_init): Return error_mark_node if
            expand_aggr_init_1 returns false.
            (expand_default_init): Change return type to bool.  Return false
            on error, true on success.
            (expand_aggr_init_1): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp0x/pr78765.C: Expect another conversion failure
            diagnostic.
            * g++.dg/template/sfinae14.C: Flip incorrect assertion.
            * g++.dg/cpp2a/concepts-requires27.C: New test.

Diff:
---
 gcc/cp/init.c                                    | 43 ++++++++++++++++--------
 gcc/testsuite/g++.dg/cpp0x/pr78765.C             |  2 +-
 gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C | 10 ++++++
 gcc/testsuite/g++.dg/template/sfinae14.C         |  2 +-
 4 files changed, 41 insertions(+), 16 deletions(-)

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 88f6f90a800..d47e405e745 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -39,8 +39,8 @@ along with GCC; see the file COPYING3.  If not see
 static bool begin_init_stmts (tree *, tree *);
 static tree finish_init_stmts (bool, tree, tree);
 static void construct_virtual_base (tree, tree);
-static void expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t);
-static void expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t);
+static bool expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t);
+static bool expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t);
 static void perform_member_init (tree, tree);
 static int member_init_ok_or_else (tree, tree, tree);
 static void expand_virtual_init (tree, tree);
@@ -1838,12 +1838,14 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
   is_global = begin_init_stmts (&stmt_expr, &compound_stmt);
   destroy_temps = stmts_are_full_exprs_p ();
   current_stmt_tree ()->stmts_are_full_exprs_p = 0;
-  expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
-		      init, LOOKUP_NORMAL|flags, complain);
+  bool ok = expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,
+				init, LOOKUP_NORMAL|flags, complain);
   stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
   current_stmt_tree ()->stmts_are_full_exprs_p = destroy_temps;
   TREE_READONLY (exp) = was_const;
   TREE_THIS_VOLATILE (exp) = was_volatile;
+  if (!ok)
+    return error_mark_node;
 
   if ((VAR_P (exp) || TREE_CODE (exp) == PARM_DECL)
       && TREE_SIDE_EFFECTS (stmt_expr)
@@ -1854,7 +1856,7 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain)
   return stmt_expr;
 }
 
-static void
+static bool
 expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
                      tsubst_flags_t complain)
 {
@@ -1889,6 +1891,9 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
        happen for direct-initialization, too.  */
     init = digest_init (type, init, complain);
 
+  if (init == error_mark_node)
+    return false;
+
   /* A CONSTRUCTOR of the target's type is a previously digested
      initializer, whether that happened just above or in
      cp_parser_late_parsing_nsdmi.
@@ -1910,7 +1915,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
       init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init);
       TREE_SIDE_EFFECTS (init) = 1;
       finish_expr_stmt (init);
-      return;
+      return true;
     }
 
   if (init && TREE_CODE (init) != TREE_LIST
@@ -1927,8 +1932,12 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
 	   have already built up the constructor call so we could wrap it
 	   in an exception region.  */;
       else
-	init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP,
-			    flags, complain | tf_no_cleanup);
+	{
+	  init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP,
+			      flags, complain | tf_no_cleanup);
+	  if (init == error_mark_node)
+	    return false;
+	}
 
       if (TREE_CODE (init) == MUST_NOT_THROW_EXPR)
 	/* We need to protect the initialization of a catch parm with a
@@ -1944,7 +1953,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
 	init = build2 (INIT_EXPR, TREE_TYPE (exp), exp, init);
       TREE_SIDE_EFFECTS (init) = 1;
       finish_expr_stmt (init);
-      return;
+      return true;
     }
 
   if (init == NULL_TREE)
@@ -1982,6 +1991,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
 					&parms, binfo, flags,
 					complain);
       base = fold_build_cleanup_point_expr (void_type_node, base);
+      if (complete == error_mark_node || base == error_mark_node)
+	return false;
       rval = build_if_in_charge (complete, base);
     }
    else
@@ -1991,6 +2002,8 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
 
       rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
 					complain);
+      if (rval == error_mark_node)
+	return false;
     }
 
   if (parms != NULL)
@@ -2010,10 +2023,12 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
   /* FIXME put back convert_to_void?  */
   if (TREE_SIDE_EFFECTS (rval))
     finish_expr_stmt (rval);
+
+  return true;
 }
 
 /* This function is responsible for initializing EXP with INIT
-   (if any).
+   (if any).  Returns true on success, false on failure.
 
    BINFO is the binfo of the type for who we are performing the
    initialization.  For example, if W is a virtual base class of A and B,
@@ -2032,7 +2047,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
    FLAGS is just passed to `build_new_method_call'.  See that function
    for its description.  */
 
-static void
+static bool
 expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
                     tsubst_flags_t complain)
 {
@@ -2058,7 +2073,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
       if (init)
 	finish_expr_stmt (init);
       gcc_assert (!cleanups);
-      return;
+      return true;
     }
 
   /* List-initialization from {} becomes value-initialization for non-aggregate
@@ -2096,7 +2111,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
       /* If we don't need to mess with the constructor at all,
 	 then we're done.  */
       if (! type_build_ctor_call (type))
-	return;
+	return true;
 
       /* Otherwise fall through and call the constructor.  */
       init = NULL_TREE;
@@ -2104,7 +2119,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
 
   /* We know that expand_default_init can handle everything we want
      at this point.  */
-  expand_default_init (binfo, true_exp, exp, init, flags, complain);
+  return expand_default_init (binfo, true_exp, exp, init, flags, complain);
 }
 
 /* Report an error if TYPE is not a user-defined, class type.  If
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr78765.C b/gcc/testsuite/g++.dg/cpp0x/pr78765.C
index 6b66d26e549..4c63fddb684 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr78765.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr78765.C
@@ -8,7 +8,7 @@ struct ValueType {
   int field;
 };
 
-static constexpr ValueType var = 0; // { dg-error "conversion" }
+static constexpr ValueType var = 0; // { dg-error "conversion|convert" }
 
 template <int> class ValueTypeInfo;
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C
new file mode 100644
index 00000000000..99d45001383
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires27.C
@@ -0,0 +1,10 @@
+// PR c++/82110
+// { dg-do compile { target c++20 } }
+
+struct X { X() = delete; };
+
+template<class T> concept C = requires(T t) { new T; };
+template<class T> concept D = requires(T t) { new T[1]; };
+
+static_assert(!C<X>);
+static_assert(!D<X>);
diff --git a/gcc/testsuite/g++.dg/template/sfinae14.C b/gcc/testsuite/g++.dg/template/sfinae14.C
index 93eba43a08f..0c59dad305d 100644
--- a/gcc/testsuite/g++.dg/template/sfinae14.C
+++ b/gcc/testsuite/g++.dg/template/sfinae14.C
@@ -76,4 +76,4 @@ STATIC_ASSERT(!(has_new_one_arg<X, int X::*>::value));
 
 STATIC_ASSERT((has_array_new<Y, int, 5>::value));
 STATIC_ASSERT(!(has_array_new<X, int Y::*, &Y::foo>::value));
-STATIC_ASSERT((has_array_new<X, int, 5>::value));
+STATIC_ASSERT(!(has_array_new<X, int, 5>::value));


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-07-10  2:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-10  2:43 [gcc r12-2233] c++: 'new T[N]' and SFINAE [PR82110] Patrick Palka

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).