@@ -9007,6 +9007,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
if (! (complain & tf_error))
return error_mark_node;
+ basetype = DECL_CONTEXT (fn);
name = constructor_name (basetype);
if (permerror (input_location,
"cannot call constructor %<%T::%D%> directly",
@@ -590,7 +590,11 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
/* Add it to the appropriate closure class if we've started it. */
if (current_class_type
&& current_class_type == LAMBDA_EXPR_CLOSURE (lambda))
- finish_member_declaration (member);
+ {
+ if (COMPLETE_TYPE_P (current_class_type))
+ internal_error ("trying to capture %qD after closure is complete", id);
+ finish_member_declaration (member);
+ }
tree listmem = member;
if (variadic)
@@ -3015,6 +3015,7 @@ write_expression (tree expr)
{
scope = TREE_OPERAND (expr, 0);
member = TREE_OPERAND (expr, 1);
+ gcc_assert (!BASELINK_P (member));
}
else
{
@@ -7446,11 +7446,14 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
/* 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;
@@ -20671,33 +20674,6 @@ parsing_nsdmi (void)
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
@@ -2035,7 +2035,7 @@ finish_qualified_id_expr (tree qualifying_class,
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'. */
@@ -2055,8 +2055,6 @@ finish_qualified_id_expr (tree qualifying_class,
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
@@ -2065,7 +2063,8 @@ finish_qualified_id_expr (tree qualifying_class,
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);
@@ -3595,78 +3594,12 @@ finish_id_expression (tree id_expression,
? 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)
{
@@ -3700,6 +3633,7 @@ finish_id_expression (tree id_expression,
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
@@ -3726,6 +3660,7 @@ finish_id_expression (tree id_expression,
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);
@@ -3734,6 +3669,12 @@ finish_id_expression (tree id_expression,
}
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()));
@@ -2028,6 +2028,7 @@ build_qualified_name (tree type, tree scope, tree name, bool template_p)
|| scope == error_mark_node
|| name == error_mark_node)
return error_mark_node;
+ gcc_assert (TREE_CODE (name) != SCOPE_REF);
t = build2 (SCOPE_REF, type, scope, name);
QUALIFIED_NAME_IS_TEMPLATE (t) = template_p;
PTRMEM_OK_P (t) = true;
@@ -4663,6 +4664,8 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
break;
case BASELINK:
+ if (BASELINK_QUALIFIED_P (*tp))
+ WALK_SUBTREE (BINFO_TYPE (BASELINK_ACCESS_BINFO (*tp)));
WALK_SUBTREE (BASELINK_FUNCTIONS (*tp));
*walk_subtrees_p = 0;
break;
new file mode 100644
@@ -0,0 +1,17 @@
+// PR c++/81236
+// { dg-do compile { target c++14 } }
+
+struct A { constexpr operator int() { return 24; } };
+
+struct MyType {
+ void crash() {
+ auto l = [&](auto i){
+ make_crash<i>(); // Line (1)
+ };
+
+ l(A{});
+ }
+
+ template<int i>
+ void make_crash() {}
+};
new file mode 100644
@@ -0,0 +1,17 @@
+// PR c++/81236
+// { dg-do compile { target c++14 } }
+
+struct A { constexpr operator int() { return 24; } };
+
+struct MyType {
+ void crash() {
+ auto l = [&](auto i){
+ MyType::make_crash<i>(); // Line (1)
+ };
+
+ l(A{});
+ }
+
+ template<int i>
+ void make_crash() {}
+};
@@ -11,7 +11,7 @@ struct A
template <typename T> struct B
{
T &foo ();
- B () { foo.~T (); } // { dg-error "15:invalid use of member" }
+ B () { foo.~T (); } // { dg-error "10:invalid use of member" }
};
B<int> b;
@@ -37,7 +37,7 @@ template <typename T> struct E
{
T &foo ();
typedef long int U;
- E () { foo.~U (); } // { dg-error "10:is not of type" }
+ E () { foo.~U (); } // { dg-error "10:invalid use of member" }
};
E<int> e;