diff options
author | Jason Merrill <jason@redhat.com> | 2013-03-16 22:38:50 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-03-16 22:38:50 -0400 |
commit | c73356802f430fd51f0d4db1ec928fb093c7c4a6 (patch) | |
tree | 327525948c4a7e69b6203fbe7bbe1911d384e157 /gcc | |
parent | 8e519a8b0a3543210d7103042cc0a2e1b3603832 (diff) | |
download | gcc-c73356802f430fd51f0d4db1ec928fb093c7c4a6.zip gcc-c73356802f430fd51f0d4db1ec928fb093c7c4a6.tar.gz gcc-c73356802f430fd51f0d4db1ec928fb093c7c4a6.tar.bz2 |
re PR c++/54764 (In class initialization of non-static lambda member can't be used in class with default template paramer)
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/decl.c | 12 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 3 | ||||
-rw-r--r-- | gcc/cp/pt.c | 9 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 2 | ||||
-rw-r--r-- | gcc/cp/tree.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg4.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi3.C | 9 |
8 files changed, 51 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 983365c..5f6932f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 40152b1..b67978d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); } } diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index f9a0fbe..b88ada3 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -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 { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4ffc353..1bbcba2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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) diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index e46b4bf..9a2b728 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 42ba677..a1cce64 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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 index 0000000..22179545 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-defarg4.C @@ -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 index 0000000..da7e0bf --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nsdmi3.C @@ -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; }(); +}; |