summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2013-03-08 16:03:48 +0000
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>2013-03-08 16:03:48 +0000
commitd9cca713633fec2ef330900fe4a08aefab44ad6d (patch)
tree625454b1e858550bbc542f3e02625cff0632d3a5
parent53c6377cf66330535722ef7c760f8193480994b9 (diff)
downloadgcc-d9cca713633fec2ef330900fe4a08aefab44ad6d.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@196549 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/call.c25
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/semantics.c38
-rw-r--r--gcc/cp/tree.c7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this11.C22
6 files changed, 86 insertions, 17 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 14647610e4f..f9731a5538e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,15 @@
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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4eb38ec73e9..530835b87c8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7627,6 +7627,7 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
else
{
fn = cand->fn;
+ call = NULL_TREE;
if (!(flags & LOOKUP_NONVIRTUAL)
&& DECL_PURE_VIRTUAL_P (fn)
@@ -7644,12 +7645,26 @@ build_new_method_call_1 (tree instance, tree fns, vec<tree, va_gc> **args,
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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 4a597d8b3a6..c3b2aecf3b1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5722,6 +5722,7 @@ extern bool is_capture_proxy (tree);
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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d605de9631f..d11a4e4b218 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1544,6 +1544,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
object = maybe_dummy_object (scope, NULL);
}
+ object = maybe_resolve_dummy (object);
if (object == error_mark_node)
return error_mark_node;
@@ -1778,15 +1779,14 @@ finish_qualified_id_expr (tree qualifying_class,
}
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,
@@ -9534,6 +9534,34 @@ lambda_expr_this_capture (tree lambda)
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. */
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index b57b44ad149..178b80aa24f 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -2863,13 +2863,6 @@ maybe_dummy_object (tree type, tree* binfop)
&& (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);
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this11.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this11.C
new file mode 100644
index 00000000000..2618295662e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this11.C
@@ -0,0 +1,22 @@
+// 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;
+ };
+ }
+};