aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-08-29 16:37:15 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-08-29 16:37:15 -0400
commitf44a8dd56f5bfbd0596c39693e268ef880c06221 (patch)
treeb1c3f161803fc2b6d6b610a8db75bddd8b2369d1 /gcc/cp/semantics.c
parent72932ccf0ac4837b020d29b386d75fbceeb88735 (diff)
downloadgcc-f44a8dd56f5bfbd0596c39693e268ef880c06221.zip
gcc-f44a8dd56f5bfbd0596c39693e268ef880c06221.tar.gz
gcc-f44a8dd56f5bfbd0596c39693e268ef880c06221.tar.bz2
Reimplement handling of lambdas in templates.
* cp-tree.h (LAMBDA_FUNCTION_P): Check DECL_DECLARES_FUNCTION_P. * decl.c (start_preparsed_function): Call start_lambda_scope. (finish_function): Call finish_lambda_scope. * init.c (get_nsdmi): Call start/finish_lambda_scope. * lambda.c (start_lambda_scope): Only ignore VAR_DECL in a function. * parser.c (cp_parser_function_definition_after_declarator): Don't call start/finish_lambda_scope. * pt.c (retrieve_specialization): Ignore lambda functions in templates. (find_parameter_packs_r): Ignore capture proxies. Look into lambdas. (check_for_bare_parameter_packs): Allow bare packs in lambdas. (tsubst_default_argument): Call start/finish_lambda_scope. (tsubst_function_decl): Handle lambda functions differently. (tsubst_template_decl): Likewise. (tsubst_expr) [DECL_EXPR]: Skip closure declarations and capture proxies. (tsubst_lambda_expr): Create a new closure rather than instantiate the one from the template. (tsubst_copy_and_build): Don't register a specialization of a pack. (regenerate_decl_from_template): Call start/finish_lambda_scope. (instantiate_decl): Remove special lambda function handling. * semantics.c (process_outer_var_ref): Remove special generic lambda handling. Don't implicitly capture in a lambda in a template. Look for an existing proxy. * class.c (current_nonlambda_class_type): Use decl_type_context. From-SVN: r251433
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r--gcc/cp/semantics.c95
1 files changed, 48 insertions, 47 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index fe118cd..8f28221 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3301,40 +3301,56 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)
if (!mark_used (decl, complain))
return error_mark_node;
- bool saw_generic_lambda = false;
if (parsing_nsdmi ())
containing_function = NULL_TREE;
- else
- /* If we are in a lambda function, we can move out until we hit
- 1. the context,
- 2. a non-lambda function, or
- 3. a non-default capturing lambda function. */
- while (context != containing_function
- /* containing_function can be null with invalid generic lambdas. */
- && containing_function
- && LAMBDA_FUNCTION_P (containing_function))
- {
- tree closure = DECL_CONTEXT (containing_function);
- lambda_expr = CLASSTYPE_LAMBDA_EXPR (closure);
- if (generic_lambda_fn_p (containing_function))
- saw_generic_lambda = true;
+ if (containing_function && DECL_TEMPLATE_INFO (context)
+ && LAMBDA_FUNCTION_P (containing_function))
+ {
+ /* Check whether we've already built a proxy;
+ insert_pending_capture_proxies doesn't update
+ local_specializations. */
+ tree d = lookup_name (DECL_NAME (decl));
+ if (d && is_capture_proxy (d)
+ && DECL_CONTEXT (d) == containing_function)
+ return d;
+ }
- if (TYPE_CLASS_SCOPE_P (closure))
- /* A lambda in an NSDMI (c++/64496). */
- break;
+ /* If we are in a lambda function, we can move out until we hit
+ 1. the context,
+ 2. a non-lambda function, or
+ 3. a non-default capturing lambda function. */
+ while (context != containing_function
+ /* containing_function can be null with invalid generic lambdas. */
+ && containing_function
+ && LAMBDA_FUNCTION_P (containing_function))
+ {
+ tree closure = DECL_CONTEXT (containing_function);
+ lambda_expr = CLASSTYPE_LAMBDA_EXPR (closure);
- if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)
- == CPLD_NONE)
- break;
+ if (TYPE_CLASS_SCOPE_P (closure))
+ /* A lambda in an NSDMI (c++/64496). */
+ break;
- lambda_stack = tree_cons (NULL_TREE,
- lambda_expr,
- lambda_stack);
+ if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr)
+ == CPLD_NONE)
+ break;
- containing_function
- = decl_function_context (containing_function);
- }
+ lambda_stack = tree_cons (NULL_TREE,
+ lambda_expr,
+ lambda_stack);
+
+ containing_function
+ = decl_function_context (containing_function);
+ }
+
+ /* In a lambda within a template, wait until instantiation
+ time to implicitly capture. */
+ if (context == containing_function
+ && DECL_TEMPLATE_INFO (containing_function)
+ && any_dependent_template_arguments_p (DECL_TI_ARGS
+ (containing_function)))
+ return decl;
/* Core issue 696: "[At the July 2009 meeting] the CWG expressed
support for an approach in which a reference to a local
@@ -3343,26 +3359,11 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)
the complexity of the problem"
FIXME update for final resolution of core issue 696. */
- if (decl_maybe_constant_var_p (decl))
- {
- if (processing_template_decl && !saw_generic_lambda)
- /* In a non-generic lambda within a template, wait until instantiation
- time to decide whether to capture. For a generic lambda, we can't
- wait until we instantiate the op() because the closure class is
- already defined at that point. FIXME to get the semantics exactly
- right we need to partially-instantiate the lambda body so the only
- dependencies left are on the generic parameters themselves. This
- probably means moving away from our current model of lambdas in
- templates (instantiating the closure type) to one based on creating
- the closure type when instantiating the lambda context. That is
- probably also the way to handle lambdas within pack expansions. */
- return decl;
- else if (decl_constant_var_p (decl))
- {
- tree t = maybe_constant_value (convert_from_reference (decl));
- if (TREE_CONSTANT (t))
- return t;
- }
+ if (decl_constant_var_p (decl))
+ {
+ tree t = maybe_constant_value (convert_from_reference (decl));
+ if (TREE_CONSTANT (t))
+ return t;
}
if (lambda_expr && VAR_P (decl)