diff mbox series

C++ PATCH for c++/88979 - further P0634 fix for constructors

Message ID 20190313172539.GR26967@redhat.com
State New
Headers show
Series C++ PATCH for c++/88979 - further P0634 fix for constructors | expand

Commit Message

Marek Polacek March 13, 2019, 5:25 p.m. UTC
This PR points out that our P0634 implementation misses constructor parameters
and still requires 'typename'.  I'm not 100% sure if the standard really says
we should also handle constructors.  Does a constructor have a function type?

But I guess it makes sense, so this patch handles it.  To handle a constructor
in a class, we need to pass flags to cp_parser_constructor_declarator_p.  To
handle an out-of-line constructor, use constructor_name_p.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

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.

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

Comments

Jason Merrill March 13, 2019, 6:32 p.m. UTC | #1
On 3/13/19 1:25 PM, Marek Polacek wrote:
> This PR points out that our P0634 implementation misses constructor parameters
> and still requires 'typename'.  I'm not 100% sure if the standard really says
> we should also handle constructors.  Does a constructor have a function type?

Not that we can ask about, but a constructor declaration is a function 
declaration.

> But I guess it makes sense, so this patch handles it.  To handle a constructor
> in a class, we need to pass flags to cp_parser_constructor_declarator_p.  To
> handle an out-of-line constructor, use constructor_name_p.
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?

OK.

Jason
Marek Polacek March 13, 2019, 6:34 p.m. UTC | #2
On Wed, Mar 13, 2019 at 02:32:36PM -0400, Jason Merrill wrote:
> On 3/13/19 1:25 PM, Marek Polacek wrote:
> > This PR points out that our P0634 implementation misses constructor parameters
> > and still requires 'typename'.  I'm not 100% sure if the standard really says
> > we should also handle constructors.  Does a constructor have a function type?
> 
> Not that we can ask about, but a constructor declaration is a function
> declaration.

That settles it, then.

> > But I guess it makes sense, so this patch handles it.  To handle a constructor
> > in a class, we need to pass flags to cp_parser_constructor_declarator_p.  To
> > handle an out-of-line constructor, use constructor_name_p.
> > 
> > Bootstrapped/regtested on x86_64-linux, ok for trunk?
> 
> OK.

Thanks!

Marek
diff mbox series

Patch

diff --git gcc/cp/parser.c gcc/cp/parser.c
index f95111169ed..8244366e669 100644
--- gcc/cp/parser.c
+++ gcc/cp/parser.c
@@ -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,
diff --git gcc/testsuite/g++.dg/cpp2a/typename15.C gcc/testsuite/g++.dg/cpp2a/typename15.C
new file mode 100644
index 00000000000..9094190cec9
--- /dev/null
+++ gcc/testsuite/g++.dg/cpp2a/typename15.C
@@ -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) { }