* [PATCH] c++: SFINAE-unfriendly error on throwing pointer [PR112436]
@ 2024-02-10 20:27 Marek Polacek
2024-02-13 3:45 ` Jason Merrill
0 siblings, 1 reply; 2+ messages in thread
From: Marek Polacek @ 2024-02-10 20:27 UTC (permalink / raw)
To: GCC Patches, Jason Merrill
Probably stage1 material but it should be safe...
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
-- >8 --
On the heels of r14-8903, this patch adds further complain parameters
so that we don't emit "invalid use of incomplete type" from inside
a concept.
PR c++/112436
gcc/cp/ChangeLog:
* except.cc (expand_start_catch_block): Pass tf_warning_or_error to
is_admissible_throw_operand_or_catch_parameter.
(build_throw): Pass complain to
is_admissible_throw_operand_or_catch_parameter.
(complete_ptr_ref_or_void_ptr_p): Add a tsubst_flags_t parameter. Use
it. Return bool. Call complete_type_or_maybe_complain instead of
complete_type_or_else.
(is_admissible_throw_operand_or_catch_parameter): Add a tsubst_flags_t
parameter. Use it. Guard error calls.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-pr112436.C: New test.
---
gcc/cp/except.cc | 66 ++++++++++---------
.../g++.dg/cpp2a/concepts-pr112436.C | 9 +++
2 files changed, 44 insertions(+), 31 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C
diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
index ea3d6f57396..f1ffda22fd3 100644
--- a/gcc/cp/except.cc
+++ b/gcc/cp/except.cc
@@ -39,8 +39,8 @@ static tree do_end_catch (tree);
static void initialize_handler_parm (tree, tree);
static tree do_allocate_exception (tree);
static tree wrap_cleanups_r (tree *, int *, void *);
-static int complete_ptr_ref_or_void_ptr_p (tree, tree);
-static bool is_admissible_throw_operand_or_catch_parameter (tree, bool);
+static bool is_admissible_throw_operand_or_catch_parameter (tree, bool,
+ tsubst_flags_t);
/* Sets up all the global eh stuff that needs to be initialized at the
start of compilation. */
@@ -398,7 +398,8 @@ expand_start_catch_block (tree decl)
if (decl)
{
- if (!is_admissible_throw_operand_or_catch_parameter (decl, false))
+ if (!is_admissible_throw_operand_or_catch_parameter (decl, false,
+ tf_warning_or_error))
decl = error_mark_node;
type = prepare_eh_type (TREE_TYPE (decl));
@@ -626,11 +627,10 @@ build_throw (location_t loc, tree exp, tsubst_flags_t complain)
warning_at (loc, 0,
"throwing NULL, which has integral, not pointer type");
- if (exp != NULL_TREE)
- {
- if (!is_admissible_throw_operand_or_catch_parameter (exp, true))
- return error_mark_node;
- }
+ if (exp && !is_admissible_throw_operand_or_catch_parameter (exp,
+ /*is_throw=*/true,
+ complain))
+ return error_mark_node;
if (! doing_eh ())
return error_mark_node;
@@ -815,28 +815,26 @@ build_throw (location_t loc, tree exp, tsubst_flags_t complain)
Return the zero on failure and nonzero on success. FROM can be
the expr or decl from whence TYPE came, if available. */
-static int
-complete_ptr_ref_or_void_ptr_p (tree type, tree from)
+static bool
+complete_ptr_ref_or_void_ptr_p (tree type, tree from, tsubst_flags_t complain)
{
- int is_ptr;
-
/* Check complete. */
- type = complete_type_or_else (type, from);
+ type = complete_type_or_maybe_complain (type, from, complain);
if (!type)
- return 0;
+ return false;
/* Or a pointer or ref to one, or cv void *. */
- is_ptr = TYPE_PTR_P (type);
+ const bool is_ptr = TYPE_PTR_P (type);
if (is_ptr || TYPE_REF_P (type))
{
tree core = TREE_TYPE (type);
if (is_ptr && VOID_TYPE_P (core))
/* OK */;
- else if (!complete_type_or_else (core, from))
- return 0;
+ else if (!complete_type_or_maybe_complain (core, from, complain))
+ return false;
}
- return 1;
+ return true;
}
/* If IS_THROW is true return truth-value if T is an expression admissible
@@ -846,13 +844,14 @@ complete_ptr_ref_or_void_ptr_p (tree type, tree from)
for its type plus rvalue reference type is also not admissible. */
static bool
-is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
+is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw,
+ tsubst_flags_t complain)
{
tree expr = is_throw ? t : NULL_TREE;
tree type = TREE_TYPE (t);
/* C++11 [except.handle] The exception-declaration shall not denote
- an incomplete type, an abstract class type, or an rvalue reference
+ an incomplete type, an abstract class type, or an rvalue reference
type. */
/* 15.1/4 [...] The type of the throw-expression shall not be an
@@ -862,7 +861,7 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
restrictions on type matching mentioned in 15.3, the operand
of throw is treated exactly as a function argument in a call
(5.2.2) or the operand of a return statement. */
- if (!complete_ptr_ref_or_void_ptr_p (type, expr))
+ if (!complete_ptr_ref_or_void_ptr_p (type, expr, complain))
return false;
tree nonref_type = non_reference (type);
@@ -872,25 +871,30 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
/* 10.4/3 An abstract class shall not be used as a parameter type,
as a function return type or as type of an explicit
conversion. */
- else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type))
+ else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type,
+ complain))
return false;
else if (!is_throw
&& TYPE_REF_P (type)
&& TYPE_REF_IS_RVALUE (type))
{
- error ("cannot declare %<catch%> parameter to be of rvalue "
- "reference type %qT", type);
+ if (complain & tf_error)
+ error ("cannot declare %<catch%> parameter to be of rvalue "
+ "reference type %qT", type);
return false;
}
else if (variably_modified_type_p (type, NULL_TREE))
{
- if (is_throw)
- error_at (cp_expr_loc_or_input_loc (expr),
- "cannot throw expression of type %qT because it involves "
- "types of variable size", type);
- else
- error ("cannot catch type %qT because it involves types of "
- "variable size", type);
+ if (complain & tf_error)
+ {
+ if (is_throw)
+ error_at (cp_expr_loc_or_input_loc (expr),
+ "cannot throw expression of type %qT because it involves "
+ "types of variable size", type);
+ else
+ error ("cannot catch type %qT because it involves types of "
+ "variable size", type);
+ }
return false;
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C
new file mode 100644
index 00000000000..6b755e5ed70
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C
@@ -0,0 +1,9 @@
+// PR c++/112436
+// { dg-do compile { target c++20 } }
+
+template<class T>
+concept Throwable = requires { throw T(); };
+struct Incomplete;
+
+static_assert(!Throwable<Incomplete*>);
+static_assert(!Throwable<int(*)[]>);
base-commit: 93e1559bea434a681208e5e7a21513d7da2844d6
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] c++: SFINAE-unfriendly error on throwing pointer [PR112436]
2024-02-10 20:27 [PATCH] c++: SFINAE-unfriendly error on throwing pointer [PR112436] Marek Polacek
@ 2024-02-13 3:45 ` Jason Merrill
0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2024-02-13 3:45 UTC (permalink / raw)
To: Marek Polacek, GCC Patches
On 2/10/24 15:27, Marek Polacek wrote:
> Probably stage1 material but it should be safe...
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
Yeah, OK, this should go in along with the 98388 patch.
> -- >8 --
> On the heels of r14-8903, this patch adds further complain parameters
> so that we don't emit "invalid use of incomplete type" from inside
> a concept.
>
> PR c++/112436
>
> gcc/cp/ChangeLog:
>
> * except.cc (expand_start_catch_block): Pass tf_warning_or_error to
> is_admissible_throw_operand_or_catch_parameter.
> (build_throw): Pass complain to
> is_admissible_throw_operand_or_catch_parameter.
> (complete_ptr_ref_or_void_ptr_p): Add a tsubst_flags_t parameter. Use
> it. Return bool. Call complete_type_or_maybe_complain instead of
> complete_type_or_else.
> (is_admissible_throw_operand_or_catch_parameter): Add a tsubst_flags_t
> parameter. Use it. Guard error calls.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp2a/concepts-pr112436.C: New test.
> ---
> gcc/cp/except.cc | 66 ++++++++++---------
> .../g++.dg/cpp2a/concepts-pr112436.C | 9 +++
> 2 files changed, 44 insertions(+), 31 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C
>
> diff --git a/gcc/cp/except.cc b/gcc/cp/except.cc
> index ea3d6f57396..f1ffda22fd3 100644
> --- a/gcc/cp/except.cc
> +++ b/gcc/cp/except.cc
> @@ -39,8 +39,8 @@ static tree do_end_catch (tree);
> static void initialize_handler_parm (tree, tree);
> static tree do_allocate_exception (tree);
> static tree wrap_cleanups_r (tree *, int *, void *);
> -static int complete_ptr_ref_or_void_ptr_p (tree, tree);
> -static bool is_admissible_throw_operand_or_catch_parameter (tree, bool);
> +static bool is_admissible_throw_operand_or_catch_parameter (tree, bool,
> + tsubst_flags_t);
>
> /* Sets up all the global eh stuff that needs to be initialized at the
> start of compilation. */
> @@ -398,7 +398,8 @@ expand_start_catch_block (tree decl)
>
> if (decl)
> {
> - if (!is_admissible_throw_operand_or_catch_parameter (decl, false))
> + if (!is_admissible_throw_operand_or_catch_parameter (decl, false,
> + tf_warning_or_error))
> decl = error_mark_node;
>
> type = prepare_eh_type (TREE_TYPE (decl));
> @@ -626,11 +627,10 @@ build_throw (location_t loc, tree exp, tsubst_flags_t complain)
> warning_at (loc, 0,
> "throwing NULL, which has integral, not pointer type");
>
> - if (exp != NULL_TREE)
> - {
> - if (!is_admissible_throw_operand_or_catch_parameter (exp, true))
> - return error_mark_node;
> - }
> + if (exp && !is_admissible_throw_operand_or_catch_parameter (exp,
> + /*is_throw=*/true,
> + complain))
> + return error_mark_node;
>
> if (! doing_eh ())
> return error_mark_node;
> @@ -815,28 +815,26 @@ build_throw (location_t loc, tree exp, tsubst_flags_t complain)
> Return the zero on failure and nonzero on success. FROM can be
> the expr or decl from whence TYPE came, if available. */
>
> -static int
> -complete_ptr_ref_or_void_ptr_p (tree type, tree from)
> +static bool
> +complete_ptr_ref_or_void_ptr_p (tree type, tree from, tsubst_flags_t complain)
> {
> - int is_ptr;
> -
> /* Check complete. */
> - type = complete_type_or_else (type, from);
> + type = complete_type_or_maybe_complain (type, from, complain);
> if (!type)
> - return 0;
> + return false;
>
> /* Or a pointer or ref to one, or cv void *. */
> - is_ptr = TYPE_PTR_P (type);
> + const bool is_ptr = TYPE_PTR_P (type);
> if (is_ptr || TYPE_REF_P (type))
> {
> tree core = TREE_TYPE (type);
>
> if (is_ptr && VOID_TYPE_P (core))
> /* OK */;
> - else if (!complete_type_or_else (core, from))
> - return 0;
> + else if (!complete_type_or_maybe_complain (core, from, complain))
> + return false;
> }
> - return 1;
> + return true;
> }
>
> /* If IS_THROW is true return truth-value if T is an expression admissible
> @@ -846,13 +844,14 @@ complete_ptr_ref_or_void_ptr_p (tree type, tree from)
> for its type plus rvalue reference type is also not admissible. */
>
> static bool
> -is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
> +is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw,
> + tsubst_flags_t complain)
> {
> tree expr = is_throw ? t : NULL_TREE;
> tree type = TREE_TYPE (t);
>
> /* C++11 [except.handle] The exception-declaration shall not denote
> - an incomplete type, an abstract class type, or an rvalue reference
> + an incomplete type, an abstract class type, or an rvalue reference
> type. */
>
> /* 15.1/4 [...] The type of the throw-expression shall not be an
> @@ -862,7 +861,7 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
> restrictions on type matching mentioned in 15.3, the operand
> of throw is treated exactly as a function argument in a call
> (5.2.2) or the operand of a return statement. */
> - if (!complete_ptr_ref_or_void_ptr_p (type, expr))
> + if (!complete_ptr_ref_or_void_ptr_p (type, expr, complain))
> return false;
>
> tree nonref_type = non_reference (type);
> @@ -872,25 +871,30 @@ is_admissible_throw_operand_or_catch_parameter (tree t, bool is_throw)
> /* 10.4/3 An abstract class shall not be used as a parameter type,
> as a function return type or as type of an explicit
> conversion. */
> - else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type))
> + else if (abstract_virtuals_error (is_throw ? ACU_THROW : ACU_CATCH, type,
> + complain))
> return false;
> else if (!is_throw
> && TYPE_REF_P (type)
> && TYPE_REF_IS_RVALUE (type))
> {
> - error ("cannot declare %<catch%> parameter to be of rvalue "
> - "reference type %qT", type);
> + if (complain & tf_error)
> + error ("cannot declare %<catch%> parameter to be of rvalue "
> + "reference type %qT", type);
> return false;
> }
> else if (variably_modified_type_p (type, NULL_TREE))
> {
> - if (is_throw)
> - error_at (cp_expr_loc_or_input_loc (expr),
> - "cannot throw expression of type %qT because it involves "
> - "types of variable size", type);
> - else
> - error ("cannot catch type %qT because it involves types of "
> - "variable size", type);
> + if (complain & tf_error)
> + {
> + if (is_throw)
> + error_at (cp_expr_loc_or_input_loc (expr),
> + "cannot throw expression of type %qT because it involves "
> + "types of variable size", type);
> + else
> + error ("cannot catch type %qT because it involves types of "
> + "variable size", type);
> + }
> return false;
> }
>
> diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C
> new file mode 100644
> index 00000000000..6b755e5ed70
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr112436.C
> @@ -0,0 +1,9 @@
> +// PR c++/112436
> +// { dg-do compile { target c++20 } }
> +
> +template<class T>
> +concept Throwable = requires { throw T(); };
> +struct Incomplete;
> +
> +static_assert(!Throwable<Incomplete*>);
> +static_assert(!Throwable<int(*)[]>);
>
> base-commit: 93e1559bea434a681208e5e7a21513d7da2844d6
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-02-13 3:45 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-10 20:27 [PATCH] c++: SFINAE-unfriendly error on throwing pointer [PR112436] Marek Polacek
2024-02-13 3:45 ` Jason Merrill
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).