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 ();
 
@@ -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

Reply via email to