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
This commit is contained in:
Jason Merrill 2013-03-16 22:38:50 -04:00 committed by Jason Merrill
parent 8e519a8b0a
commit c73356802f
8 changed files with 51 additions and 4 deletions

View 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.

View 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);
}
}

View 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 {

View 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)

View 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);
}

View 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. */

View File

@ -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;};
};

View File

@ -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; }();
};