Bug 88979 - [C++20] P0634R3 not working for constructor parameter types
Summary: [C++20] P0634R3 not working for constructor parameter types
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.0
: P3 normal
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2019-01-22 14:35 UTC by 19Sebastian95
Modified: 2019-03-13 18:40 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-01-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description 19Sebastian95 2019-01-22 14:35:03 UTC
# gcc -v
Using built-in specs.
COLLECT_GCC=/opt/bin/gcc
Target: x86_64-pc-linux-gnu
Configured with: ../gcc/configure --prefix=/opt/ --enable-languages=c,c++
Thread model: posix
gcc version 9.0.0 20190118 (experimental) (GCC) 

# Description: 
When compiling the following code and uncommenting the first constructor of A it'll throw the error in the comment. 
The expected behaviour would either be "error: need 'typename' before 'T::type' because 'T' is a dependent scope" or no error at all.

# Options: 
-O2 -std=c++2a -Wall -Wextra

# Source Code:
template<typename T>
class A {
public:
    using type = T::type;
    /*A(T::type a) : mA{a} {}*/ // error: expected ')' before 'a'
    A(type a); // OK
    constexpr void a(T::type a) noexcept { // OK
        mA = a;
    }
    [[nodiscard]] constexpr T::type a() const noexcept { // OK
        return mA;
    }
private:
    T::type mA; // OK
};

template<typename T>
A<T>::A(T::type a) : mA{a} {} // OK


struct B {
    using type = int;
};

int main() {
    A<B> a{20};
    a.a(10);
    return a.a();
}
Comment 1 Marek Polacek 2019-01-22 17:00:04 UTC
I'll look though I'm not sure yet if there's an actual bug.  Is there a version with 'typename's included that compiles?
Comment 2 19Sebastian95 2019-01-22 18:08:20 UTC
I'm sorry if I'm misinterpreting this, but the program I wrote does compile with gcc 9.0, as the "error" part is commented out, so I'll just write what to do to get the descriped error: 

If my constructor is:

A(typename T::type a) : mA{a} {} 

it is working, but if I remove the typename it'll give me The "error: expected ')' before 'a'" error. (As far as I know it should detect that it is only a missing typename, so for versions before c++20 it should be "error: need 'typename' [...]" and for c++20 it shouldn't be an error).

So right now this won't compile:
A(T::type a) : mA{a} {} 

But if I'd define the constructor out-of-line it won't give me an error:

template<typename T>
A<T>::A(T::type a) : mA{a} {} 

As GCC is detecting that there can only be a type at this position, which it doesn't with the "header-only"-version.

I hope this will help.
Comment 3 Marek Polacek 2019-02-01 20:17:42 UTC
Oh, so basically this should compile in C++2a:

template<typename T>
struct A {
  using type = T::type;
  A(type);
};

template<typename T>
A<T>::A(T::type a) {}

but it doesn't.  It does when I add 'typename' to the out-of-line ctor parameter.
Comment 4 Marek Polacek 2019-02-04 22:17:57 UTC
And by the same token, I suspect this ought to work too:

template<typename T>
struct A {
  A(T::type);
};
Comment 5 Marek Polacek 2019-03-13 18:39:17 UTC
Author: mpolacek
Date: Wed Mar 13 18:38:45 2019
New Revision: 269656

URL: https://gcc.gnu.org/viewcvs?rev=269656&root=gcc&view=rev
Log:
	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.

Added:
    trunk/gcc/testsuite/g++.dg/cpp2a/typename15.C
Modified:
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/parser.c
    trunk/gcc/testsuite/ChangeLog
Comment 6 Marek Polacek 2019-03-13 18:40:10 UTC
Fixed.