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

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() {}

base-commit: 7ebdef2076fda56cb4cffb941f6c2576f980f3b3
-- 
2.27.0

Reply via email to