2013-03-08 Jason Merrill <jason@redhat.com>
+ PR c++/51494
+ PR c++/51884
+ PR c++/56222
+ * tree.c (maybe_dummy_object): Don't capture 'this'.
+ * semantics.c (maybe_resolve_dummy): New.
+ (finish_non_static_data_member): Use it.
+ (finish_qualified_id_expr): Don't test is_dummy_object.
+ * cp-tree.h: Declare maybe_resolve_dummy.
+ * call.c (build_new_method_call_1): Use it.
+
PR c++/56567
* semantics.c (apply_deduced_return_type): Don't allow returning
std::initializer_list.
else
{
fn = cand->fn;
+ call = NULL_TREE;
if (!(flags & LOOKUP_NONVIRTUAL)
&& DECL_PURE_VIRTUAL_P (fn)
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
&& is_dummy_object (instance_ptr))
{
- if (complain & tf_error)
- error ("cannot call member function %qD without object",
- fn);
- call = error_mark_node;
+ instance = maybe_resolve_dummy (instance);
+ if (instance == error_mark_node)
+ call = error_mark_node;
+ else if (!is_dummy_object (instance))
+ {
+ /* We captured 'this' in the current lambda now that
+ we know we really need it. */
+ instance_ptr = build_this (instance);
+ cand->first_arg = instance_ptr;
+ }
+ else
+ {
+ if (complain & tf_error)
+ error ("cannot call member function %qD without object",
+ fn);
+ call = error_mark_node;
+ }
}
- else
+
+ if (call != error_mark_node)
{
/* Optimize away vtable lookup if we know that this
function can't be overridden. We need to check if
extern bool is_normal_capture_proxy (tree);
extern void register_capture_members (tree);
extern tree lambda_expr_this_capture (tree);
+extern tree maybe_resolve_dummy (tree);
extern tree nonlambda_method_basetype (void);
extern void maybe_add_lambda_conv_op (tree);
extern bool is_lambda_ignored_entity (tree);
object = maybe_dummy_object (scope, NULL);
}
+ object = maybe_resolve_dummy (object);
if (object == error_mark_node)
return error_mark_node;
}
else if (BASELINK_P (expr) && !processing_template_decl)
{
- tree ob;
-
/* See if any of the functions are non-static members. */
/* If so, the expression may be relative to 'this'. */
if (!shared_member_p (expr)
- && (ob = maybe_dummy_object (qualifying_class, NULL),
- !is_dummy_object (ob)))
+ && current_class_ptr
+ && DERIVED_FROM_P (qualifying_class,
+ current_nonlambda_class_type ()))
expr = (build_class_member_access_expr
- (ob,
+ (maybe_dummy_object (qualifying_class, NULL),
expr,
BASELINK_ACCESS_BINFO (expr),
/*preserve_reference=*/false,
return result;
}
+/* We don't want to capture 'this' until we know we need it, i.e. after
+ overload resolution has chosen a non-static member function. At that
+ point we call this function to turn a dummy object into a use of the
+ 'this' capture. */
+
+tree
+maybe_resolve_dummy (tree object)
+{
+ if (!is_dummy_object (object))
+ return object;
+
+ tree type = TYPE_MAIN_VARIANT (TREE_TYPE (object));
+ gcc_assert (TREE_CODE (type) != POINTER_TYPE);
+
+ if (type != current_class_type
+ && current_class_type
+ && LAMBDA_TYPE_P (current_class_type))
+ {
+ /* In a lambda, need to go through 'this' capture. */
+ tree lam = CLASSTYPE_LAMBDA_EXPR (current_class_type);
+ tree cap = lambda_expr_this_capture (lam);
+ object = build_x_indirect_ref (EXPR_LOCATION (object), cap,
+ RO_NULL, tf_warning_or_error);
+ }
+
+ return object;
+}
+
/* Returns the method basetype of the innermost non-lambda function, or
NULL_TREE if none. */
&& (same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (current_class_ref), context)))
decl = current_class_ref;
- else if (current != current_class_type
- && context == nonlambda_method_basetype ())
- /* In a lambda, need to go through 'this' capture. */
- decl = (build_x_indirect_ref
- (input_location, (lambda_expr_this_capture
- (CLASSTYPE_LAMBDA_EXPR (current_class_type))),
- RO_NULL, tf_warning_or_error));
else
decl = build_dummy_object (context);
--- /dev/null
+// PR c++/51494, c++/56222
+// Uses of static members and creating pointers to members aren't odr-uses
+// of 'this'.
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ static void f() {}
+ static int i;
+ int j;
+ void f(int);
+
+ void foo()
+ {
+ [] () {
+ ++i;
+ f();
+ &A::j;
+ (void(*)())&A::f;
+ };
+ }
+};