* C++ PATCH for various lambda bugs (51494, 51884, 56222, 51884)
@ 2013-03-08 16:04 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2013-03-08 16:04 UTC (permalink / raw)
To: gcc-patches List
[-- Attachment #1: Type: text/plain, Size: 420 bytes --]
The first two patches deal with issues with 'this' capture; we were
inappropriately capturing 'this' for uses of static members and forming
pointers to members, and for uses in unevaluated context. The last
patch avoids a crash from recursive use of dfs_walk when instantiating a
class with virtual functions using a local class whose scope involves a
qualified-id.
Tested x86_64-pc-linux-gnu, applying to trunk.
[-- Attachment #2: 56222.patch --]
[-- Type: text/x-patch, Size: 8754 bytes --]
commit 58322f8d0b0892ac66d184cc933655e135d324af
Author: Jason Merrill <jason@redhat.com>
Date: Tue Mar 5 12:09:52 2013 -0500
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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4eb38ec..530835b 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 4a597d8..c3b2aec 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 d605de9..d11a4e4 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 b57b44a..178b80a 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 0000000..2618295
--- /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;
+ };
+ }
+};
commit 977321fdf969a16e3546e044bc2c1404b0565804
Author: Jason Merrill <jason@redhat.com>
Date: Tue Mar 5 12:03:06 2013 -0500
* semantics.c (lambda_expr_this_capture): In unevaluated context,
just return the nearest 'this'.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index d11a4e4..233765a 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -9513,6 +9513,11 @@ lambda_expr_this_capture (tree lambda)
if (!this_capture)
{
+ /* In unevaluated context this isn't an odr-use, so just return the
+ nearest 'this'. */
+ if (cp_unevaluated_operand)
+ return lookup_name (this_identifier);
+
error ("%<this%> was not captured for this lambda function");
result = error_mark_node;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this12.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this12.C
new file mode 100644
index 0000000..ef573b1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this12.C
@@ -0,0 +1,13 @@
+// Uses of 'this' in unevaluated context are not odr-uses.
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ int f() {}
+ int i;
+
+ void foo()
+ {
+ [] () { sizeof(i); sizeof(f()); };
+ }
+};
commit a5f8c7b4fb99d4f02201cd7eaa0bac518b2a4695
Author: Jason Merrill <jason@redhat.com>
Date: Wed Mar 6 09:27:22 2013 -0500
PR c++/51884
* class.c (modify_all_vtables): Mangle the vtable name before
entering dfs_walk.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 2a0351f..746c29d 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2541,6 +2541,10 @@ modify_all_vtables (tree t, tree virtuals)
tree binfo = TYPE_BINFO (t);
tree *fnsp;
+ /* Mangle the vtable name before entering dfs_walk (c++/51884). */
+ if (TYPE_CONTAINS_VPTR_P (t))
+ get_vtable_decl (t, false);
+
/* Update all of the vtables. */
dfs_walk_once (binfo, dfs_modify_vtables, NULL, t);
diff --git a/gcc/testsuite/g++.dg/cpp0x/local-targ1.C b/gcc/testsuite/g++.dg/cpp0x/local-targ1.C
new file mode 100644
index 0000000..588149a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/local-targ1.C
@@ -0,0 +1,31 @@
+// PR c++/51884
+// { dg-do compile { target c++11 } }
+// { dg-final { scan-assembler "_ZN1BIZN3fooIivE3barILb1EEEvvE1CEC1ERKS4_" } }
+
+template<typename TT>
+ struct test { static const int value = 0; };
+template<int I>
+ struct enable_if { typedef void type; };
+
+struct A { virtual void f() {} };
+template<typename U> struct B : A { B(); B(const B&); };
+template<typename U> B<U>::B() { }
+template<typename U> B<U>::B(const B&) { }
+
+template<class T> void g(T) { }
+
+template<typename T, typename = void> struct foo;
+template<typename T>
+struct foo<T,typename enable_if<test<T>::value>::type>
+{
+ template <bool P> void bar() {
+ struct C { } c;
+ B<C> b;
+ g(b);
+ }
+};
+
+int main() {
+ foo<int> f;
+ f.bar<true>();
+}
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2013-03-08 16:04 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-08 16:04 C++ PATCH for various lambda bugs (51494, 51884, 56222, 51884) Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).