aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2021-05-03 13:35:37 -0400
committerPatrick Palka <ppalka@redhat.com>2021-05-03 13:35:37 -0400
commit2a6fc19e655e696bf0df9b7aaedf9848b23f07f3 (patch)
tree8ca05e6d392eb94ded6018a66afc8a50f0b83a69
parenteef4fa6968ae0682679c27dae06409db3d113d5d (diff)
downloadgcc-2a6fc19e655e696bf0df9b7aaedf9848b23f07f3.zip
gcc-2a6fc19e655e696bf0df9b7aaedf9848b23f07f3.tar.gz
gcc-2a6fc19e655e696bf0df9b7aaedf9848b23f07f3.tar.bz2
c++: base-clause parsing and implicit 'this' [PR100362]
My r11-6815 change to defer access checking when processing a base-clause removed a pair of pushclass / popclass calls that seemed to be unnecessary now that we'd also defer access checking while parsing the base-clause. But it turns out these calls make a difference in the below testcase, where we have a local class whose base-clause implicitly uses the 'this' of the enclosing class. Before r11-6815, while parsing the base-clause of the local class, maybe_resolve_dummy would fail to resolve the dummy 'this' object because the current scope would be the local class. Now, since the current scope is the lambda, maybe_resolve_dummy succeeds and returns the 'this' for the enclosing class Qux. Later, during deferred instantiation of the local class, we get confused trying to resolve the access of 'a_' through this non-dummy 'this'. So this patch just reinstates the calls to pushclass / popclass that were removed in r11-6815. gcc/cp/ChangeLog: PR c++/100362 * parser.c (cp_parser_class_head): Reinstate calls to pushclass and popclass when parsing the base-clause that were removed in r11-6815. gcc/testsuite/ChangeLog: PR c++/100362 * g++.dg/cpp1y/lambda-generic-100362.C: New test.
-rw-r--r--gcc/cp/parser.c8
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-100362.C25
2 files changed, 32 insertions, 1 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9603a1e..58bd6d1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -25690,7 +25690,13 @@ cp_parser_class_head (cp_parser* parser,
until the entire list has been seen, as per [class.access.general]. */
push_deferring_access_checks (dk_deferred);
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
- bases = cp_parser_base_clause (parser);
+ {
+ if (type)
+ pushclass (type);
+ bases = cp_parser_base_clause (parser);
+ if (type)
+ popclass ();
+ }
else
bases = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-100362.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-100362.C
new file mode 100644
index 0000000..283c2c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-100362.C
@@ -0,0 +1,25 @@
+// PR c++/100362
+// { dg-do compile { target c++14 } }
+
+template <class>
+struct Qux {
+ struct A { } a_;
+ A f();
+
+ void AsyncOp() {
+ [](auto) {
+ struct local : decltype(a_) {};
+ local ptr;
+ }(0);
+
+ [](auto) {
+ struct local : decltype(f()) {};
+ local ptr;
+ }(0);
+ }
+};
+
+void corge() {
+ Qux<int> qux;
+ qux.AsyncOp();
+}