mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 12:21:09 +08:00
Fix lookup of initialized captures in unevaluated context.
* cp-tree.h (DECL_NORMAL_CAPTURE_P): New. * name-lookup.c (qualify_lookup): Check it. * parser.c (cp_parser_lambda_introducer): Pass explicit_init_p to add_capture. * semantics.c (add_capture): Set DECL_NORMAL_CAPTURE_P on captures without explicit init. (add_default_capture): Pass explicit_init_p. Fix capture by copy of types with explicit copy constructor. * cp-tree.h (TARGET_EXPR_DIRECT_INIT_P): New. (DIRECT_INIT_EXPR_P): New. * typeck.c (convert_for_initialization): Just return if DIRECT_INIT_EXPR_P. * parser.c (cp_parser_lambda_introducer): Use TARGET_EXPR_DIRECT_INIT_P for normal captures. From-SVN: r152500
This commit is contained in:
parent
ebde32fd24
commit
37a7519a24
@ -1,3 +1,22 @@
|
||||
2009-10-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
Fix lookup of initialized captures in unevaluated context.
|
||||
* cp-tree.h (DECL_NORMAL_CAPTURE_P): New.
|
||||
* name-lookup.c (qualify_lookup): Check it.
|
||||
* parser.c (cp_parser_lambda_introducer): Pass explicit_init_p
|
||||
to add_capture.
|
||||
* semantics.c (add_capture): Set DECL_NORMAL_CAPTURE_P
|
||||
on captures without explicit init.
|
||||
(add_default_capture): Pass explicit_init_p.
|
||||
|
||||
Fix capture by copy of types with explicit copy constructor.
|
||||
* cp-tree.h (TARGET_EXPR_DIRECT_INIT_P): New.
|
||||
(DIRECT_INIT_EXPR_P): New.
|
||||
* typeck.c (convert_for_initialization): Just return if
|
||||
DIRECT_INIT_EXPR_P.
|
||||
* semantics.c (build_lambda_object): Use
|
||||
TARGET_EXPR_DIRECT_INIT_P for normal captures.
|
||||
|
||||
2009-10-05 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* parser.c: Mark lambda_scope and lambda_count for PCH.
|
||||
|
@ -97,6 +97,7 @@ framework extensions, you must include this file before toplev.h, not after.
|
||||
STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
|
||||
TYPENAME_IS_RESOLVING_P (in TYPE_NAME_TYPE)
|
||||
LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (in LAMBDA_EXPR)
|
||||
TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
|
||||
3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
|
||||
ICS_BAD_FLAG (in _CONV)
|
||||
FN_TRY_BLOCK_P (in TRY_BLOCK)
|
||||
@ -147,6 +148,7 @@ framework extensions, you must include this file before toplev.h, not after.
|
||||
DECL_FIELD_IS_BASE (in FIELD_DECL)
|
||||
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
|
||||
DECL_THUNK_P (in a member FUNCTION_DECL)
|
||||
DECL_NORMAL_CAPTURE_P (in FIELD_DECL)
|
||||
|
||||
Usage of language-independent fields in a language-dependent manner:
|
||||
|
||||
@ -3199,6 +3201,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
||||
#define DECL_FIELD_IS_BASE(NODE) \
|
||||
DECL_LANG_FLAG_6 (FIELD_DECL_CHECK (NODE))
|
||||
|
||||
/* Nonzero for FIELD_DECL node means that this field is a simple (no
|
||||
explicit initializer) lambda capture field, making it invisible to
|
||||
name lookup in unevaluated contexts. */
|
||||
#define DECL_NORMAL_CAPTURE_P(NODE) \
|
||||
DECL_LANG_FLAG_7 (FIELD_DECL_CHECK (NODE))
|
||||
|
||||
/* Nonzero if TYPE is an anonymous union or struct type. We have to use a
|
||||
flag for this because "A union for which objects or pointers are
|
||||
declared is not an anonymous union" [class.union]. */
|
||||
@ -3633,6 +3641,16 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
||||
#define TARGET_EXPR_LIST_INIT_P(NODE) \
|
||||
TREE_LANG_FLAG_1 (TARGET_EXPR_CHECK (NODE))
|
||||
|
||||
/* True if this TARGET_EXPR expresses direct-initialization of an object
|
||||
to be named later. */
|
||||
#define TARGET_EXPR_DIRECT_INIT_P(NODE) \
|
||||
TREE_LANG_FLAG_2 (TARGET_EXPR_CHECK (NODE))
|
||||
|
||||
/* True if EXPR expresses direct-initialization of a TYPE. */
|
||||
#define DIRECT_INIT_EXPR_P(TYPE,EXPR) \
|
||||
(TREE_CODE (EXPR) == TARGET_EXPR && TREE_LANG_FLAG_2 (EXPR) \
|
||||
&& same_type_ignoring_top_level_qualifiers_p (TYPE, TREE_TYPE (EXPR)))
|
||||
|
||||
/* An enumeration of the kind of tags that C++ accepts. */
|
||||
enum tag_types {
|
||||
none_type = 0, /* Not a tag type. */
|
||||
@ -5041,7 +5059,7 @@ extern tree lambda_capture_field_type (tree);
|
||||
extern tree lambda_return_type (tree);
|
||||
extern tree lambda_function (tree);
|
||||
extern void apply_lambda_return_type (tree, tree);
|
||||
extern tree add_capture (tree, tree, tree, bool);
|
||||
extern tree add_capture (tree, tree, tree, bool, bool);
|
||||
extern tree add_default_capture (tree, tree, tree);
|
||||
extern tree lambda_expr_this_capture (tree);
|
||||
|
||||
|
@ -3757,10 +3757,9 @@ qualify_lookup (tree val, int flags)
|
||||
return true;
|
||||
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
|
||||
return false;
|
||||
/* In unevaluated context, look past capture fields. */
|
||||
/* FIXME this will cause trouble with the initializer extension. */
|
||||
/* In unevaluated context, look past normal capture fields. */
|
||||
if (cp_unevaluated_operand && TREE_CODE (val) == FIELD_DECL
|
||||
&& LAMBDA_TYPE_P (DECL_CONTEXT (val)))
|
||||
&& DECL_NORMAL_CAPTURE_P (val))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -7125,6 +7125,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
|
||||
tree capture_id;
|
||||
tree capture_init_expr;
|
||||
cp_id_kind idk = CP_ID_KIND_NONE;
|
||||
bool explicit_init_p = false;
|
||||
|
||||
enum capture_kind_type
|
||||
{
|
||||
@ -7151,7 +7152,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
|
||||
add_capture (lambda_expr,
|
||||
/*id=*/get_identifier ("__this"),
|
||||
/*initializer=*/finish_this_expr(),
|
||||
/*by_reference_p=*/false);
|
||||
/*by_reference_p=*/false,
|
||||
explicit_init_p);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -7190,6 +7192,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
|
||||
capture_init_expr = cp_parser_assignment_expression (parser,
|
||||
/*cast_p=*/true,
|
||||
&idk);
|
||||
explicit_init_p = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -7231,7 +7234,8 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
|
||||
add_capture (lambda_expr,
|
||||
capture_id,
|
||||
capture_init_expr,
|
||||
/*by_reference_p=*/capture_kind == BY_REFERENCE);
|
||||
/*by_reference_p=*/capture_kind == BY_REFERENCE,
|
||||
explicit_init_p);
|
||||
}
|
||||
|
||||
cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
|
||||
|
@ -5328,6 +5328,20 @@ build_lambda_object (tree lambda_expr)
|
||||
do some magic to make it work here. */
|
||||
if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
|
||||
val = build_array_copy (val);
|
||||
else if (DECL_NORMAL_CAPTURE_P (field)
|
||||
&& TREE_CODE (TREE_TYPE (field)) != REFERENCE_TYPE)
|
||||
{
|
||||
/* "the entities that are captured by copy are used to
|
||||
direct-initialize each corresponding non-static data
|
||||
member of the resulting closure object."
|
||||
|
||||
There's normally no way to express direct-initialization
|
||||
from an element of a CONSTRUCTOR, so we build up a special
|
||||
TARGET_EXPR to bypass the usual copy-initialization. */
|
||||
val = force_rvalue (val);
|
||||
if (TREE_CODE (val) == TARGET_EXPR)
|
||||
TARGET_EXPR_DIRECT_INIT_P (val) = true;
|
||||
}
|
||||
|
||||
CONSTRUCTOR_APPEND_ELT (elts, DECL_NAME (field), val);
|
||||
}
|
||||
@ -5545,7 +5559,8 @@ capture_decltype (tree decl)
|
||||
and return it. */
|
||||
|
||||
tree
|
||||
add_capture (tree lambda, tree id, tree initializer, bool by_reference_p)
|
||||
add_capture (tree lambda, tree id, tree initializer, bool by_reference_p,
|
||||
bool explicit_init_p)
|
||||
{
|
||||
tree type;
|
||||
tree member;
|
||||
@ -5560,6 +5575,13 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p)
|
||||
|
||||
/* Make member variable. */
|
||||
member = build_lang_decl (FIELD_DECL, id, type);
|
||||
if (!explicit_init_p)
|
||||
/* Normal captures are invisible to name lookup but uses are replaced
|
||||
with references to the capture field; we implement this by only
|
||||
really making them invisible in unevaluated context; see
|
||||
qualify_lookup. For now, let's make explicitly initialized captures
|
||||
always visible. */
|
||||
DECL_NORMAL_CAPTURE_P (member) = true;
|
||||
|
||||
/* Add it to the appropriate closure class. */
|
||||
finish_member_declaration (member);
|
||||
@ -5605,7 +5627,8 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
|
||||
/*by_reference_p=*/
|
||||
(!this_capture_p
|
||||
&& (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda)
|
||||
== CPLD_REFERENCE)));
|
||||
== CPLD_REFERENCE)),
|
||||
/*explicit_init_p=*/false);
|
||||
|
||||
{
|
||||
/* Have to get the old value of current_class_ref. */
|
||||
|
@ -6893,6 +6893,11 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
|
||||
|
||||
type = complete_type (type);
|
||||
|
||||
if (DIRECT_INIT_EXPR_P (type, rhs))
|
||||
/* Don't try to do copy-initialization if we already have
|
||||
direct-initialization. */
|
||||
return rhs;
|
||||
|
||||
if (MAYBE_CLASS_TYPE_P (type))
|
||||
return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2009-10-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/lambda/lambda-init.C: New.
|
||||
* g++.dg/cpp0x/lambda/lambda-direct-init.C: New.
|
||||
|
||||
2009-10-06 Richard Guenther <rguenther@suse.de>
|
||||
|
||||
PR lto/41502
|
||||
|
14
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-direct-init.C
Normal file
14
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-direct-init.C
Normal file
@ -0,0 +1,14 @@
|
||||
// Test that capture by copy uses direct-initialization.
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
struct A
|
||||
{
|
||||
A();
|
||||
explicit A(const A&);
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
A a;
|
||||
[a]{};
|
||||
}
|
8
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-init.C
Normal file
8
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-init.C
Normal file
@ -0,0 +1,8 @@
|
||||
// Test for the explicit initializer extension
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
int main()
|
||||
{
|
||||
int j = [i = 2]{sizeof(i); return i;}();
|
||||
return (j != 2);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user