PR c++/90572 - wrong disambiguation in friend declaration.
authorMarek Polacek <polacek@redhat.com>
Sat, 25 May 2019 14:39:12 +0000 (14:39 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Sat, 25 May 2019 14:39:12 +0000 (14:39 +0000)
* parser.c (cp_parser_constructor_declarator_p): Don't allow missing
typename for friend declarations.

* g++.dg/cpp2a/typename16.C: New test.
* g++.dg/parse/friend13.C: New test.

From-SVN: r271619

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/typename16.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/friend13.C [new file with mode: 0644]

index 8dacb224a8c3bf732920c14feaad0d4637da4484..0c37f55fe25881559c5f1f0b0d2d321aad200258 100644 (file)
@@ -1,3 +1,9 @@
+2019-05-25  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/90572 - wrong disambiguation in friend declaration.
+       * parser.c (cp_parser_constructor_declarator_p): Don't allow missing
+       typename for friend declarations.
+
 2019-05-23  Jonathan Wakely  <jwakely@redhat.com>
 
        * cp-tree.h (CP_AGGREGATE_TYPE_P): Fix whitespace.
index 1440fdb0d184a2c63e283faedb9ea327adb7c23d..08b4105c97f8c8af35f4a005be103e52a175623c 100644 (file)
@@ -27593,9 +27593,19 @@ cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
          parser->num_template_parameter_lists = 0;
 
          /* Look for the type-specifier.  It's not optional, but its typename
-            might be.  */
+            might be.  Unless this is a friend declaration; we don't want to
+            treat
+
+              friend S (T::fn)(int);
+
+            as a constructor, but with P0634, we might assume a type when
+            looking for the type-specifier.  It is actually a function named
+            `T::fn' that takes one parameter (of type `int') and returns a
+            value of type `S'.  Constructors can be friends, but they must
+            use a qualified name.  */
          cp_parser_type_specifier (parser,
-                                   (flags & ~CP_PARSER_FLAGS_OPTIONAL),
+                                   (friend_p ? CP_PARSER_FLAGS_NONE
+                                    : (flags & ~CP_PARSER_FLAGS_OPTIONAL)),
                                    /*decl_specs=*/NULL,
                                    /*is_declarator=*/true,
                                    /*declares_class_or_enum=*/NULL,
index a0cff00b6210f49d2e57fefda0f2a1ebf9fd4ead..998a8ffd04e1478c322778e14937a5a9c4d785e7 100644 (file)
@@ -1,3 +1,9 @@
+2019-05-25  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/90572 - wrong disambiguation in friend declaration.
+       * g++.dg/cpp2a/typename16.C: New test.
+       * g++.dg/parse/friend13.C: New test.
+
 2019-05-24  Jakub Jelinek  <jakub@redhat.com>
 
        * c-c++-common/gomp/lastprivate-conditional-2.c (foo): Don't expect
diff --git a/gcc/testsuite/g++.dg/cpp2a/typename16.C b/gcc/testsuite/g++.dg/cpp2a/typename16.C
new file mode 100644 (file)
index 0000000..7f4242a
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/90572
+// { dg-do compile { target c++2a } }
+
+struct X { X(int); };
+
+template<typename T> struct S {
+  friend X::X(T::t);
+};
+
+struct W { using t = int; };
+S<W> s;
diff --git a/gcc/testsuite/g++.dg/parse/friend13.C b/gcc/testsuite/g++.dg/parse/friend13.C
new file mode 100644 (file)
index 0000000..d716247
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/90572
+
+template <typename T> struct C {
+  friend C(T::fn)();
+  friend C(T::fn)(int);
+  friend C(T::fn)(int, int);
+};
+
+struct X { };
+
+template<typename T>
+struct B {
+  friend X(T::fn)();
+  friend X(T::fn)(int);
+  friend X(T::fn)(int, int);
+};