and during the instantiation of template functions.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
- 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2008, 2009 Free Software Foundation, Inc.
Written by Mark Mitchell (mmitchell@usa.net) based on code found
formerly in parse.y and pt.c.
otherwise we'll get an error. Gross, but ... */
STRIP_NOPS (operand);
- operand = mark_lvalue_use (operand);
-
if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error))
operand = error_mark_node;
{
gcc_assert (TREE_CODE (decl) == FIELD_DECL);
- if (!object)
+ if (!object && cp_unevaluated_operand != 0)
{
+ /* DR 613: Can use non-static data members without an associated
+ object in sizeof/decltype/alignof. */
tree scope = qualifying_scope;
if (scope == NULL_TREE)
scope = context_for_name_lookup (decl);
object = maybe_dummy_object (scope, NULL);
}
- /* DR 613: Can use non-static data members without an associated
- object in sizeof/decltype/alignof. */
- if (is_dummy_object (object) && cp_unevaluated_operand == 0
- && (!processing_template_decl || !current_class_ref))
+ if (!object)
{
if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
return error_mark_node;
}
+ /* If decl is a non-capture field and object has a lambda type,
+ then we have a reference to a member of 'this' from a
+ lambda inside a non-static member function, and we must get to decl
+ through the 'this' capture. If decl is not a member of that object,
+ either, then its access will still fail later. */
+ if (LAMBDA_TYPE_P (TREE_TYPE (object))
+ && !LAMBDA_TYPE_P (DECL_CONTEXT (decl)))
+ object = cp_build_indirect_ref (lambda_expr_this_capture
+ (CLASSTYPE_LAMBDA_EXPR
+ (TREE_TYPE (object))),
+ RO_NULL,
+ /*complain=*/tf_warning_or_error);
+
if (current_class_ptr)
TREE_USED (current_class_ptr) = 1;
if (processing_template_decl && !qualifying_scope)
else
{
tree access_type = TREE_TYPE (object);
+ tree lookup_context = context_for_name_lookup (decl);
+
+ while (!DERIVED_FROM_P (lookup_context, access_type))
+ {
+ access_type = TYPE_CONTEXT (access_type);
+ while (access_type && DECL_P (access_type))
+ access_type = DECL_CONTEXT (access_type);
+
+ if (!access_type)
+ {
+ error ("object missing in reference to %q+D", decl);
+ error ("from this location");
+ return error_mark_node;
+ }
+ }
perform_or_defer_access_check (TYPE_BINFO (access_type), decl,
decl);
else if (TREE_CODE (expr) == FIELD_DECL)
{
push_deferring_access_checks (dk_no_check);
- expr = finish_non_static_data_member (expr, NULL_TREE,
+ expr = finish_non_static_data_member (expr, current_class_ref,
qualifying_class);
pop_deferring_access_checks ();
}
else if (BASELINK_P (expr) && !processing_template_decl)
{
+ tree fns;
tree ob;
/* See if any of the functions are non-static members. */
+ fns = BASELINK_FUNCTIONS (expr);
+ if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
+ fns = TREE_OPERAND (fns, 0);
/* If so, the expression may be relative to 'this'. */
- if (!shared_member_p (expr)
+ if (!shared_member_p (fns)
&& (ob = maybe_dummy_object (qualifying_class, NULL),
!is_dummy_object (ob)))
expr = (build_class_member_access_expr
already. Turn off checking to avoid duplicate errors. */
push_deferring_access_checks (dk_no_check);
decl = finish_non_static_data_member
- (decl, NULL_TREE,
+ (decl, current_class_ref,
/*qualifying_scope=*/NULL_TREE);
pop_deferring_access_checks ();
return decl;
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,
+ decl = finish_non_static_data_member (decl, current_class_ref,
/*qualifying_scope=*/NULL_TREE);
pop_deferring_access_checks ();
}
{
tree first_fn;
- first_fn = get_first_fn (decl);
+ first_fn = decl;
+ if (TREE_CODE (first_fn) == TEMPLATE_ID_EXPR)
+ first_fn = TREE_OPERAND (first_fn, 0);
+ first_fn = get_first_fn (first_fn);
if (TREE_CODE (first_fn) == TEMPLATE_DECL)
first_fn = DECL_TEMPLATE_RESULT (first_fn);
return type;
}
- expr = mark_type_use (expr);
-
type = unlowered_expr_type (expr);
if (!type || type == unknown_type_node)
}
if (TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE
- || TREE_TYPE (expr) == unknown_type_node)
+ || TREE_CODE (TREE_TYPE (expr)) == UNKNOWN_TYPE)
{
if (TREE_CODE (expr) == COMPONENT_REF
|| TREE_CODE (expr) == COMPOUND_EXPR)
expand_call{,_inline}. */
cxx_mark_addressable (slot);
CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true;
- call_expr = build2 (INIT_EXPR, TREE_TYPE (call_expr), slot, call_expr);
+ call_expr = build2 (MODIFY_EXPR, TREE_TYPE (call_expr), slot, call_expr);
}
else if (style == pcc)
{
case PARM_DECL:
case RESULT_DECL:
case TEMPLATE_PARM_INDEX:
- expr = mark_type_use (expr);
type = TREE_TYPE (expr);
break;
break;
case COMPONENT_REF:
- mark_type_use (expr);
type = is_bitfield_expr_with_lowered_type (expr);
if (!type)
type = TREE_TYPE (TREE_OPERAND (expr, 1));
gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda));
result = finish_non_static_data_member (this_capture,
- NULL_TREE,
+ current_class_ref,
/*qualifying_scope=*/NULL_TREE);
/* If 'this' is captured, each use of 'this' is transformed into an
start_preparsed_function (convfn, NULL_TREE,
SF_PRE_PARSED | SF_INCLASS_INLINE);
- if (DECL_ONE_ONLY (statfn))
- {
- /* Put the thunk in the same comdat group as the call op. */
- struct cgraph_node *callop_node, *thunk_node;
- DECL_COMDAT_GROUP (statfn) = DECL_COMDAT_GROUP (callop);
- callop_node = cgraph_node (callop);
- thunk_node = cgraph_node (statfn);
- gcc_assert (callop_node->same_comdat_group == NULL);
- gcc_assert (thunk_node->same_comdat_group == NULL);
- callop_node->same_comdat_group = thunk_node;
- thunk_node->same_comdat_group = callop_node;
- }
body = begin_function_body ();
compound_stmt = begin_compound_stmt (0);