re PR c++/54764 (In class initialization of non-static lambda member can't be used...
authorJason Merrill <jason@redhat.com>
Sun, 17 Mar 2013 02:38:50 +0000 (22:38 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 17 Mar 2013 02:38:50 +0000 (22:38 -0400)
PR c++/54764
PR c++/55972
* name-lookup.h (tag_scope): Add ts_lambda.
* semantics.c (begin_lambda_type): Use it.
* decl.c (xref_tag_1): Set CLASSTYPE_LAMBDA_EXPR.
* pt.c (check_default_tmpl_args): Ignore lambdas.
(push_template_decl_real): Handle lambdas.
* tree.c (no_linkage_check): Adjust lambda check.

From-SVN: r196742

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/name-lookup.h
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi3.C [new file with mode: 0644]

index 983365ca5e8b8d989e2229eadce874503559373c..5f6932f2ef79051de1c5340970d85cfcbbb7a35a 100644 (file)
@@ -1,5 +1,14 @@
 2013-03-16  Jason Merrill  <jason@redhat.com>
 
+       PR c++/54764
+       PR c++/55972
+       * name-lookup.h (tag_scope): Add ts_lambda.
+       * semantics.c (begin_lambda_type): Use it.
+       * decl.c (xref_tag_1): Set CLASSTYPE_LAMBDA_EXPR.
+       * pt.c (check_default_tmpl_args): Ignore lambdas.
+       (push_template_decl_real): Handle lambdas.
+       * tree.c (no_linkage_check): Adjust lambda check.
+
        PR c++/56039
        * tree.c (strip_typedefs_expr): Complain about lambda, don't abort.
 
index 40152b194fbf3229a6c9f769915c57f496f8e2c8..b67978de7c0113c35e9665841fc630270f2cbfeb 100644 (file)
@@ -11887,11 +11887,12 @@ lookup_and_check_tag (enum tag_types tag_code, tree name,
 
 static tree
 xref_tag_1 (enum tag_types tag_code, tree name,
-            tag_scope scope, bool template_header_p)
+            tag_scope orig_scope, bool template_header_p)
 {
   enum tree_code code;
   tree t;
   tree context = NULL_TREE;
+  tag_scope scope;
 
   gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
 
@@ -11911,6 +11912,11 @@ xref_tag_1 (enum tag_types tag_code, tree name,
       gcc_unreachable ();
     }
 
+  if (orig_scope == ts_lambda)
+    scope = ts_current;
+  else
+    scope = orig_scope;
+
   /* In case of anonymous name, xref_tag is only called to
      make type node and push name.  Name lookup is not required.  */
   if (ANON_AGGRNAME_P (name))
@@ -11984,6 +11990,10 @@ xref_tag_1 (enum tag_types tag_code, tree name,
        {
          t = make_class_type (code);
          TYPE_CONTEXT (t) = context;
+         if (orig_scope == ts_lambda)
+           /* Remember that we're declaring a lambda to avoid bogus errors
+              in push_template_decl.  */
+           CLASSTYPE_LAMBDA_EXPR (t) = error_mark_node;
          t = pushtag (name, t, scope);
        }
     }
index f9a0fbe4dcbb466c580f0146135d2beb550e0c5d..b88ada37c960d1e54bc7ff2af19916b5be0ca55c 100644 (file)
@@ -132,10 +132,11 @@ typedef enum tag_scope {
   ts_global = 1,       /* All scopes.  This is the 3.4.1
                           [basic.lookup.unqual] lookup mentioned
                           in [basic.lookup.elab]/2.  */
-  ts_within_enclosing_non_class = 2    /* Search within enclosing non-class
+  ts_within_enclosing_non_class = 2,   /* Search within enclosing non-class
                                           only, for friend class lookup
                                           according to [namespace.memdef]/3
                                           and [class.friend]/9.  */
+  ts_lambda = 3                        /* Declaring a lambda closure.  */
 } tag_scope;
 
 typedef struct GTY(()) cp_class_binding {
index 4ffc353ed0e8e652993748b513d828a2b7f2bb0a..1bbcba2ac9fd2b3493fbad183643e390809309a6 100644 (file)
@@ -4306,6 +4306,13 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary,
        local scope.  */
     return true;
 
+  if (TREE_CODE (decl) == TYPE_DECL
+      && TREE_TYPE (decl)
+      && LAMBDA_TYPE_P (TREE_TYPE (decl)))
+    /* A lambda doesn't have an explicit declaration; don't complain
+       about the parms of the enclosing class.  */
+    return true;
+
   if (current_class_type
       && !TYPE_BEING_DEFINED (current_class_type)
       && DECL_LANG_SPECIFIC (decl)
@@ -4674,6 +4681,8 @@ push_template_decl_real (tree decl, bool is_friend)
   if (!ctx
       || TREE_CODE (ctx) == FUNCTION_DECL
       || (CLASS_TYPE_P (ctx) && TYPE_BEING_DEFINED (ctx))
+      || (TREE_CODE (decl) == TYPE_DECL
+         && LAMBDA_TYPE_P (TREE_TYPE (decl)))
       || (is_friend && !DECL_TEMPLATE_INFO (decl)))
     {
       if (DECL_LANG_SPECIFIC (decl)
index e46b4bfae9ce50cd2e065133bdcafcee801c061d..9a2b7285dc91de8352cd91c4a414ba7672a7f386 100644 (file)
@@ -8984,7 +8984,7 @@ begin_lambda_type (tree lambda)
     /* Create the new RECORD_TYPE for this lambda.  */
     type = xref_tag (/*tag_code=*/record_type,
                      name,
-                     /*scope=*/ts_within_enclosing_non_class,
+                     /*scope=*/ts_lambda,
                      /*template_header_p=*/false);
   }
 
index 42ba677056c807ffa35f3d46ce47ea815fb3d09a..a1cce647b24d6ede73c49e7d49d686ff431e0f6c 100644 (file)
@@ -2028,11 +2028,12 @@ no_linkage_check (tree t, bool relaxed_p)
       if (TYPE_PTRMEMFUNC_P (t))
        goto ptrmem;
       /* Lambda types that don't have mangling scope have no linkage.  We
-        check CLASSTYPE_LAMBDA_EXPR here rather than LAMBDA_TYPE_P because
+        check CLASSTYPE_LAMBDA_EXPR for error_mark_node because
         when we get here from pushtag none of the lambda information is
         set up yet, so we want to assume that the lambda has linkage and
         fix it up later if not.  */
       if (CLASSTYPE_LAMBDA_EXPR (t)
+         && CLASSTYPE_LAMBDA_EXPR (t) != error_mark_node
          && LAMBDA_TYPE_EXTRA_SCOPE (t) == NULL_TREE)
        return t;
       /* Fall through.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg4.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg4.C
new file mode 100644 (file)
index 0000000..2217954
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/54764
+// { dg-require-effective-target c++11 }
+
+template<class T = void>
+struct c
+{
+  int (*f)(int) = [](int i){return i + i;};
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi3.C
new file mode 100644 (file)
index 0000000..da7e0bf
--- /dev/null
@@ -0,0 +1,9 @@
+// PR c++/55972
+// { dg-do compile { target c++11 } }
+
+class C
+{
+  void f();
+  int j = 10;
+  int i = [this]() { return this->j; }();
+};