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);
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)))
+ && (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)
{
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
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);
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. */
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_cxx_call (callop, VEC_length (tree, argvec),
- VEC_address (tree, argvec));
+ 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);