diff mbox series

C++ PATCH for c++/82565, ICE with concepts and generic lambda

Message ID CADzB+2nsJCwz=3UamZpTrXHCy9S68wzS53fL4-o0V4gKzo6npQ@mail.gmail.com
State New
Headers show
Series C++ PATCH for c++/82565, ICE with concepts and generic lambda | expand

Commit Message

Jason Merrill March 13, 2018, 8:14 p.m. UTC
Here, trying to evaluate the constraints of the test::visit template
led us to instantiating the generic lambda function; this ends up with
us trying to instantiate it with processing_template_decl still set.

A simple way to fix this case in GCC 8 is to not treat the lambda as a
nested function, because we've already resolved any references to
outer functions in tsubst_lambda_expr.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox series

Patch

commit 8b9654e9d4a6db1d42a47a77b0636c1a05a9d60d
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Mar 13 15:13:12 2018 -0400

            PR c++/82565 - ICE with concepts and generic lambda.
    
            * pt.c (instantiate_decl): Clear fn_context for lambdas.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a16aef6bf58..d720c33cf0a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -23460,6 +23460,9 @@  instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
   bool push_to_top, nested;
   tree fn_context;
   fn_context = decl_function_context (d);
+  if (LAMBDA_FUNCTION_P (d))
+    /* tsubst_lambda_expr resolved any references to enclosing functions.  */
+    fn_context = NULL_TREE;
   nested = current_function_decl != NULL_TREE;
   push_to_top = !(nested && fn_context == current_function_decl);
 
diff --git a/gcc/testsuite/g++.dg/concepts/lambda1.C b/gcc/testsuite/g++.dg/concepts/lambda1.C
new file mode 100644
index 00000000000..a77e65459b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/concepts/lambda1.C
@@ -0,0 +1,32 @@ 
+// PR c++/82565
+// { dg-do compile { target c++14 } }
+// { dg-additional-options -fconcepts }
+
+struct string
+{
+  string();
+  string(const char *);
+  bool empty() const;
+};
+
+template<typename T, typename ReturnType>
+concept bool Concept() {
+  return requires(T t, const string& s) {
+    { t(s) } -> ReturnType;
+  };
+}
+
+struct test {
+  string _str;
+
+  template<typename Visitor>
+    requires Concept<Visitor, bool>()
+  decltype(auto) visit(Visitor&& visitor) const {
+    return visitor(_str);
+  }
+
+};
+
+int main() {
+  test().visit([] (auto& x) { return x.empty(); });
+}