The standard says that lambdas go in the enclosing block, class or namespace scope, but also that default arguments aren't parsed until the class is complete. So we need to accept pushing a lambda into a complete class.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.8.
commit a3eed6be088f776afde7a9d6020a477dc04c23f2
Author: Jason Merrill <ja...@redhat.com>
Date:   Wed Aug 7 16:40:53 2013 -0400

    	PR c++/58083
    	* name-lookup.c (push_class_level_binding_1): It's OK to push a
    	lambda type after the enclosing type is complete.

diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 0fe0246..cf6c757 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3062,8 +3062,10 @@ push_class_level_binding_1 (tree name, tree x)
   if (name == error_mark_node)
     return false;
 
-  /* Check for invalid member names.  */
-  gcc_assert (TYPE_BEING_DEFINED (current_class_type));
+  /* Check for invalid member names.  But don't worry about a default
+     argument-scope lambda being pushed after the class is complete.  */
+  gcc_assert (TYPE_BEING_DEFINED (current_class_type)
+	      || LAMBDA_TYPE_P (TREE_TYPE (decl)));
   /* Check that we're pushing into the right binding level.  */
   gcc_assert (current_class_type == class_binding_level->this_entity);
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg5.C
new file mode 100644
index 0000000..d85918d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg5.C
@@ -0,0 +1,30 @@
+// PR c++/58083
+// { dg-do compile { target c++11 } }
+
+namespace details {
+struct iterator_concept_checker
+{
+    typedef char yes_type;
+    typedef char (&no_type)[2];
+
+    template <typename T>
+    static no_type test(...);
+
+    template <typename T>
+    static yes_type test(
+        int*
+	, void (*)(T) = [](T it)
+        {
+            auto copy = T{it};                              // copy constructible
+            copy = it;                                      // copy assignable
+            copy.~T();                                      // destroyable
+            ++it;                                           // incrementable
+        }
+      );
+};
+}
+
+int main()
+{
+  details::iterator_concept_checker::test<int>(0);
+}

Reply via email to