c++: make finish_pseudo_destructor_expr SFINAE-aware [PR116417]
Checks
| Context |
Check |
Description |
| linaro-tcwg-bot/tcwg_gcc_build--master-aarch64 |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_check--master-aarch64 |
success
|
Test passed
|
| linaro-tcwg-bot/tcwg_gcc_build--master-arm |
success
|
Build passed
|
| linaro-tcwg-bot/tcwg_gcc_check--master-arm |
success
|
Test passed
|
Commit Message
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
OK for trunk?
-- >8 --
PR c++/116417
gcc/cp/ChangeLog:
* cp-tree.h (finish_pseudo_destructor_expr): Add complain
parameter.
* parser.cc (cp_parser_postfix_dot_deref_expression): Pass
complain=tf_warning_or_error to finish_pseudo_destructor_expr.
* pt.cc (tsubst_expr): Pass complain to
finish_pseudo_destructor_expr.
* semantics.cc (finish_pseudo_destructor_expr): Check complain
before issuing a diagnostic.
gcc/testsuite/ChangeLog:
* g++.dg/template/pseudodtor7.C: New test.
---
gcc/cp/cp-tree.h | 2 +-
gcc/cp/parser.cc | 3 ++-
gcc/cp/pt.cc | 4 ++--
gcc/cp/semantics.cc | 15 +++++++++------
gcc/testsuite/g++.dg/template/pseudodtor7.C | 15 +++++++++++++++
5 files changed, 29 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/template/pseudodtor7.C
Comments
On Mon, Jan 13, 2025 at 11:25:25AM -0500, Patrick Palka wrote:
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
> OK for trunk?
Looks okay to me.
> -- >8 --
>
> PR c++/116417
>
> gcc/cp/ChangeLog:
>
> * cp-tree.h (finish_pseudo_destructor_expr): Add complain
> parameter.
> * parser.cc (cp_parser_postfix_dot_deref_expression): Pass
> complain=tf_warning_or_error to finish_pseudo_destructor_expr.
> * pt.cc (tsubst_expr): Pass complain to
> finish_pseudo_destructor_expr.
> * semantics.cc (finish_pseudo_destructor_expr): Check complain
> before issuing a diagnostic.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/template/pseudodtor7.C: New test.
> ---
> gcc/cp/cp-tree.h | 2 +-
> gcc/cp/parser.cc | 3 ++-
> gcc/cp/pt.cc | 4 ++--
> gcc/cp/semantics.cc | 15 +++++++++------
> gcc/testsuite/g++.dg/template/pseudodtor7.C | 15 +++++++++++++++
> 5 files changed, 29 insertions(+), 10 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/template/pseudodtor7.C
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index aed58523b16..1b42e8ba7d8 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -7966,7 +7966,7 @@ extern tree lookup_and_finish_template_variable (tree, tree, tsubst_flags_t = tf
> extern tree finish_template_variable (tree, tsubst_flags_t = tf_warning_or_error);
> extern cp_expr finish_increment_expr (cp_expr, enum tree_code);
> extern tree finish_this_expr (void);
> -extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t);
> +extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t, tsubst_flags_t);
> extern cp_expr finish_unary_op_expr (location_t, enum tree_code, cp_expr,
> tsubst_flags_t);
> /* Whether this call to finish_compound_literal represents a C++11 functional
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index f548dc31c2b..7f4340537c9 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -8847,7 +8847,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
> pseudo_destructor_p = true;
> postfix_expression
> = finish_pseudo_destructor_expr (postfix_expression,
> - s, type, location);
> + s, type, location,
> + tf_warning_or_error);
> }
> }
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index a141de56446..537e4c4a494 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -21537,7 +21537,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> tree op1 = RECUR (TREE_OPERAND (t, 1));
> tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
> RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
> - input_location));
> + input_location, complain));
> }
>
> case TREE_LIST:
> @@ -21601,7 +21601,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
> dtor = TREE_OPERAND (dtor, 0);
> if (TYPE_P (dtor))
> RETURN (finish_pseudo_destructor_expr
> - (object, s, dtor, input_location));
> + (object, s, dtor, input_location, complain));
> }
> }
> }
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 15840e10620..76c79c6a8cc 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -3527,7 +3527,7 @@ finish_this_expr (void)
>
> tree
> finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
> - location_t loc)
> + location_t loc, tsubst_flags_t complain)
> {
> if (object == error_mark_node || destructor == error_mark_node)
> return error_mark_node;
> @@ -3538,16 +3538,18 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
> {
> if (scope == error_mark_node)
> {
> - error_at (loc, "invalid qualifying scope in pseudo-destructor name");
> + if (complain & tf_error)
> + error_at (loc, "invalid qualifying scope in pseudo-destructor name");
> return error_mark_node;
> }
> if (is_auto (destructor))
> destructor = TREE_TYPE (object);
> if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
> {
> - error_at (loc,
> - "qualified type %qT does not match destructor name ~%qT",
> - scope, destructor);
> + if (complain & tf_error)
> + error_at (loc,
> + "qualified type %qT does not match destructor name ~%qT",
> + scope, destructor);
> return error_mark_node;
> }
>
> @@ -3568,7 +3570,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
> if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
> destructor))
> {
> - error_at (loc, "%qE is not of type %qT", object, destructor);
> + if (complain & tf_error)
> + error_at (loc, "%qE is not of type %qT", object, destructor);
> return error_mark_node;
> }
> }
> diff --git a/gcc/testsuite/g++.dg/template/pseudodtor7.C b/gcc/testsuite/g++.dg/template/pseudodtor7.C
> new file mode 100644
> index 00000000000..302b8c96625
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/pseudodtor7.C
> @@ -0,0 +1,15 @@
> +// PR c++/116417
> +// { dg-do compile { target c++11 } }
> +
> +template<class T>
> +T&& declval();
> +
> +template<class T, class = decltype(declval<T>().~T())>
> +void f(int) = delete;
> +
> +template<class T>
> +void f(...);
> +
> +int main() {
> + f<int&>(0);
> +}
> --
> 2.48.0.rc1.35.g1b4e9a5f8b
>
Marek
On 1/13/25 2:57 PM, Marek Polacek wrote:
> On Mon, Jan 13, 2025 at 11:25:25AM -0500, Patrick Palka wrote:
>> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look
>> OK for trunk?
>
> Looks okay to me.
OK.
>> -- >8 --
>>
>> PR c++/116417
>>
>> gcc/cp/ChangeLog:
>>
>> * cp-tree.h (finish_pseudo_destructor_expr): Add complain
>> parameter.
>> * parser.cc (cp_parser_postfix_dot_deref_expression): Pass
>> complain=tf_warning_or_error to finish_pseudo_destructor_expr.
>> * pt.cc (tsubst_expr): Pass complain to
>> finish_pseudo_destructor_expr.
>> * semantics.cc (finish_pseudo_destructor_expr): Check complain
>> before issuing a diagnostic.
>>
>> gcc/testsuite/ChangeLog:
>>
>> * g++.dg/template/pseudodtor7.C: New test.
>> ---
>> gcc/cp/cp-tree.h | 2 +-
>> gcc/cp/parser.cc | 3 ++-
>> gcc/cp/pt.cc | 4 ++--
>> gcc/cp/semantics.cc | 15 +++++++++------
>> gcc/testsuite/g++.dg/template/pseudodtor7.C | 15 +++++++++++++++
>> 5 files changed, 29 insertions(+), 10 deletions(-)
>> create mode 100644 gcc/testsuite/g++.dg/template/pseudodtor7.C
>>
>> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
>> index aed58523b16..1b42e8ba7d8 100644
>> --- a/gcc/cp/cp-tree.h
>> +++ b/gcc/cp/cp-tree.h
>> @@ -7966,7 +7966,7 @@ extern tree lookup_and_finish_template_variable (tree, tree, tsubst_flags_t = tf
>> extern tree finish_template_variable (tree, tsubst_flags_t = tf_warning_or_error);
>> extern cp_expr finish_increment_expr (cp_expr, enum tree_code);
>> extern tree finish_this_expr (void);
>> -extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t);
>> +extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t, tsubst_flags_t);
>> extern cp_expr finish_unary_op_expr (location_t, enum tree_code, cp_expr,
>> tsubst_flags_t);
>> /* Whether this call to finish_compound_literal represents a C++11 functional
>> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
>> index f548dc31c2b..7f4340537c9 100644
>> --- a/gcc/cp/parser.cc
>> +++ b/gcc/cp/parser.cc
>> @@ -8847,7 +8847,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
>> pseudo_destructor_p = true;
>> postfix_expression
>> = finish_pseudo_destructor_expr (postfix_expression,
>> - s, type, location);
>> + s, type, location,
>> + tf_warning_or_error);
>> }
>> }
>>
>> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
>> index a141de56446..537e4c4a494 100644
>> --- a/gcc/cp/pt.cc
>> +++ b/gcc/cp/pt.cc
>> @@ -21537,7 +21537,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>> tree op1 = RECUR (TREE_OPERAND (t, 1));
>> tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
>> RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
>> - input_location));
>> + input_location, complain));
>> }
>>
>> case TREE_LIST:
>> @@ -21601,7 +21601,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
>> dtor = TREE_OPERAND (dtor, 0);
>> if (TYPE_P (dtor))
>> RETURN (finish_pseudo_destructor_expr
>> - (object, s, dtor, input_location));
>> + (object, s, dtor, input_location, complain));
>> }
>> }
>> }
>> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
>> index 15840e10620..76c79c6a8cc 100644
>> --- a/gcc/cp/semantics.cc
>> +++ b/gcc/cp/semantics.cc
>> @@ -3527,7 +3527,7 @@ finish_this_expr (void)
>>
>> tree
>> finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
>> - location_t loc)
>> + location_t loc, tsubst_flags_t complain)
>> {
>> if (object == error_mark_node || destructor == error_mark_node)
>> return error_mark_node;
>> @@ -3538,16 +3538,18 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
>> {
>> if (scope == error_mark_node)
>> {
>> - error_at (loc, "invalid qualifying scope in pseudo-destructor name");
>> + if (complain & tf_error)
>> + error_at (loc, "invalid qualifying scope in pseudo-destructor name");
>> return error_mark_node;
>> }
>> if (is_auto (destructor))
>> destructor = TREE_TYPE (object);
>> if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
>> {
>> - error_at (loc,
>> - "qualified type %qT does not match destructor name ~%qT",
>> - scope, destructor);
>> + if (complain & tf_error)
>> + error_at (loc,
>> + "qualified type %qT does not match destructor name ~%qT",
>> + scope, destructor);
>> return error_mark_node;
>> }
>>
>> @@ -3568,7 +3570,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
>> if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
>> destructor))
>> {
>> - error_at (loc, "%qE is not of type %qT", object, destructor);
>> + if (complain & tf_error)
>> + error_at (loc, "%qE is not of type %qT", object, destructor);
>> return error_mark_node;
>> }
>> }
>> diff --git a/gcc/testsuite/g++.dg/template/pseudodtor7.C b/gcc/testsuite/g++.dg/template/pseudodtor7.C
>> new file mode 100644
>> index 00000000000..302b8c96625
>> --- /dev/null
>> +++ b/gcc/testsuite/g++.dg/template/pseudodtor7.C
>> @@ -0,0 +1,15 @@
>> +// PR c++/116417
>> +// { dg-do compile { target c++11 } }
>> +
>> +template<class T>
>> +T&& declval();
>> +
>> +template<class T, class = decltype(declval<T>().~T())>
>> +void f(int) = delete;
>> +
>> +template<class T>
>> +void f(...);
>> +
>> +int main() {
>> + f<int&>(0);
>> +}
>> --
>> 2.48.0.rc1.35.g1b4e9a5f8b
>>
>
> Marek
>
@@ -7966,7 +7966,7 @@ extern tree lookup_and_finish_template_variable (tree, tree, tsubst_flags_t = tf
extern tree finish_template_variable (tree, tsubst_flags_t = tf_warning_or_error);
extern cp_expr finish_increment_expr (cp_expr, enum tree_code);
extern tree finish_this_expr (void);
-extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t);
+extern tree finish_pseudo_destructor_expr (tree, tree, tree, location_t, tsubst_flags_t);
extern cp_expr finish_unary_op_expr (location_t, enum tree_code, cp_expr,
tsubst_flags_t);
/* Whether this call to finish_compound_literal represents a C++11 functional
@@ -8847,7 +8847,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
pseudo_destructor_p = true;
postfix_expression
= finish_pseudo_destructor_expr (postfix_expression,
- s, type, location);
+ s, type, location,
+ tf_warning_or_error);
}
}
@@ -21537,7 +21537,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
tree op1 = RECUR (TREE_OPERAND (t, 1));
tree op2 = tsubst (TREE_OPERAND (t, 2), args, complain, in_decl);
RETURN (finish_pseudo_destructor_expr (op0, op1, op2,
- input_location));
+ input_location, complain));
}
case TREE_LIST:
@@ -21601,7 +21601,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
dtor = TREE_OPERAND (dtor, 0);
if (TYPE_P (dtor))
RETURN (finish_pseudo_destructor_expr
- (object, s, dtor, input_location));
+ (object, s, dtor, input_location, complain));
}
}
}
@@ -3527,7 +3527,7 @@ finish_this_expr (void)
tree
finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
- location_t loc)
+ location_t loc, tsubst_flags_t complain)
{
if (object == error_mark_node || destructor == error_mark_node)
return error_mark_node;
@@ -3538,16 +3538,18 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
{
if (scope == error_mark_node)
{
- error_at (loc, "invalid qualifying scope in pseudo-destructor name");
+ if (complain & tf_error)
+ error_at (loc, "invalid qualifying scope in pseudo-destructor name");
return error_mark_node;
}
if (is_auto (destructor))
destructor = TREE_TYPE (object);
if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor))
{
- error_at (loc,
- "qualified type %qT does not match destructor name ~%qT",
- scope, destructor);
+ if (complain & tf_error)
+ error_at (loc,
+ "qualified type %qT does not match destructor name ~%qT",
+ scope, destructor);
return error_mark_node;
}
@@ -3568,7 +3570,8 @@ finish_pseudo_destructor_expr (tree object, tree scope, tree destructor,
if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object),
destructor))
{
- error_at (loc, "%qE is not of type %qT", object, destructor);
+ if (complain & tf_error)
+ error_at (loc, "%qE is not of type %qT", object, destructor);
return error_mark_node;
}
}
new file mode 100644
@@ -0,0 +1,15 @@
+// PR c++/116417
+// { dg-do compile { target c++11 } }
+
+template<class T>
+T&& declval();
+
+template<class T, class = decltype(declval<T>().~T())>
+void f(int) = delete;
+
+template<class T>
+void f(...);
+
+int main() {
+ f<int&>(0);
+}