| Submitter | Jason Merrill |
|---|---|
| Date | March 17, 2013, 2:40 a.m. |
| Message ID | <51452D06.2080709@redhat.com> |
| Download | mbox | patch |
| Permalink | /patch/228269/ |
| State | New |
| Headers | show |
Comments
On 13-03-16 10:40 PM, Jason Merrill wrote: > On 03/16/2013 03:28 PM, Jason Merrill wrote: >> I have no idea why the existing code tried to deduce the desired quals >> from current_class_ref rather than just look at the object it has. > > Well, maybe now I do; when I tested all my changes again before checking > in, this one caused a crash because I had left out another change that > it depends on. Previously we gave the 'this' capture in a lambda a > DECLTYPE_TYPE type since the enclosing class is a dependent type, but > that means that *this has no type at all and so we can't look at its > quals. But that isn't necessary; we know enough about the type of > 'this' that it's a pointer to some instantiation of this class template, > so we can give the capture field and proxy that type rather than mess > with DECLTYPE_TYPE. We could limit this change to only POINTER_TYPE, > but we might as well save a bit of memory and only use the DECLTYPE_TYPE > when we really don't know anything about the type being captured; > specifically, when we don't know whether or not it's a reference. > > Tested x86_64-pc-linux-gnu, applying to trunk. Hi Jason, It seems this change introduced the following segfault building compatibility-thread-c++0x.cc for an arm eabi target. ice.ii:48:20: internal compiler error: Segmentation fault (__args) ...); ^ 0xa7b67f crash_signal ../../gcc/toplev.c:332 0x4e98e2 resolve_args ../../gcc/cp/call.c:3739 0x5022d7 build_new_function_call(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, int) ../../gcc/cp/call.c:3849 0x66dc42 finish_call_expr(tree_node*, vec<tree_node*, va_gc, vl_embed>**, bool, bool, int) ../../gcc/cp/semantics.c:2214 Attached is a reduced testcase. Sorry, for reporting it on gcc-patches but bugzilla is currently offline. Regards, Ryan Mansfield namespace std __attribute__ ((__visibility__ ("default"))) { template < typename _Tp > struct remove_reference { typedef _Tp type; }; template < typename _Tp > constexpr _Tp && forward (typename std::remove_reference < _Tp >::type & __t) noexcept { return static_cast < _Tp && >(__t); } template < typename _Res, typename _T1, typename _T2 > struct _Reference_wrapper_base <_Res (_T1::*) (_T2) const volatile >:binary_function < const volatile _T1 *, _T2, _Res > { }; template < typename _Tp > class reference_wrapper:public _Reference_wrapper_base < typename remove_cv < _Tp >::type > { }; template < typename _Tp > inline reference_wrapper < _Tp > ref (_Tp & __t) noexcept { } template < typename _Signature > struct _Bind_simple; template < typename _Func, typename ... _BoundArgs > struct _Bind_simple_helper { typedef _Bind_simple < __func_type (typename decay < _BoundArgs >::type ...) > __type; }; template < typename _Callable, typename ... _Args > typename _Bind_simple_helper < _Callable, _Args ... >::__type __bind_simple (_Callable && __callable, _Args && ... __args) { } template < typename _Signature > class function; struct once_flag { }; template < typename _Callable, typename ... _Args > void call_once (once_flag & __once, _Callable && __f, _Args && ... __args) { auto __callable = std::__bind_simple (std::forward < _Callable > (__f), std::forward < _Args > (__args) ...); __once_functor =[&]() { __callable (); }; } class _State_base { once_flag _M_once; void _M_set_result (function < _Ptr_type () > __res, bool __ignore_failure = false) { bool __set = __ignore_failure; call_once (_M_once, &_State_base::_M_do_set, this, ref (__res), ref (__set)); } private:void _M_do_set (function < _Ptr_type () > &__f, bool & __set) { } } }
Patch
commit 4be028d462b52838a0afd6cf3f25fff33ac925ad
Author: Jason Merrill <jason@redhat.com>
Date: Fri Feb 15 14:14:12 2013 -0500
PR c++/54277
* cp-tree.h (WILDCARD_TYPE_P): Split out from...
(MAYBE_CLASS_TYPE_P): ...here.
* semantics.c (lambda_capture_field_type): Only build a
magic decltype for wildcard types.
(lambda_proxy_type): Likewise.
(finish_non_static_data_member): Get the quals from
the object.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 39fb3df..7ce1acb 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1220,17 +1220,20 @@ enum languages { lang_c, lang_cplusplus, lang_java };
/* The _DECL for this _TYPE. */
#define TYPE_MAIN_DECL(NODE) (TYPE_STUB_DECL (TYPE_MAIN_VARIANT (NODE)))
-/* Nonzero if T is a class (or struct or union) type. Also nonzero
- for template type parameters, typename types, and instantiated
- template template parameters. Keep these checks in ascending code
- order. */
-#define MAYBE_CLASS_TYPE_P(T) \
+/* Nonzero if T is a type that could resolve to any kind of concrete type
+ at instantiation time. */
+#define WILDCARD_TYPE_P(T) \
(TREE_CODE (T) == TEMPLATE_TYPE_PARM \
|| TREE_CODE (T) == TYPENAME_TYPE \
|| TREE_CODE (T) == TYPEOF_TYPE \
|| TREE_CODE (T) == BOUND_TEMPLATE_TEMPLATE_PARM \
- || TREE_CODE (T) == DECLTYPE_TYPE \
- || CLASS_TYPE_P (T))
+ || TREE_CODE (T) == DECLTYPE_TYPE)
+
+/* Nonzero if T is a class (or struct or union) type. Also nonzero
+ for template type parameters, typename types, and instantiated
+ template template parameters. Keep these checks in ascending code
+ order. */
+#define MAYBE_CLASS_TYPE_P(T) (WILDCARD_TYPE_P (T) || CLASS_TYPE_P (T))
/* Set CLASS_TYPE_P for T to VAL. T must be a class, struct, or
union type. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 9a2b728..5143e4b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1574,9 +1574,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope)
else
{
/* Set the cv qualifiers. */
- int quals = (current_class_ref
- ? cp_type_quals (TREE_TYPE (current_class_ref))
- : TYPE_UNQUALIFIED);
+ int quals = cp_type_quals (TREE_TYPE (object));
if (DECL_MUTABLE_P (decl))
quals &= ~TYPE_QUAL_CONST;
@@ -9056,7 +9054,7 @@ tree
lambda_capture_field_type (tree expr)
{
tree type;
- if (type_dependent_expression_p (expr))
+ if (!TREE_TYPE (expr) || WILDCARD_TYPE_P (TREE_TYPE (expr)))
{
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;
@@ -9265,7 +9263,7 @@ lambda_proxy_type (tree ref)
if (REFERENCE_REF_P (ref))
ref = TREE_OPERAND (ref, 0);
type = TREE_TYPE (ref);
- if (!dependent_type_p (type))
+ if (type && !WILDCARD_TYPE_P (type))
return type;
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = ref;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this9.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this9.C
new file mode 100644
index 0000000..07ddd08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-this9.C
@@ -0,0 +1,19 @@
+// PR c++/54277
+// { dg-do compile { target c++11 } }
+
+struct Used
+{
+ void foo() { }
+};
+
+template <typename>
+struct S
+{
+ Used x;
+
+ void bar()
+ {
+ auto f = [this] { x.foo(); };
+ f();
+ }
+};