PR c++/88358 - name wrongly treated as type.
authorMarek Polacek <polacek@redhat.com>
Mon, 28 Jan 2019 22:14:27 +0000 (22:14 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Mon, 28 Jan 2019 22:14:27 +0000 (22:14 +0000)
* parser.c (cp_parser_direct_declarator): Don't assume a qualified-id
in parameter-list is a type if the function's declarator-id is not
qualified.

* g++.dg/cpp2a/typename1.C: Add dg-error.
* g++.dg/cpp2a/typename13.C: New test.
* g++.dg/cpp2a/typename6.C: Make a function name qualified.
Add typename.

From-SVN: r268343

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/typename1.C
gcc/testsuite/g++.dg/cpp2a/typename13.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/typename6.C

index dcac8e7..5e2f69d 100644 (file)
@@ -1,3 +1,10 @@
+2019-01-28  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/88358 - name wrongly treated as type.
+       * parser.c (cp_parser_direct_declarator): Don't assume a qualified-id
+       in parameter-list is a type if the function's declarator-id is not
+       qualified.
+
 2019-01-27  Marek Polacek  <polacek@redhat.com>
 
        PR c++/88815 - narrowing conversion lost in decltype.
index dc9d651..16f2a32 100644 (file)
@@ -21107,23 +21107,28 @@ cp_parser_direct_declarator (cp_parser* parser,
            if (cxx_dialect >= cxx2a
                && (flags & CP_PARSER_FLAGS_TYPENAME_OPTIONAL)
                && declarator->kind == cdk_id
-               /* ...whose declarator-id is qualified.  */
-               && qualifying_scope != NULL_TREE
                && !at_class_scope_p ()
                && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
              {
-               /* Now we have something like
-                  template <typename T> int C::x(S::p);
-                  which can be a function template declaration or a
-                  variable template definition.  If name lookup for
-                  the declarator-id C::x finds one or more function
-                  templates, assume S::p to name a type.  Otherwise,
-                  don't.  */
-               tree decl
-                 = cp_parser_lookup_name_simple (parser, unqualified_name,
-                                                 token->location);
-               if (!is_overloaded_fn (decl))
+               /* ...whose declarator-id is qualified.  If it isn't, never
+                  assume the parameters to refer to types.  */
+               if (qualifying_scope == NULL_TREE)
                  flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+               else
+                 {
+                   /* Now we have something like
+                      template <typename T> int C::x(S::p);
+                      which can be a function template declaration or a
+                      variable template definition.  If name lookup for
+                      the declarator-id C::x finds one or more function
+                      templates, assume S::p to name a type.  Otherwise,
+                      don't.  */
+                   tree decl
+                     = cp_parser_lookup_name_simple (parser, unqualified_name,
+                                                     token->location);
+                   if (!is_overloaded_fn (decl))
+                     flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
+                 }
              }
          }
 
index a36e19c..7af76a1 100644 (file)
@@ -1,5 +1,13 @@
 2019-01-28  Marek Polacek  <polacek@redhat.com>
 
+       PR c++/88358 - name wrongly treated as type.
+       * g++.dg/cpp2a/typename1.C: Add dg-error.
+       * g++.dg/cpp2a/typename13.C: New test.
+       * g++.dg/cpp2a/typename6.C: Make a function name qualified.
+       Add typename.
+
+2019-01-28  Marek Polacek  <polacek@redhat.com>
+
        * g++.dg/cpp0x/enum37.C: Add dg-error.
 
 2019-01-28  Bernd Edlinger  <bernd.edlinger@hotmail.de>
index 833d3b8..0c1f630 100644 (file)
@@ -6,7 +6,7 @@ template<class T> T::R f();
 
 // Ill-formed (no diagnostic required), attempt to declare
 // a void variable template
-template<class T> void f(T::R);
+template<class T> void f(T::R); // { dg-error "declared void" }
 
 template <class T> struct A;
 template <class T> using B = A<T>::U;
diff --git a/gcc/testsuite/g++.dg/cpp2a/typename13.C b/gcc/testsuite/g++.dg/cpp2a/typename13.C
new file mode 100644 (file)
index 0000000..c439f72
--- /dev/null
@@ -0,0 +1,13 @@
+// P0634R3, PR c++/88358
+// { dg-do compile { target c++2a } }
+
+template <typename T>
+int pi(T::your_pi);
+
+struct Foo { static constexpr int your_pi = 10; };
+
+int
+main ()
+{
+  return pi<Foo>;
+}
index 49e2235..e96e2ab 100644 (file)
@@ -55,11 +55,14 @@ struct S2 {
 // (5.2.4) parameter-declaration in a declarator of a function or function
 // template declaration whose declarator-id is qualified,
 // unless that parameter-declaration appears in a default argument
-template<typename T>
-int fn3 (T::X);
+
+struct M {
+  template<typename T>
+  int fn (T::X);
+};
 
 template<typename T>
-int fn4 (T::X p) { return p; }
+int M::fn (T::X p) { return p; }
 
 // (5.2.5) parameter-declaration in a lambda-declarator,
 // unless that parameter-declaration appears in a default argument
@@ -92,7 +95,7 @@ struct S5 {
 };
 
 template<typename T>
-void fn7 (T::X p)
+void fn7 (typename T::X p)
 {
   int i = static_cast<T::Y>(p);
   i = dynamic_cast<T::Y>(p);