aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2016-05-23 21:21:18 +0000
committerJason Merrill <jason@redhat.com>2016-05-23 21:21:18 +0000
commit868ca3e262482b7cc48d6cfa2bcf5cf7d22d221e (patch)
treec660ce4b1de04232fc91bb3ff74573ae91bf2bd8
parent1d6aaa38e74cda64a542273a8739d76c5845dbc2 (diff)
PR c++/70735 - generic lambda and local static variable
* pt.c (tsubst_copy): Just return a local variable from non-template context. Don't call rest_of_decl_compilation for duplicated static locals. (tsubst_decl): Set DECL_CONTEXT of local static from another function. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@236615 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/pt.c22
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C19
4 files changed, 54 insertions, 9 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6201bdaa036..232acc6772b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2016-05-23 Jason Merrill <jason@redhat.com>
+
+ PR c++/70735
+ * pt.c (tsubst_copy): Just return a local variable from
+ non-template context. Don't call rest_of_decl_compilation for
+ duplicated static locals.
+ (tsubst_decl): Set DECL_CONTEXT of local static from another
+ function.
+
2016-05-23 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/70972
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 2ce8f40f791..3e07fb0b6e0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12281,6 +12281,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
local_p = true;
/* Subsequent calls to pushdecl will fill this in. */
ctx = NULL_TREE;
+ /* Unless this is a reference to a static variable from an
+ enclosing function, in which case we need to fill it in now. */
+ if (TREE_STATIC (t))
+ {
+ tree fn = tsubst (DECL_CONTEXT (t), args, complain, in_decl);
+ if (fn != current_function_decl)
+ ctx = fn;
+ }
spec = retrieve_local_specialization (t);
}
/* If we already have the specialization we need, there is
@@ -13992,7 +14000,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case FUNCTION_DECL:
if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t))
r = tsubst (t, args, complain, in_decl);
- else if (local_variable_p (t))
+ else if (local_variable_p (t)
+ && uses_template_parms (DECL_CONTEXT (t)))
{
r = retrieve_local_specialization (t);
if (r == NULL_TREE)
@@ -14036,14 +14045,9 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (cp_unevaluated_operand || TREE_STATIC (r)
|| decl_constant_var_p (r)
|| errorcount || sorrycount);
- if (!processing_template_decl)
- {
- if (TREE_STATIC (r))
- rest_of_decl_compilation (r, toplevel_bindings_p (),
- at_eof);
- else
- r = process_outer_var_ref (r, complain);
- }
+ if (!processing_template_decl
+ && !TREE_STATIC (r))
+ r = process_outer_var_ref (r, complain);
}
/* Remember this for subsequent uses. */
if (local_specializations)
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C
new file mode 100644
index 00000000000..a1667a2de47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static1.C
@@ -0,0 +1,13 @@
+// PR c++/70735
+// { dg-do run { target c++1y } }
+
+int main()
+{
+ static int a;
+ auto f = [](auto) { return a; };
+ if (f(0) != 0)
+ __builtin_abort();
+ a = 1;
+ if (f(0) != 1)
+ __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C
new file mode 100644
index 00000000000..51bf75f20ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-static2.C
@@ -0,0 +1,19 @@
+// PR c++/70735
+// { dg-do run { target c++1y } }
+
+template <class T>
+static void g()
+{
+ static int a;
+ auto f = [](auto) { return a; };
+ if (f(0) != 0)
+ __builtin_abort();
+ a = 1;
+ if (f(0) != 1)
+ __builtin_abort();
+}
+
+int main()
+{
+ g<int>();
+}