PR c++/88979 - further P0634 fix for constructors.
authorMarek Polacek <polacek@redhat.com>
Wed, 13 Mar 2019 18:38:45 +0000 (18:38 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Wed, 13 Mar 2019 18:38:45 +0000 (18:38 +0000)
* parser.c (cp_parser_decl_specifier_seq): Pass flags to
cp_parser_constructor_declarator_p.
(cp_parser_direct_declarator): Allow missing typename for constructor
parameters.
(cp_parser_constructor_declarator_p): Add FLAGS parameter.  Pass it to
cp_parser_type_specifier.

* g++.dg/cpp2a/typename15.C: New test.

From-SVN: r269656

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

index 334023998861545fb96a65c069412c5c1477b14e..2e06623efaf340a8bb9d531e5b048559dd3b3096 100644 (file)
@@ -1,3 +1,13 @@
+2019-03-13  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/88979 - further P0634 fix for constructors.
+       * parser.c (cp_parser_decl_specifier_seq): Pass flags to
+       cp_parser_constructor_declarator_p.
+       (cp_parser_direct_declarator): Allow missing typename for constructor
+       parameters.
+       (cp_parser_constructor_declarator_p): Add FLAGS parameter.  Pass it to
+       cp_parser_type_specifier.
+
 2019-03-11  Jason Merrill  <jason@redhat.com>
 
        PR c++/86521 - wrong overload resolution with ref-qualifiers.
index f95111169ed3ebfe1c6ac42c2f33882faed2ff49..8244366e669a4cab856b98d72b64fb5762ddaa9a 100644 (file)
@@ -2506,7 +2506,7 @@ static cp_expr cp_parser_simple_cast_expression
 static tree cp_parser_global_scope_opt
   (cp_parser *, bool);
 static bool cp_parser_constructor_declarator_p
-  (cp_parser *, bool);
+  (cp_parser *, cp_parser_flags, bool);
 static tree cp_parser_function_definition_from_specifiers_and_declarator
   (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *);
 static tree cp_parser_function_definition_after_declarator
@@ -14052,7 +14052,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
        = (!found_decl_spec
           && constructor_possible_p
           && (cp_parser_constructor_declarator_p
-              (parser, decl_spec_seq_has_spec_p (decl_specs, ds_friend))));
+              (parser, flags, decl_spec_seq_has_spec_p (decl_specs,
+                                                        ds_friend))));
 
       /* If we don't have a DECL_SPEC yet, then we must be looking at
         a type-specifier.  */
@@ -21160,7 +21161,13 @@ cp_parser_direct_declarator (cp_parser* parser,
                    tree decl
                      = cp_parser_lookup_name_simple (parser, unqualified_name,
                                                      token->location);
-                   if (!is_overloaded_fn (decl))
+                   if (!is_overloaded_fn (decl)
+                       /* Allow
+                          template<typename T>
+                          A<T>::A(T::type) { }  */
+                       && !(MAYBE_CLASS_TYPE_P (qualifying_scope)
+                            && constructor_name_p (unqualified_name,
+                                                   qualifying_scope)))
                      flags &= ~CP_PARSER_FLAGS_TYPENAME_OPTIONAL;
                  }
              }
@@ -27380,10 +27387,12 @@ cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p)
 
 /* Returns TRUE if the upcoming token sequence is the start of a
    constructor declarator or C++17 deduction guide.  If FRIEND_P is true, the
-   declarator is preceded by the `friend' specifier.  */
+   declarator is preceded by the `friend' specifier.  The parser flags FLAGS
+   is used to control type-specifier parsing.  */
 
 static bool
-cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
+cp_parser_constructor_declarator_p (cp_parser *parser, cp_parser_flags flags,
+                                   bool friend_p)
 {
   bool constructor_p;
   bool outside_class_specifier_p;
@@ -27562,9 +27571,10 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
            = parser->num_template_parameter_lists;
          parser->num_template_parameter_lists = 0;
 
-         /* Look for the type-specifier.  */
+         /* Look for the type-specifier.  It's not optional, but its typename
+            might be.  */
          cp_parser_type_specifier (parser,
-                                   CP_PARSER_FLAGS_NONE,
+                                   (flags & ~CP_PARSER_FLAGS_OPTIONAL),
                                    /*decl_specs=*/NULL,
                                    /*is_declarator=*/true,
                                    /*declares_class_or_enum=*/NULL,
index f4dc0a009d9ba8fd198b9a28773db5fba3b3333e..0abb39bdb47b246bcb6bf149f60035fb386dc727 100644 (file)
@@ -1,3 +1,8 @@
+2019-03-13  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/88979 - further P0634 fix for constructors.
+       * g++.dg/cpp2a/typename15.C: New test.
+
 2019-03-13  Martin Sebor  <msebor@redhat.com>
 
        PR tree-optimization/89662
diff --git a/gcc/testsuite/g++.dg/cpp2a/typename15.C b/gcc/testsuite/g++.dg/cpp2a/typename15.C
new file mode 100644 (file)
index 0000000..9094190
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/88979
+// { dg-do compile { target c++2a } }
+
+template<typename T>
+struct B {
+  B(T::type);
+};
+
+template<typename T>
+struct A {
+  A(T::type);
+};
+
+template<typename T>
+A<T>::A(T::type) { }