On Thu, 21 Jan 2021, Patrick Palka wrote: > Here at parse time finish_qualified_id_expr adds an implicit 'this->' to > the expression tmp::integral<T> (because it's type-dependent, and also > current_class_ptr is set) within the trailing return type, and later > during substitution we can't resolve the 'this' since > tsubst_function_type does inject_this_parm only for non-static member > functions which tmp::func is not. > > It seems the root of the problem is that we set current_class_ptr when > parsing the signature of a static member function. Since explicit uses > of 'this' are already not allowed in this context, we probably shouldn't > be doing inject_this_parm either. > > Bootstrapped and regtested on x64_64-pc-linux-gnu, does this look OK for > trunk? > > gcc/cp/ChangeLog: > > PR c++/97399 > * parser.c (cp_parser_init_declarator): If the storage class > specifier is sc_static, pass true for static_p to > cp_parser_declarator. > (cp_parser_direct_declarator): Don't do inject_this_parm when > the member function is static. > > gcc/testsuite/ChangeLog: > > PR c++/88548 > PR c++/97399 > * g++.dg/cpp0x/this2.C: New test. > * g++.dg/template/pr97399a.C: New test. > * g++.dg/template/pr97399b.C: New test. > --- > gcc/cp/parser.c | 5 +++-- > gcc/testsuite/g++.dg/cpp0x/this2.C | 8 ++++++++ > gcc/testsuite/g++.dg/template/pr97399a.C | 11 +++++++++++ > gcc/testsuite/g++.dg/template/pr97399b.C | 11 +++++++++++ > 4 files changed, 33 insertions(+), 2 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/this2.C > create mode 100644 gcc/testsuite/g++.dg/template/pr97399a.C > create mode 100644 gcc/testsuite/g++.dg/template/pr97399b.C > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index 48437f23175..18cf9888632 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -21413,6 +21413,7 @@ cp_parser_init_declarator (cp_parser* parser, > bool is_non_constant_init; > int ctor_dtor_or_conv_p; > bool friend_p = cp_parser_friend_p (decl_specifiers); > + bool static_p = decl_specifiers->storage_class == sc_static; > tree pushed_scope = NULL_TREE; > bool range_for_decl_p = false; > bool saved_default_arg_ok_p = parser->default_arg_ok_p; > @@ -21446,7 +21447,7 @@ cp_parser_init_declarator (cp_parser* parser, > = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED, > flags, &ctor_dtor_or_conv_p, > /*parenthesized_p=*/NULL, > - member_p, friend_p, /*static_p=*/false); > + member_p, friend_p, static_p); > /* Gather up the deferred checks. */ > stop_deferring_access_checks ();
I should note that the above parser change is needed so that we properly communicate static-ness to cp_parser_direct_declarator when parsing a member function template. > > @@ -22122,7 +22123,7 @@ cp_parser_direct_declarator (cp_parser* parser, > > tree save_ccp = current_class_ptr; > tree save_ccr = current_class_ref; > - if (memfn) > + if (memfn && !static_p) > /* DR 1207: 'this' is in scope after the cv-quals. */ > inject_this_parameter (current_class_type, cv_quals); > > diff --git a/gcc/testsuite/g++.dg/cpp0x/this2.C > b/gcc/testsuite/g++.dg/cpp0x/this2.C > new file mode 100644 > index 00000000000..3781bc5efec > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/this2.C > @@ -0,0 +1,8 @@ > +// PR c++/88548 > +// { dg-do compile { target c++11 } } > + > +struct S { > + int a; > + template <class> static auto m1 () > + -> decltype(this->a) { return 0; }; // { dg-error "'this'" } > +}; > diff --git a/gcc/testsuite/g++.dg/template/pr97399a.C > b/gcc/testsuite/g++.dg/template/pr97399a.C > new file mode 100644 > index 00000000000..3713dbde6e0 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/template/pr97399a.C > @@ -0,0 +1,11 @@ > +// PR c++/97399 > +// { dg-do compile { target c++11 } } > + > +template <bool> struct enable_if_t {}; > +struct tmp { > + template <class T> static constexpr bool is_integral(); > + template <class T> static auto func() > + -> enable_if_t<tmp::is_integral<T>()>; > +}; > +template <class> constexpr bool tmp::is_integral() { return true; } > +int main() { tmp::func<int>(); } > diff --git a/gcc/testsuite/g++.dg/template/pr97399b.C > b/gcc/testsuite/g++.dg/template/pr97399b.C > new file mode 100644 > index 00000000000..9196c985834 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/template/pr97399b.C > @@ -0,0 +1,11 @@ > +// PR c++/97399 > +// { dg-do compile { target c++11 } } > + > +template <bool> struct enable_if_t {}; > +struct tmp { > + template <class T> constexpr bool is_integral(); // non-static > + template <class T> static auto func() > + -> enable_if_t<tmp::is_integral<T>()>; // { dg-error "without object" } > +}; > +template <class> constexpr bool tmp::is_integral() { return true; } > +int main() { tmp::func<int>(); } // { dg-error "no match" } > -- > 2.30.0.155.g66e871b664 > >