public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: non-dependent immediate member fn call [PR99895]
@ 2022-01-19 16:15 Patrick Palka
  2022-01-19 19:19 ` Jason Merrill
  0 siblings, 1 reply; 6+ messages in thread
From: Patrick Palka @ 2022-01-19 16:15 UTC (permalink / raw)
  To: gcc-patches

Here we're emitting a bogus error during ahead of time evaluation of a
non-dependent immediate member function call such as a.f(args) because
the defacto templated form for such a call is (a.f)(args) but we're
trying to evaluate it using the intermediate CALL_EXPR built by
build_over_call, which has the non-member form f(a, args).  The defacto
member form is built in build_new_method_call, so it seems we should
handle the immediate call there instead.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk and perhaps 11?

	PR c++/99895

gcc/cp/ChangeLog:

	* call.cc (build_over_call): Don't evaluate non-dependent
	immediate member function calls here.
	(build_new_method_call): Instead evaluate them here.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp2a/consteval-memfn1.C: New test.
	* g++.dg/cpp2a/consteval-memfn2.C: New test.
---
 gcc/cp/call.cc                                |  9 ++++-
 gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C | 15 ++++++++
 gcc/testsuite/g++.dg/cpp2a/consteval-memfn2.C | 34 +++++++++++++++++++
 3 files changed, 57 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/consteval-memfn2.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index d4a07a7a9b3..0583cc0083b 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -9241,7 +9241,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 				   addr, nargs, argarray);
       if (TREE_THIS_VOLATILE (fn) && cfun)
 	current_function_returns_abnormally = 1;
-      if (immediate_invocation_p (fn, nargs))
+      if (!DECL_FUNCTION_MEMBER_P (fn)
+	  /* Non-dependent immediate member function calls are evaluated in
+	     build_new_method_call.  */
+	  && immediate_invocation_p (fn, nargs))
 	{
 	  tree obj_arg = NULL_TREE, exprimm = expr;
 	  if (DECL_CONSTRUCTOR_P (fn))
@@ -11227,6 +11230,10 @@ skip_prune:
       call = convert_from_reference (call);
       if (cast_to_void)
 	call = build_nop (void_type_node, call);
+
+      if (immediate_invocation_p (fn, vec_safe_length (orig_args)))
+	fold_non_dependent_expr (call, complain,
+				 /*manifestly_const_eval=*/true);
     }
 
  /* Free all the conversions we allocated.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C
new file mode 100644
index 00000000000..d2df2e9b5ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn1.C
@@ -0,0 +1,15 @@
+// PR c++/99895
+// { dg-do compile { target c++20 } }
+
+struct fixed_string {
+  consteval int size(int n) const {
+    if (n < 0) throw; // { dg-error "not a constant" }
+    return n;
+  }
+};
+
+template<class>
+void VerifyHash(fixed_string s) {
+  s.size(0); // { dg-bogus "" }
+  s.size(-1); // { dg-message "expansion of" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval-memfn2.C b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn2.C
new file mode 100644
index 00000000000..71748f46b13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval-memfn2.C
@@ -0,0 +1,34 @@
+// PR c++/99895
+// { dg-do compile { target c++20 } }
+
+static constexpr unsigned hash(const char* s, unsigned length)
+{
+    s=s;
+    return length;
+}
+template<unsigned N>
+struct fixed_string
+{
+    constexpr fixed_string(const char (&s)[N])
+    {
+        for (int i = 0; i < N; i++)
+            str[i] = s[i];
+    }
+    consteval const char* data() const { return str; }
+    consteval unsigned size() const { return N-1; }
+    char str[N];
+};
+template<unsigned expected_hash, fixed_string... s>
+static consteval void VerifyHash()
+{
+    (
+      [](auto){static_assert(hash(s.data(), s.size()) == expected_hash);}(s)
+    ,...);
+    // The compiler mistakenly translates s.data() into s.data(&s)
+    // and then complains that the call is not valid, because
+    // the function expects 0 parameters and 1 "was provided".
+}
+void foo()
+{
+    VerifyHash<5, "khaki", "plums">();
+}
-- 
2.35.0.rc1


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-01-27 15:31 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-19 16:15 [PATCH] c++: non-dependent immediate member fn call [PR99895] Patrick Palka
2022-01-19 19:19 ` Jason Merrill
2022-01-26 22:27   ` Patrick Palka
2022-01-26 22:46     ` Patrick Palka
2022-01-27 14:02       ` Patrick Palka
2022-01-27 15:31         ` 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).