From 1df539fd197ef2427bdfa27156b92d2a857af949 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 3 Nov 2021 09:29:47 -0400 Subject: [PATCH] c++: remember pointer-to-member location Jakub recently mentioned that a PTRMEM_CST has no location; let's give it a location wrapper. gcc/cp/ChangeLog: * typeck.c (build_x_unary_op): Set address location. (convert_member_func_to_ptr): Handle location wrapper. * pt.c (convert_nontype_argument): Likewise. gcc/testsuite/ChangeLog: * g++.dg/template/crash106.C: Adjust. * g++.dg/diagnostic/ptrtomem3.C: New test. --- gcc/cp/pt.c | 2 ++ gcc/cp/typeck.c | 15 +++++++++++++-- gcc/testsuite/g++.dg/diagnostic/ptrtomem3.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/template/crash106.C | 4 ++-- 4 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 gcc/testsuite/g++.dg/diagnostic/ptrtomem3.C diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index c73e035d8b8..288625e3e93 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -7267,6 +7267,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) const bool val_dep_p = value_dependent_expression_p (expr); if (val_dep_p) expr = canonicalize_expr_argument (expr, complain); + else + STRIP_ANY_LOCATION_WRAPPER (expr); /* 14.3.2/5: The null pointer{,-to-member} conversion is applied to a non-type argument of "nullptr". */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 63a0eaef2da..84dcb6f014f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6492,6 +6492,11 @@ build_x_unary_op (location_t loc, enum tree_code code, cp_expr xarg, } exp = cp_build_addr_expr_strict (xarg, complain); + + if (TREE_CODE (exp) == PTRMEM_CST) + exp = maybe_wrap_with_location (exp, loc); + else + protected_set_expr_location (exp, loc); } if (processing_template_decl && exp != error_mark_node) @@ -8179,10 +8184,14 @@ convert_member_func_to_ptr (tree type, tree expr, tsubst_flags_t complain) if (!(complain & tf_warning_or_error)) return error_mark_node; + location_t loc = cp_expr_loc_or_input_loc (expr); + if (pedantic || warn_pmf2ptr) - pedwarn (input_location, pedantic ? OPT_Wpedantic : OPT_Wpmf_conversions, + pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpmf_conversions, "converting from %qH to %qI", intype, type); + STRIP_ANY_LOCATION_WRAPPER (expr); + if (TREE_CODE (intype) == METHOD_TYPE) expr = build_addr_func (expr, complain); else if (TREE_CODE (expr) == PTRMEM_CST) @@ -8197,7 +8206,9 @@ convert_member_func_to_ptr (tree type, tree expr, tsubst_flags_t complain) if (expr == error_mark_node) return error_mark_node; - return build_nop (type, expr); + expr = build_nop (type, expr); + SET_EXPR_LOCATION (expr, loc); + return expr; } /* Build a NOP_EXPR to TYPE, but mark it as a reinterpret_cast so that diff --git a/gcc/testsuite/g++.dg/diagnostic/ptrtomem3.C b/gcc/testsuite/g++.dg/diagnostic/ptrtomem3.C new file mode 100644 index 00000000000..6096a98f708 --- /dev/null +++ b/gcc/testsuite/g++.dg/diagnostic/ptrtomem3.C @@ -0,0 +1,14 @@ +// Check that the diagnostic for a pointer-to-member expression has the caret +// at the &. + +struct A +{ + int i; +}; + +void f(); + +int main() +{ + return &A::i; // { dg-error "10:cannot convert" } +} diff --git a/gcc/testsuite/g++.dg/template/crash106.C b/gcc/testsuite/g++.dg/template/crash106.C index f904bd4dc9b..35cedb55b0b 100644 --- a/gcc/testsuite/g++.dg/template/crash106.C +++ b/gcc/testsuite/g++.dg/template/crash106.C @@ -7,6 +7,6 @@ struct A template void foo(); // { dg-error "type" "" { target c++17_down } } }; -template > struct B {}; // { dg-error "type|declared" "" { target c++17_down } } +template > struct B {}; // { dg-error "type|declared|could not convert" "" { target c++17_down } } -B<> b; // { dg-error "(could not convert|no matches)" "" { target c++17_down } } +B<> b; // { dg-message "" "" { target c++17_down } }