aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-05-02 15:47:40 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-05-02 15:47:40 -0400
commit43b781fac7673ac9f11105048ccc2a75c8a9f0c3 (patch)
tree5f8a43ce0d7d633ca950be8f18dfbaf9acef0cbf
parent62da5a07b2f56f860e70c9bb66791ac665bf14d8 (diff)
downloadgcc-43b781fac7673ac9f11105048ccc2a75c8a9f0c3.zip
gcc-43b781fac7673ac9f11105048ccc2a75c8a9f0c3.tar.gz
gcc-43b781fac7673ac9f11105048ccc2a75c8a9f0c3.tar.bz2
re PR c++/60992 (ICE in tsubst_copy, at cp/pt.c:12637)
PR c++/60992 * lambda.c (lambda_capture_field_type): Wrap anything dependent other than 'this'. (add_capture): Check for VLA before calling it. * semantics.c (is_this_parameter): Accept any 'this' parameter, not just the current one. Make non-static. * cp-tree.h: Declare it. * pt.c (tsubst_copy) [VAR_DECL]: Also build a new VAR_DECL if the operand was static or constant. From-SVN: r210017
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/lambda.c24
-rw-r--r--gcc/cp/pt.c18
-rw-r--r--gcc/cp/semantics.c5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C38
6 files changed, 79 insertions, 19 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7729cb9..422e98c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2014-05-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/60992
+ * lambda.c (lambda_capture_field_type): Wrap anything dependent
+ other than 'this'.
+ (add_capture): Check for VLA before calling it.
+ * semantics.c (is_this_parameter): Accept any 'this' parameter, not
+ just the current one. Make non-static.
+ * cp-tree.h: Declare it.
+ * pt.c (tsubst_copy) [VAR_DECL]: Also build a new VAR_DECL if
+ the operand was static or constant.
+
2014-05-02 Marek Polacek <polacek@redhat.com>
* typeck.c (maybe_warn_about_returning_address_of_local): Separate
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 55ecc4e..34d3d20 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5773,6 +5773,7 @@ extern bool is_sub_constant_expr (tree);
extern bool reduced_constant_expression_p (tree);
extern void explain_invalid_constexpr_fn (tree);
extern vec<tree> cx_error_context (void);
+extern bool is_this_parameter (tree);
enum {
BCS_NO_SCOPE = 1,
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index 0b8b46a..5ba6f14 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -216,8 +216,8 @@ lambda_capture_field_type (tree expr, bool explicit_init_p)
}
else
type = non_reference (unlowered_expr_type (expr));
- if (!type || WILDCARD_TYPE_P (type) || type_uses_auto (type)
- || DECL_PACK_P (expr))
+ if (type_dependent_expression_p (expr)
+ && !is_this_parameter (tree_strip_nop_conversions (expr)))
{
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;
@@ -455,7 +455,7 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
if (TREE_CODE (initializer) == TREE_LIST)
initializer = build_x_compound_expr_from_list (initializer, ELK_INIT,
tf_warning_or_error);
- type = lambda_capture_field_type (initializer, explicit_init_p);
+ type = TREE_TYPE (initializer);
if (array_of_runtime_bound_p (type))
{
vla = true;
@@ -482,15 +482,19 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
"variable size", TREE_TYPE (type));
type = error_mark_node;
}
- else if (by_reference_p)
+ else
{
- type = build_reference_type (type);
- if (!real_lvalue_p (initializer))
- error ("cannot capture %qE by reference", initializer);
+ type = lambda_capture_field_type (initializer, explicit_init_p);
+ if (by_reference_p)
+ {
+ type = build_reference_type (type);
+ if (!real_lvalue_p (initializer))
+ error ("cannot capture %qE by reference", initializer);
+ }
+ else
+ /* Capture by copy requires a complete type. */
+ type = complete_type (type);
}
- else
- /* Capture by copy requires a complete type. */
- type = complete_type (type);
/* Add __ to the beginning of the field name so that user code
won't find the field with name lookup. We can't just leave the name
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 48cc2a9..1584eb9 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12629,13 +12629,17 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
else
{
- /* This can happen for a variable used in a late-specified
- return type of a local lambda. Just make a dummy decl
- since it's only used for its type. */
- if (cp_unevaluated_operand)
- return tsubst_decl (t, args, complain);
- gcc_assert (errorcount || sorrycount);
- return error_mark_node;
+ /* This can happen for a variable used in a
+ late-specified return type of a local lambda, or for a
+ local static or constant. Building a new VAR_DECL
+ should be OK in all those cases. */
+ r = tsubst_decl (t, args, complain);
+ if (decl_constant_var_p (r))
+ /* A use of a local constant must decay to its value. */
+ return integral_constant_value (r);
+ gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
+ || errorcount || sorrycount);
+ return r;
}
}
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3f8ca44..4afb821 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8155,10 +8155,11 @@ maybe_initialize_constexpr_call_table (void)
/* Return true if T designates the implied `this' parameter. */
-static inline bool
+bool
is_this_parameter (tree t)
{
- return t == current_class_ptr;
+ return (TREE_CODE (t) == PARM_DECL
+ && DECL_NAME (t) == this_identifier);
}
/* We have an expression tree T that represents a call, either CALL_EXPR
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C
new file mode 100644
index 0000000..a1ffadd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-const3.C
@@ -0,0 +1,38 @@
+// PR c++/60992
+// { dg-do compile { target c++11 } }
+
+struct ScopeGuardGenerator { };
+
+struct FF
+{
+ template < class F, class ... Ts >
+ void
+ operator () (F & ...)
+ {
+ const int n = sizeof ... (Ts) + 1;
+ void *mutexes[n];
+ auto _on_scope_exit_var_0 =
+ ScopeGuardGenerator () + [&mutexes] { };
+ }
+};
+
+template < class F >
+int operator+ (ScopeGuardGenerator, F) { return 1; }
+
+struct D
+{
+ template < class T0, class T1, class T2, class ... T >
+ void
+ operator () (T0, T1, const T2 & t2, T & ... t)
+ {
+ base (t2, t ...);
+ }
+ FF base;
+};
+
+D run_with_locks;
+
+void Fn ()
+{
+ run_with_locks ([] { }, 0, 0);
+}