https://gcc.gnu.org/g:232d3a73e18d6886f0a5781048a78da293fbb014
commit r15-6973-g232d3a73e18d6886f0a5781048a78da293fbb014 Author: Patrick Palka <ppa...@redhat.com> Date: Thu Jan 16 16:05:46 2025 -0500 c++: make finish_pseudo_destructor_expr SFINAE-aware [PR116417] 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 emitting a diagnostic. gcc/testsuite/ChangeLog: * g++.dg/template/pseudodtor7.C: New test. Reviewed-by: Marek Polacek <pola...@redhat.com> Reviewed-by: Jason Merrill <ja...@redhat.com> Diff: --- 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(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 269aca5d4f40..e229fe02cbb0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7975,7 +7975,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 ba2c4dbb0538..c030a18689e0 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -8862,7 +8862,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 961696f333ea..00b61aec24ea 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -21669,7 +21669,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: @@ -21733,7 +21733,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 2daad2d27bea..e891319f9a99 100644 --- a/gcc/cp/semantics.cc +++ b/gcc/cp/semantics.cc @@ -3570,7 +3570,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; @@ -3581,16 +3581,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; } @@ -3611,7 +3613,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 000000000000..302b8c96625f --- /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); +}