diff options
author | Patrick Palka <ppalka@redhat.com> | 2023-05-07 10:24:49 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2023-05-07 10:24:49 -0400 |
commit | 7f4840ddef9746ab591c78ecdd750e3b18aa1ce6 (patch) | |
tree | 3f5d8e64336e092b7f95b9ca3d9e7bbdb7b11328 /gcc | |
parent | b05b529125fa51e24b35ef9ac13b875521c9b052 (diff) | |
download | gcc-7f4840ddef9746ab591c78ecdd750e3b18aa1ce6.zip gcc-7f4840ddef9746ab591c78ecdd750e3b18aa1ce6.tar.gz gcc-7f4840ddef9746ab591c78ecdd750e3b18aa1ce6.tar.bz2 |
c++: potentiality of templated memfn call [PR109480]
Here we're incorrectly deeming the templated call a.g() inside b's
initializer as potentially constant, despite g being non-constexpr,
which leads to us needlessly instantiating the initializer ahead of time
and which subsequently triggers a bug in access checking deferral (to be
fixed by the follow-up patch).
This patch fixes this by calling get_fns earlier during CALL_EXPR
potentiality checking so that when we extract a FUNCTION_DECL out of a
templated member function call (whose overall callee is typically a
COMPONENT_REF) we do the usual constexpr-eligibility checking for it.
In passing, I noticed the nearby special handling of the object argument
of a non-static member function call is effectively the same as the
generic argument handling a few lines below. So this patch just gets
rid of this special handling; otherwise we'd have to adapt it to handle
templated versions of such calls.
PR c++/109480
gcc/cp/ChangeLog:
* constexpr.cc (potential_constant_expression_1) <case CALL_EXPR>:
Reorganize to call get_fns sooner. Remove special handling of
the object argument of a non-static member function call. Remove
dead store to 'fun'.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/noexcept59.C: Make e() constexpr so that the
expected "without object" diagnostic isn't replaced by a
"call to non-constexpr function" diagnostic.
* g++.dg/template/non-dependent25.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/constexpr.cc | 32 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/noexcept59.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/non-dependent25.C | 14 |
3 files changed, 21 insertions, 27 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 70dd6cf..987a536 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -9135,6 +9135,10 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, if (fun && is_overloaded_fn (fun)) { + if (!RECUR (fun, true)) + return false; + fun = get_fns (fun); + if (TREE_CODE (fun) == FUNCTION_DECL) { if (builtin_valid_in_constant_expr_p (fun)) @@ -9165,36 +9169,12 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, explain_invalid_constexpr_fn (fun); return false; } - /* A call to a non-static member function takes the address - of the object as the first argument. But in a constant - expression the address will be folded away, so look - through it now. */ - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fun) - && !DECL_CONSTRUCTOR_P (fun)) - { - tree x = get_nth_callarg (t, 0); - if (is_this_parameter (x)) - return true; - /* Don't require an immediately constant value, as - constexpr substitution might not use the value. */ - bool sub_now = false; - if (!potential_constant_expression_1 (x, rval, strict, - sub_now, fundef_p, - flags, jump_target)) - return false; - i = 1; - } - } - else - { - if (!RECUR (fun, true)) - return false; - fun = get_first_fn (fun); } + + fun = OVL_FIRST (fun); /* Skip initial arguments to base constructors. */ if (DECL_BASE_CONSTRUCTOR_P (fun)) i = num_artificial_parms_for (fun); - fun = DECL_ORIGIN (fun); } else if (fun) { diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept59.C b/gcc/testsuite/g++.dg/cpp0x/noexcept59.C index c752601..1dc826d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/noexcept59.C +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept59.C @@ -3,7 +3,7 @@ template <class ...Ts> class A { - void e (); + constexpr bool e () { return true; }; bool f (int() noexcept(this->e())); // { dg-error "this" } bool g (int() noexcept(e())); // { dg-error "without object" } }; diff --git a/gcc/testsuite/g++.dg/template/non-dependent25.C b/gcc/testsuite/g++.dg/template/non-dependent25.C new file mode 100644 index 0000000..c00e445 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/non-dependent25.C @@ -0,0 +1,14 @@ +// PR c++/109480 + +template<class T> +struct A { + void f() { + A<int> a; + const bool b = a.g(); // { dg-bogus "private" } + } + +private: + bool g() const; +}; + +template struct A<int>; |