2017-08-29 Jason Merrill <jason@redhat.com>
+ PR c++/81236 - ICE with template-id in generic lambda
+ * semantics.c (finish_id_expression): Remove special dependent case.
+ Avoid some later pieces when dependent.
+ (finish_qualified_id_expr): Do normal BASELINK handling in a
+ template. Always build a SCOPE_REF for a destructor BIT_NOT_EXPR.
+ (parsing_default_capturing_generic_lambda_in_template): Remove.
+ * parser.c (cp_parser_postfix_dot_deref_expression): Always give an
+ error for types that will never be complete.
+ * mangle.c (write_expression): Add sanity check.
+ * tree.c (build_qualified_name): Add sanity check.
+ (cp_walk_subtrees): Walk into the class context of a BASELINK.
+ * lambda.c (add_capture): Improve diagnostic for generic lambda
+ capture failure.
+ * call.c (build_new_method_call_1): Print the right constructor
+ name.
+
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.
/* In a template, be permissive by treating an object expression
of incomplete type as dependent (after a pedwarn). */
diagnostic_t kind = (processing_template_decl
+ && MAYBE_CLASS_TYPE_P (scope)
? DK_PEDWARN
: DK_ERROR);
cxx_incomplete_type_diagnostic
(location_of (postfix_expression),
postfix_expression, scope, kind);
+ if (!MAYBE_CLASS_TYPE_P (scope))
+ return error_mark_node;
if (processing_template_decl)
{
dependent_p = true;
return false;
}
-/* Return true iff our current scope is a default capturing generic lambda
- defined within a template. FIXME: This is part of a workaround (see
- semantics.c) to handle building lambda closure types correctly in templates
- which we ultimately want to defer to instantiation time. */
-
-bool
-parsing_default_capturing_generic_lambda_in_template (void)
-{
- if (!processing_template_decl || !current_class_type)
- return false;
-
- tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type);
- if (!lam || LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam) == CPLD_NONE)
- return false;
-
- tree callop = lambda_function (lam);
- if (!callop)
- return false;
-
- return (DECL_TEMPLATE_INFO (callop)
- && (DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (callop)) == callop)
- && ((current_nonlambda_class_type ()
- && CLASSTYPE_TEMPLATE_INFO (current_nonlambda_class_type ()))
- || ((current_nonlambda_function ()
- && DECL_TEMPLATE_INFO (current_nonlambda_function ())))));
-}
-
/* Parse a late-specified return type, if any. This is not a separate
non-terminal, but part of a function declarator, which looks like
qualifying_class);
pop_deferring_access_checks ();
}
- else if (BASELINK_P (expr) && !processing_template_decl)
+ else if (BASELINK_P (expr))
{
/* See if any of the functions are non-static members. */
/* If so, the expression may be relative to 'this'. */
expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false,
complain);
}
- else if (BASELINK_P (expr))
- ;
else
{
/* In a template, return a SCOPE_REF for most qualified-ids
know we have access and building up the SCOPE_REF confuses
non-type template argument handling. */
if (processing_template_decl
- && !currently_open_class (qualifying_class))
+ && (!currently_open_class (qualifying_class)
+ || TREE_CODE (expr) == BIT_NOT_EXPR))
expr = build_qualified_name (TREE_TYPE (expr),
qualifying_class, expr,
template_p);
? CP_ID_KIND_UNQUALIFIED_DEPENDENT
: CP_ID_KIND_UNQUALIFIED)));
- /* If the name was dependent on a template parameter and we're not in a
- default capturing generic lambda within a template, we will resolve the
- name at instantiation time. FIXME: For lambdas, we should defer
- building the closure type until instantiation time then we won't need
- the extra test here. */
if (dependent_p
- && !parsing_default_capturing_generic_lambda_in_template ())
- {
- if (DECL_P (decl)
- && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl)))
- /* Dependent type attributes on the decl mean that the TREE_TYPE is
- wrong, so just return the identifier. */
- return id_expression;
-
- /* If we found a variable, then name lookup during the
- instantiation will always resolve to the same VAR_DECL
- (or an instantiation thereof). */
- if (VAR_P (decl)
- || TREE_CODE (decl) == CONST_DECL
- || TREE_CODE (decl) == PARM_DECL)
- {
- mark_used (decl);
- return convert_from_reference (decl);
- }
-
- /* Create a SCOPE_REF for qualified names, if the scope is
- dependent. */
- if (scope)
- {
- if (TYPE_P (scope))
- {
- if (address_p && done)
- decl = finish_qualified_id_expr (scope, decl,
- done, address_p,
- template_p,
- template_arg_p,
- tf_warning_or_error);
- else
- {
- tree type = NULL_TREE;
- if (DECL_P (decl) && !dependent_scope_p (scope))
- type = TREE_TYPE (decl);
- decl = build_qualified_name (type,
- scope,
- id_expression,
- template_p);
- }
- }
- if (TREE_TYPE (decl))
- decl = convert_from_reference (decl);
- return decl;
- }
- /* A TEMPLATE_ID already contains all the information we
- need. */
- if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR)
- return id_expression;
- /* The same is true for FIELD_DECL, but we also need to
- make sure that the syntax is correct. */
- else if (TREE_CODE (decl) == FIELD_DECL)
- {
- /* Since SCOPE is NULL here, this is an unqualified name.
- Access checking has been performed during name lookup
- already. Turn off checking to avoid duplicate errors. */
- push_deferring_access_checks (dk_no_check);
- decl = finish_non_static_data_member
- (decl, NULL_TREE,
- /*qualifying_scope=*/NULL_TREE);
- pop_deferring_access_checks ();
- return decl;
- }
- return id_expression;
- }
+ && DECL_P (decl)
+ && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl)))
+ /* Dependent type attributes on the decl mean that the TREE_TYPE is
+ wrong, so just return the identifier. */
+ return id_expression;
if (TREE_CODE (decl) == NAMESPACE_DECL)
{
expression. Template parameters have already
been handled above. */
if (! error_operand_p (decl)
+ && !dependent_p
&& integral_constant_expression_p
&& ! decl_constant_var_p (decl)
&& TREE_CODE (decl) != CONST_DECL
decl = build_cxx_call (wrap, 0, NULL, tf_warning_or_error);
}
else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR
+ && !dependent_p
&& variable_template_p (TREE_OPERAND (decl, 0)))
{
decl = finish_template_variable (decl);
}
else if (scope)
{
+ if (TREE_CODE (decl) == SCOPE_REF)
+ {
+ gcc_assert (same_type_p (scope, TREE_OPERAND (decl, 0)));
+ decl = TREE_OPERAND (decl, 1);
+ }
+
decl = (adjust_result_of_qualified_name_lookup
(decl, scope, current_nonlambda_class_type()));