We instantiate the return type of the lambda outside of the function
context, at which point trying to walk from the template instantiation
context up to the context of 'f' hits NULL_TREE.  So we should handle
that.

There was also a SFINAE issue whereby we skipped the error in SFINAE
context, but still gave the inform.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 1742e12992e0df29546bde5b3714a07ec61e14c7
Author: Jason Merrill <ja...@redhat.com>
Date:   Wed Jan 11 07:45:01 2017 -0500

            PR c++/78337 - ICE on invalid with generic lambda
    
            * semantics.c (process_outer_var_ref): Check if containing_function
            is null.  Move inform call under complain test.

diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 342b671..4202475 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3278,6 +3278,8 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)
        2. a non-lambda function, or
        3. a non-default capturing lambda function.  */
     while (context != containing_function
+          /* containing_function can be null with invalid generic lambdas.  */
+          && containing_function
           && LAMBDA_FUNCTION_P (containing_function))
       {
        tree closure = DECL_CONTEXT (containing_function);
@@ -3365,10 +3367,13 @@ process_outer_var_ref (tree decl, tsubst_flags_t 
complain)
   else
     {
       if (complain & tf_error)
-       error (VAR_P (decl)
-              ? G_("use of local variable with automatic storage from 
containing function")
-              : G_("use of parameter from containing function"));
-      inform (DECL_SOURCE_LOCATION (decl), "%q#D declared here", decl);
+       {
+         error (VAR_P (decl)
+                ? G_("use of local variable with automatic storage from "
+                     "containing function")
+                : G_("use of parameter from containing function"));
+         inform (DECL_SOURCE_LOCATION (decl), "%q#D declared here", decl);
+       }
       return error_mark_node;
     }
   return decl;
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-ice5.C 
b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-ice5.C
new file mode 100644
index 0000000..473e412
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-ice5.C
@@ -0,0 +1,27 @@
+// PR c++/78337
+// { dg-do compile { target c++14 } }
+
+struct X {
+  static constexpr int foo (int b) {
+    return b;
+  }
+};
+
+template<int>
+using Void = void;
+
+template<typename F,typename A>
+auto
+bar(F f, A a) -> decltype( ( f(a) , 0 ) ) // { dg-error "no match" }
+{ return {}; }
+
+
+int main() {
+  //constexpr
+  int f = 3;
+  (void)f;
+  auto l = [](auto of_type_X)->
+    Void<(decltype(of_type_X)::foo(f), 0)> // { dg-error "variable" }
+    {return;};
+  bar(l , X{});                        // { dg-error "no match" }
+}

Reply via email to