aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2016-12-15 19:50:25 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2016-12-15 19:50:25 +0000
commit2a810dedce593e9b015a051a0dfb36dfb7e563bf (patch)
tree766e2803161094e7b8b634270c752d10caec7d52 /gcc
parenta3998c2fb1630638db83defcd2c680111d65b973 (diff)
downloadgcc-2a810dedce593e9b015a051a0dfb36dfb7e563bf.zip
gcc-2a810dedce593e9b015a051a0dfb36dfb7e563bf.tar.gz
gcc-2a810dedce593e9b015a051a0dfb36dfb7e563bf.tar.bz2
re PR c++/77585 (g++ incorrectly decides that member function is called without object in generic lambda)
PR c++/77585 * pt.c (instantiate_decl): Push to class scope lambda resides within when instantiating a generic lambda function. PR c++/77585 * g++.dg/cpp1y/pr77585.C: New. From-SVN: r243723
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c21
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr77585.C41
4 files changed, 72 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index d2e8d45..9c6ee48 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2016-12-15 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/77585
+ * pt.c (instantiate_decl): Push to class scope lambda resides
+ within when instantiating a generic lambda function.
+
2016-12-14 Martin Sebor <msebor@redhat.com>
PR c++/78774
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a21be81..91178ea 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -22484,6 +22484,7 @@ instantiate_decl (tree d, int defer_ok,
tree tmpl_parm;
tree spec_parm;
tree block = NULL_TREE;
+ tree lambda_ctx = NULL_TREE;
/* Save away the current list, in case we are instantiating one
template from within the body of another. */
@@ -22497,7 +22498,23 @@ instantiate_decl (tree d, int defer_ok,
&& TREE_CODE (DECL_CONTEXT (code_pattern)) == FUNCTION_DECL)
block = push_stmt_list ();
else
- start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
+ {
+ if (LAMBDA_FUNCTION_P (d))
+ {
+ /* When instantiating a lambda's templated function
+ operator, we need to push the non-lambda class scope
+ of the lambda itself so that the nested function
+ stack is sufficiently correct to deal with this
+ capture. */
+ lambda_ctx = DECL_CONTEXT (d);
+ do
+ lambda_ctx = decl_type_context (TYPE_NAME (lambda_ctx));
+ while (lambda_ctx && LAMBDA_TYPE_P (lambda_ctx));
+ if (lambda_ctx)
+ push_nested_class (lambda_ctx);
+ }
+ start_preparsed_function (d, NULL_TREE, SF_PRE_PARSED);
+ }
/* Some typedefs referenced from within the template code need to be
access checked at template instantiation time, i.e now. These
@@ -22565,6 +22582,8 @@ instantiate_decl (tree d, int defer_ok,
d = finish_function (0);
expand_or_defer_fn (d);
}
+ if (lambda_ctx)
+ pop_nested_class ();
if (DECL_OMP_DECLARE_REDUCTION_P (code_pattern))
cp_check_omp_declare_reduction (d);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 535dc84..ac49d4d 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2016-12-15 Nathan Sidwell <nathan@acm.org>
+
+ PR c++/77585
+ * g++.dg/cpp1y/pr77585.C: New.
+
2016-12-15 David Edelsohn <dje.gcc@gmail.com>
* gcc.dg/tree-ssa/ssa-fre-55.c: Add -Wno-psabi.
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr77585.C b/gcc/testsuite/g++.dg/cpp1y/pr77585.C
new file mode 100644
index 0000000..aff7a61
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr77585.C
@@ -0,0 +1,41 @@
+// PR c++/77585
+// { dg-do run { target c++14 } }
+
+// Confusion about this capture when instantiating generic lambda's
+// function operator
+
+template <typename F> int Eat (F &&f) { return f (1); }
+
+struct Foo {
+ int x = 1;
+ int Share () { return x++; }
+ int Frob (int);
+};
+
+int Foo::Frob (int r)
+{
+ auto lam = [&](auto) { return Share (); };
+ r += Eat (lam);
+
+ auto lam0 = [&](auto) {
+ auto lam1 = [&](auto) { return Share (); };
+ return Eat (lam1); };
+ r += Eat (lam0);
+
+ return r;
+}
+
+int Frob (int r)
+{
+ auto lam = [&](auto) { return 1; };
+ r += Eat (lam);
+ return r;
+}
+
+
+int main ()
+{
+ Foo f;
+
+ return Frob (f.Frob (0)) == 4 ? 0 : 1;
+}