public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-8152] c++: local fn and generic lambda [PR97219]
@ 2022-04-14  0:25 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2022-04-14  0:25 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:1824da60663b4532199ecd051d8ba6da8995821d

commit r12-8152-g1824da60663b4532199ecd051d8ba6da8995821d
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Apr 13 16:42:25 2022 -0400

    c++: local fn and generic lambda [PR97219]
    
    When instantiating the op() for a generic lambda, we can no longer do name
    lookup inside function scopes enclosing the lambda, so we need to remember
    the lookup result from processing the definition of the lambda.  So the code
    in finish_call_expr to throw away the lookup result and instead look it up
    again at instantiation time needs to be adjusted.  The approach I take is to
    only discard the result if the local extern comes from dependent scope; once
    the enclosing function template is instantiated and we're regenerating the
    lambda, then we can remember the result of lookup.  We also need any default
    arguments to be instantiated at that point.
    
            PR c++/97219
    
    gcc/cp/ChangeLog:
    
            * name-lookup.cc (dependent_local_decl_p): New.
            * cp-tree.h (dependent_local_decl_p): Declare.
            * semantics.cc (finish_call_expr): Use it.
            * pt.cc (tsubst_arg_types): Also substitute default args
            for local externs.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp1y/lambda-generic-local-fn1.C: New test.

Diff:
---
 gcc/cp/cp-tree.h                                      |  1 +
 gcc/cp/name-lookup.cc                                 | 18 ++++++++++++++++++
 gcc/cp/pt.cc                                          |  4 +++-
 gcc/cp/semantics.cc                                   |  6 +++---
 gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-fn1.C | 17 +++++++++++++++++
 5 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2f718852ac1..e9a3d09ac4c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8243,6 +8243,7 @@ extern tree fold_builtin_source_location	(location_t);
 /* in name-lookup.cc */
 extern tree strip_using_decl                    (tree);
 extern void diagnose_name_conflict		(tree, tree);
+extern bool dependent_local_decl_p		(tree);
 
 /* Tell the binding oracle what kind of binding we are looking for.  */
 
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 118da0950af..7b0638d3166 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8976,4 +8976,22 @@ cp_emit_debug_info_for_using (tree t, tree context)
     }
 }
 
+/* True if D is a local declaration in dependent scope.  Assumes that it is
+   (part of) the current lookup result for its name.  */
+
+bool
+dependent_local_decl_p (tree d)
+{
+  if (!DECL_LOCAL_DECL_P (d))
+    return false;
+
+  cxx_binding *b = IDENTIFIER_BINDING (DECL_NAME (d));
+  cp_binding_level *l = b->scope;
+  while (!l->this_entity)
+    l = l->level_chain;
+  return uses_template_parms (l->this_entity);
+}
+
+
+
 #include "gt-cp-name-lookup.h"
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 63c08706377..adc863de702 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -15182,7 +15182,9 @@ tsubst_arg_types (tree arg_types,
   /* Except that we do substitute default arguments under tsubst_lambda_expr,
      since the new op() won't have any associated template arguments for us
      to refer to later.  */
-  if (lambda_fn_in_template_p (in_decl))
+  if (lambda_fn_in_template_p (in_decl)
+      || (in_decl && TREE_CODE (in_decl) == FUNCTION_DECL
+	  && DECL_LOCAL_DECL_P (in_decl)))
     default_arg = tsubst_copy_and_build (default_arg, args, complain, in_decl,
 					 false/*fn*/, false/*constexpr*/);
 
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index f5ec808b1bc..f08c0b6281f 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -2690,13 +2690,13 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
 
   if (processing_template_decl)
     {
-      /* If FN is a local extern declaration or set thereof, look them up
-	 again at instantiation time.  */
+      /* If FN is a local extern declaration (or set thereof) in a template,
+	 look it up again at instantiation time.  */
       if (is_overloaded_fn (fn))
 	{
 	  tree ifn = get_first_fn (fn);
 	  if (TREE_CODE (ifn) == FUNCTION_DECL
-	      && DECL_LOCAL_DECL_P (ifn))
+	      && dependent_local_decl_p (ifn))
 	    orig_fn = DECL_NAME (ifn);
 	}
 
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-fn1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-fn1.C
new file mode 100644
index 00000000000..06919c535d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-local-fn1.C
@@ -0,0 +1,17 @@
+// PR c++/97219
+// { dg-do compile { target c++14 } }
+
+struct B;
+
+template <typename T>
+auto f(T *) {
+  void q(B *, void * = static_cast<T *>(0));
+  return [](auto *p) { q(p); };
+}
+
+void q(void *) = delete;
+
+int main(void) {
+  B *bp = 0;
+  f(bp)(bp);
+}


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-04-14  0:25 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-14  0:25 [gcc r12-8152] c++: local fn and generic lambda [PR97219] 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).