diff mbox series

[pushed] c++: lambda in DMI in class template [PR95870]

Message ID 20210405193822.1061490-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: lambda in DMI in class template [PR95870] | expand

Commit Message

Jason Merrill April 5, 2021, 7:38 p.m. UTC
Here enclosing_instantiation_of was failing to find a match because otctx is
struct S<T> and current_function_decl is S<int>::S(), so the latter has more
function contexts, and we end up trying to compare S() to NULL_TREE.

After spending a bit of time working on establishing the correspondence in
this case (class <=> constructor), it occurred to me that we could just use
DECL_SOURCE_LOCATION, which is unique for lambdas, since they cannot be
redeclared.  Since we're so close to release, for now I'm only doing this
for the case that was failing before.

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/ChangeLog:

	PR c++/95870
	* pt.c (enclosing_instantiation_of): Compare DECL_SOURCE_LOCATION if
	there is no enclosing non-lambda function.

gcc/testsuite/ChangeLog:

	PR c++/95870
	* g++.dg/cpp0x/lambda/lambda-nsdmi10.C: New test.
---
 gcc/cp/pt.c                                        | 13 +++++++++++++
 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C | 12 ++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C


base-commit: 7ebdef2076fda56cb4cffb941f6c2576f980f3b3
diff mbox series

Patch

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 396e622c4db..d6a8ede386d 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14371,6 +14371,19 @@  enclosing_instantiation_of (tree otctx)
 		  || instantiated_lambda_fn_p (tctx));
        tctx = decl_function_context (tctx))
     ++lambda_count;
+
+  if (!tctx)
+    {
+      /* Match using DECL_SOURCE_LOCATION, which is unique for all lambdas.
+
+	 For GCC 11 the above condition limits this to the previously failing
+	 case where all enclosing functions are lambdas (95870).  FIXME.  */
+      for (tree ofn = fn; ofn; ofn = decl_function_context (ofn))
+	if (DECL_SOURCE_LOCATION (ofn) == DECL_SOURCE_LOCATION (otctx))
+	  return ofn;
+      gcc_unreachable ();
+    }
+
   for (; fn; fn = decl_function_context (fn))
     {
       tree ofn = fn;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C
new file mode 100644
index 00000000000..810ed538719
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi10.C
@@ -0,0 +1,12 @@ 
+// PR c++/95870
+// { dg-do compile { target c++11 } }
+
+template <typename> struct S {
+  S();
+  int b = []() -> int { enum E {}; return 1; }();
+};
+struct C : S<int> {
+  C();
+};
+template <typename T> S<T>::S() = default;
+C::C() {}