TREE_USED (destination) = 1;
else
{
- /* The DESTINATION is being used as an rvalue. */
if (!processing_template_decl)
{
- destination = decay_conversion (destination);
destination = cp_convert (ptr_type_node, destination);
if (error_operand_p (destination))
return NULL_TREE;
{
gcc_assert (TREE_CODE (decl) == FIELD_DECL);
- if (!object && cp_unevaluated_operand != 0)
+ if (!object)
{
- /* 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);
}
- if (!object)
+ /* 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 (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))),
- /*errorstring=*/"",
- /*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, current_class_ref,
+ expr = finish_non_static_data_member (expr, NULL_TREE,
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 (fns)
- && current_class_ref
- && DERIVED_FROM_P (qualifying_class, TREE_TYPE (current_class_ref)))
+ if (!shared_member_p (expr)
+ && (ob = maybe_dummy_object (qualifying_class, NULL),
+ !is_dummy_object (ob)))
expr = (build_class_member_access_expr
- (maybe_dummy_object (qualifying_class, NULL),
+ (ob,
expr,
BASELINK_ACCESS_BINFO (expr),
/*preserve_reference=*/false,
. operator.... [Otherwise] a contrived object of type T
becomes the implied object argument.
- This paragraph is unclear about this situation:
+ In this situation:
struct A { void f(); };
struct B : public A {};
struct C : public A { void g() { B::f(); }};
- In particular, for `B::f', this paragraph does not make clear
- whether "the class of that member function" refers to `A' or
- to `B'. We believe it refers to `B'. */
- if (current_class_type
- && DERIVED_FROM_P (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
- current_class_type)
- && current_class_ref)
- object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
- NULL);
- else
- {
- tree representative_fn;
+ "the class of that member function" refers to `A'. But 11.2
+ [class.access.base] says that we need to convert 'this' to B* as
+ part of the access, so we pass 'B' to maybe_dummy_object. */
- representative_fn = BASELINK_FUNCTIONS (fn);
- if (TREE_CODE (representative_fn) == TEMPLATE_ID_EXPR)
- representative_fn = TREE_OPERAND (representative_fn, 0);
- representative_fn = get_first_fn (representative_fn);
- object = build_dummy_object (DECL_CONTEXT (representative_fn));
- }
+ object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)),
+ NULL);
if (processing_template_decl)
{
{
tree result;
- /* In a lambda expression, 'this' refers to the captured 'this'. */
- if (current_function_decl
- && LAMBDA_FUNCTION_P (current_function_decl))
- result = (lambda_expr_this_capture
- (CLASSTYPE_LAMBDA_EXPR (current_class_type)));
- else if (current_class_ptr)
- result = current_class_ptr;
+ if (current_class_ptr)
+ {
+ tree type = TREE_TYPE (current_class_ref);
+
+ /* In a lambda expression, 'this' refers to the captured 'this'. */
+ if (LAMBDA_TYPE_P (type))
+ result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type));
+ else
+ result = current_class_ptr;
+
+ }
else if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
{
tree decl = create_temporary_var (type);
DECL_INITIAL (decl) = compound_literal;
TREE_STATIC (decl) = 1;
+ cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
decl = pushdecl_top_level (decl);
DECL_NAME (decl) = make_anon_name ();
SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
error ("definition of %q#T inside template parameter list", t);
return error_mark_node;
}
+
+ /* According to the C++ ABI, decimal classes defined in ISO/IEC TR 24733
+ are passed the same as decimal scalar types. */
+ if (TREE_CODE (t) == RECORD_TYPE
+ && !processing_template_decl)
+ {
+ tree ns = TYPE_CONTEXT (t);
+ if (ns && TREE_CODE (ns) == NAMESPACE_DECL
+ && DECL_CONTEXT (ns) == std_node
+ && DECL_NAME (ns)
+ && !strcmp (IDENTIFIER_POINTER (DECL_NAME (ns)), "decimal"))
+ {
+ const char *n = TYPE_NAME_STRING (t);
+ if ((strcmp (n, "decimal32") == 0)
+ || (strcmp (n, "decimal64") == 0)
+ || (strcmp (n, "decimal128") == 0))
+ TYPE_TRANSPARENT_AGGR (t) = 1;
+ }
+ }
+
/* A non-implicit typename comes from code like:
template <typename T> struct A {
if (!cl)
cl = DECL_CONTEXT (fn);
cl = TYPE_BINFO (cl);
- return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE);
+ return build_baselink (TYPE_BINFO (DECL_CONTEXT (fn)), cl, fns,
+ /*optype=*/NULL_TREE);
}
/* Returns true iff DECL is an automatic variable from a function outside
already. Turn off checking to avoid duplicate errors. */
push_deferring_access_checks (dk_no_check);
decl = finish_non_static_data_member
- (decl, current_class_ref,
+ (decl, NULL_TREE,
/*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, current_class_ref,
+ decl = finish_non_static_data_member (decl, NULL_TREE,
/*qualifying_scope=*/NULL_TREE);
pop_deferring_access_checks ();
}
{
tree first_fn;
- 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);
+ first_fn = get_first_fn (decl);
if (TREE_CODE (first_fn) == TEMPLATE_DECL)
first_fn = DECL_TEMPLATE_RESULT (first_fn);
this function as needed so that finish_file will make sure to
output it later. Similarly, all dllexport'd functions must
be emitted; there may be callers in other DLLs. */
- if ((flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn))
+ if ((flag_keep_inline_functions
+ && DECL_DECLARED_INLINE_P (fn)
+ && !DECL_REALLY_EXTERN (fn))
|| lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))
mark_needed (fn);
}
}
}
\f
-/* Returns decltype((EXPR)) for cases where we can drop the decltype and
- just return the type even though EXPR is a type-dependent expression.
- The ABI specifies which cases this applies to, which is a subset of the
- possible cases. */
+/* Returns the type of EXPR for cases where we can determine it even though
+ EXPR is a type-dependent expression. */
tree
describable_type (tree expr)
case PARM_DECL:
case RESULT_DECL:
case FUNCTION_DECL:
- /* Named rvalue reference becomes lvalue. */
- type = build_reference_type (non_reference (TREE_TYPE (expr)));
+ return TREE_TYPE (expr);
break;
case NEW_EXPR:
return error_mark_node;
}
- if (type_dependent_expression_p (expr))
+ if (type_dependent_expression_p (expr)
+ /* In a template, a COMPONENT_REF has an IDENTIFIER_NODE for op1 even
+ if it isn't dependent, so that we can check access control at
+ instantiation time, so defer the decltype as well (PR 42277). */
+ || (id_expression_or_member_access_p
+ && processing_template_decl
+ && TREE_CODE (expr) == COMPONENT_REF))
{
if (id_expression_or_member_access_p)
{
if (type && !type_uses_auto (type))
return type;
+ treat_as_dependent:
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type)
/* The type denoted by decltype(e) is defined as follows: */
expr = resolve_nondeduced_context (expr);
+
+ /* To get the size of a static data member declared as an array of
+ unknown bound, we need to instantiate it. */
+ if (TREE_CODE (expr) == VAR_DECL
+ && VAR_HAD_UNKNOWN_BOUND (expr)
+ && DECL_TEMPLATE_INSTANTIATION (expr))
+ instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false);
+
if (id_expression_or_member_access_p)
{
/* If e is an id-expression or a class member access (5.2.5
&& (TREE_CODE (TREE_TYPE (target_type)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (target_type)) == METHOD_TYPE))
type = TREE_TYPE (TREE_TYPE (target_type));
+ else if (processing_template_decl)
+ /* Within a template finish_call_expr doesn't resolve
+ CALL_EXPR_FN, so even though this decltype isn't really
+ dependent let's defer resolving it. */
+ goto treat_as_dependent;
else
sorry ("unable to determine the declared type of expression %<%E%>",
expr);
tree field = TREE_PURPOSE (node);
tree val = TREE_VALUE (node);
+ if (DECL_P (val))
+ mark_used (val);
+
/* Mere mortals can't copy arrays with aggregate initialization, so
do some magic to make it work here. */
if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)
lambda_return_type (tree expr)
{
tree type;
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ warning (0, "cannot deduce lambda return type from a braced-init-list");
+ return void_type_node;
+ }
if (type_dependent_expression_p (expr))
{
type = cxx_make_type (DECLTYPE_TYPE);
/* TREE_TYPE (FUNCTION_DECL) == METHOD_TYPE
TREE_TYPE (METHOD_TYPE) == return-type */
- TREE_TYPE (TREE_TYPE (fco)) = return_type;
+ TREE_TYPE (fco) = change_return_type (return_type, TREE_TYPE (fco));
result = DECL_RESULT (fco);
if (result == NULL_TREE)
always visible. */
DECL_NORMAL_CAPTURE_P (member) = true;
- /* Add it to the appropriate closure class. */
- finish_member_declaration (member);
+ /* Add it to the appropriate closure class if we've started it. */
+ if (current_class_type && current_class_type == TREE_TYPE (lambda))
+ finish_member_declaration (member);
LAMBDA_EXPR_CAPTURE_LIST (lambda)
= tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda));
return member;
}
+/* Register all the capture members on the list CAPTURES, which is the
+ LAMBDA_EXPR_CAPTURE_LIST for the lambda after the introducer. */
+
+void register_capture_members (tree captures)
+{
+ if (captures)
+ {
+ register_capture_members (TREE_CHAIN (captures));
+ finish_member_declaration (TREE_PURPOSE (captures));
+ }
+}
+
/* Given a FIELD_DECL decl belonging to a closure type, return a
COMPONENT_REF of it relative to the 'this' parameter of the op() for
that type. */
{
tree context = lambda_function (DECL_CONTEXT (decl));
tree object = cp_build_indirect_ref (DECL_ARGUMENTS (context),
- /*errorstring*/"",
+ RO_NULL,
tf_warning_or_error);
return finish_non_static_data_member (decl, object,
/*qualifying_scope*/NULL_TREE);
gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda));
result = finish_non_static_data_member (this_capture,
- current_class_ref,
+ NULL_TREE,
/*qualifying_scope=*/NULL_TREE);
/* If 'this' is captured, each use of 'this' is transformed into an
return result;
}
+/* Returns the method basetype of the innermost non-lambda function, or
+ NULL_TREE if none. */
+
+tree
+nonlambda_method_basetype (void)
+{
+ tree fn, type;
+ if (!current_class_ref)
+ return NULL_TREE;
+
+ type = current_class_type;
+ if (!LAMBDA_TYPE_P (type))
+ return type;
+
+ /* Find the nearest enclosing non-lambda function. */
+ fn = TYPE_NAME (type);
+ do
+ fn = decl_function_context (fn);
+ while (fn && LAMBDA_FUNCTION_P (fn));
+
+ if (!fn || !DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+ return NULL_TREE;
+
+ return TYPE_METHOD_BASETYPE (TREE_TYPE (fn));
+}
+
/* If the closure TYPE has a static op(), also add a conversion to function
pointer. */
bool nested = (current_function_decl != NULL_TREE);
tree callop = lambda_function (type);
tree rettype, name, fntype, fn, body, compound_stmt;
+ tree thistype, stattype, statfn, convfn, call, arg;
+ VEC (tree, gc) *argvec;
- if (!DECL_STATIC_FUNCTION_P (callop))
+ if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
return;
- rettype = build_pointer_type (TREE_TYPE (callop));
+ stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
+ FUNCTION_ARG_CHAIN (callop));
+
+ /* First build up the conversion op. */
+
+ rettype = build_pointer_type (stattype);
name = mangle_conv_op_name_for_type (rettype);
- fntype = build_function_type (rettype, void_list_node);
- fn = build_lang_decl (FUNCTION_DECL, name, fntype);
+ thistype = cp_build_qualified_type (type, TYPE_QUAL_CONST);
+ fntype = build_method_type_directly (thistype, rettype, void_list_node);
+ fn = convfn = build_lang_decl (FUNCTION_DECL, name, fntype);
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
DECL_ARTIFICIAL (fn) = 1;
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1;
+ DECL_ARGUMENTS (fn) = build_this_parm (fntype, TYPE_QUAL_CONST);
+ if (nested)
+ DECL_INTERFACE_KNOWN (fn) = 1;
+
+ add_method (type, fn, NULL_TREE);
+
+ /* Generic thunk code fails for varargs; we'll complain in mark_used if
+ the conversion op is used. */
+ if (varargs_function_p (callop))
+ {
+ DECL_DELETED_FN (fn) = 1;
+ return;
+ }
+
+ /* Now build up the thunk to be returned. */
+
+ name = get_identifier ("_FUN");
+ fn = statfn = build_lang_decl (FUNCTION_DECL, name, stattype);
+ DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (callop);
+ if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
+ && DECL_ALIGN (fn) < 2 * BITS_PER_UNIT)
+ DECL_ALIGN (fn) = 2 * BITS_PER_UNIT;
+ grokclassfn (type, fn, NO_SPECIAL);
+ set_linkage_according_to_type (type, fn);
+ rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
+ DECL_IN_AGGR_P (fn) = 1;
+ DECL_ARTIFICIAL (fn) = 1;
+ DECL_NOT_REALLY_EXTERN (fn) = 1;
+ DECL_DECLARED_INLINE_P (fn) = 1;
DECL_STATIC_FUNCTION_P (fn) = 1;
+ DECL_ARGUMENTS (fn) = copy_list (TREE_CHAIN (DECL_ARGUMENTS (callop)));
+ for (arg = DECL_ARGUMENTS (fn); arg; arg = TREE_CHAIN (arg))
+ DECL_CONTEXT (arg) = fn;
+ if (nested)
+ DECL_INTERFACE_KNOWN (fn) = 1;
add_method (type, fn, NULL_TREE);
if (nested)
push_function_context ();
- start_preparsed_function (fn, NULL_TREE,
+
+ /* Generate the body of the thunk. */
+
+ start_preparsed_function (statfn, 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);
+
+ arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)),
+ null_pointer_node);
+ argvec = make_tree_vector ();
+ VEC_quick_push (tree, argvec, arg);
+ for (arg = DECL_ARGUMENTS (statfn); arg; arg = TREE_CHAIN (arg))
+ VEC_safe_push (tree, gc, argvec, arg);
+ call = build_call_a (callop, VEC_length (tree, argvec),
+ VEC_address (tree, argvec));
+ CALL_FROM_THUNK_P (call) = 1;
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call)))
+ call = build_cplus_new (TREE_TYPE (call), call);
+ call = convert_from_reference (call);
+ finish_return_stmt (call);
+
+ finish_compound_stmt (compound_stmt);
+ finish_function_body (body);
+
+ expand_or_defer_fn (finish_function (2));
+
+ /* Generate the body of the conversion op. */
+
+ start_preparsed_function (convfn, NULL_TREE,
SF_PRE_PARSED | SF_INCLASS_INLINE);
body = begin_function_body ();
compound_stmt = begin_compound_stmt (0);
- finish_return_stmt (decay_conversion (callop));
+ finish_return_stmt (decay_conversion (statfn));
finish_compound_stmt (compound_stmt);
finish_function_body (body);
expand_or_defer_fn (finish_function (2));
+
if (nested)
pop_function_context ();
}