From b6d0f41ac5c1786911858b4763bb6f92519166f4 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Mon, 28 Jan 2019 22:14:27 +0000 Subject: [PATCH] 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. * 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 | 7 ++++++ gcc/cp/parser.c | 31 ++++++++++++++----------- gcc/testsuite/ChangeLog | 8 +++++++ gcc/testsuite/g++.dg/cpp2a/typename1.C | 2 +- gcc/testsuite/g++.dg/cpp2a/typename13.C | 13 +++++++++++ gcc/testsuite/g++.dg/cpp2a/typename6.C | 11 +++++---- 6 files changed, 54 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/typename13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dcac8e7d106..5e2f69ddc1f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-01-28 Marek Polacek + + 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 PR c++/88815 - narrowing conversion lost in decltype. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index dc9d651308a..16f2a32bc0b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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 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 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; + } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a36e19c5152..7af76a148c8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2019-01-28 Marek Polacek + + 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 * g++.dg/cpp0x/enum37.C: Add dg-error. diff --git a/gcc/testsuite/g++.dg/cpp2a/typename1.C b/gcc/testsuite/g++.dg/cpp2a/typename1.C index 833d3b86093..0c1f6309c5b 100644 --- a/gcc/testsuite/g++.dg/cpp2a/typename1.C +++ b/gcc/testsuite/g++.dg/cpp2a/typename1.C @@ -6,7 +6,7 @@ template T::R f(); // Ill-formed (no diagnostic required), attempt to declare // a void variable template -template void f(T::R); +template void f(T::R); // { dg-error "declared void" } template struct A; template using B = A::U; diff --git a/gcc/testsuite/g++.dg/cpp2a/typename13.C b/gcc/testsuite/g++.dg/cpp2a/typename13.C new file mode 100644 index 00000000000..c439f726c5d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/typename13.C @@ -0,0 +1,13 @@ +// P0634R3, PR c++/88358 +// { dg-do compile { target c++2a } } + +template +int pi(T::your_pi); + +struct Foo { static constexpr int your_pi = 10; }; + +int +main () +{ + return pi; +} diff --git a/gcc/testsuite/g++.dg/cpp2a/typename6.C b/gcc/testsuite/g++.dg/cpp2a/typename6.C index 49e2235a53d..e96e2ab802c 100644 --- a/gcc/testsuite/g++.dg/cpp2a/typename6.C +++ b/gcc/testsuite/g++.dg/cpp2a/typename6.C @@ -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 -int fn3 (T::X); + +struct M { + template + int fn (T::X); +}; template -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 -void fn7 (T::X p) +void fn7 (typename T::X p) { int i = static_cast(p); i = dynamic_cast(p); -- 2.30.2