On 10/15/2012 07:30 PM, Jason Merrill wrote:
Actually, let's keep the diagnostic when compiling with -pedantic in 98 mode.
... too late! ;) So I prepared the below, I'm finishing testing it.
Thanks, Paolo. //////////////////
/cp 2012-10-15 Paolo Carlini <paolo.carl...@oracle.com> PR c++/50080 (again) * parser.c (cp_parser_optional_template_keyword): When -pedantic and C++98 mode restore pre-Core/468 behavior. /testsuite 2012-10-15 Paolo Carlini <paolo.carl...@oracle.com> PR c++/50080 (again) * g++.dg/parse/tmpl-outside2.C: Tweak, error in C++98. * g++.dg/parse/tmpl-outside1.C: Likewise. * g++.dg/template/qualttp18.C: Likewise. * g++.old-deja/g++.pt/memtemp87.C: Likewise. * g++.old-deja/g++.pt/overload13.C: Likewise.
Index: cp/parser.c =================================================================== --- cp/parser.c (revision 192465) +++ cp/parser.c (working copy) @@ -23252,9 +23252,29 @@ cp_parser_optional_template_keyword (cp_parser *pa { if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) { - /* Consume the `template' keyword. */ - cp_lexer_consume_token (parser->lexer); - return true; + /* In C++98 the `template' keyword can only be used within templates; + outside templates the parser can always figure out what is a + template and what is not. In C++11, per the resolution of DR 468, + 'template' is allowed in cases where it is not strictly necessary. */ + if (!processing_template_decl + && pedantic && cxx_dialect == cxx98) + { + cp_token *token = cp_lexer_peek_token (parser->lexer); + error_at (token->location, + "in C++98 %<template%> (as a disambiguator) is only " + "allowed within templates"); + /* If this part of the token stream is rescanned, the same + error message would be generated. So, we purge the token + from the stream. */ + cp_lexer_purge_token (parser->lexer); + return false; + } + else + { + /* Consume the `template' keyword. */ + cp_lexer_consume_token (parser->lexer); + return true; + } } return false; } Index: testsuite/g++.old-deja/g++.pt/overload13.C =================================================================== --- testsuite/g++.old-deja/g++.pt/overload13.C (revision 192465) +++ testsuite/g++.old-deja/g++.pt/overload13.C (working copy) @@ -7,5 +7,5 @@ struct A { int main () { A a; - return a.template f (0); + return a.template f (0); // { dg-error "template" "" { target c++98 } } } Index: testsuite/g++.old-deja/g++.pt/memtemp87.C =================================================================== --- testsuite/g++.old-deja/g++.pt/memtemp87.C (revision 192465) +++ testsuite/g++.old-deja/g++.pt/memtemp87.C (working copy) @@ -12,4 +12,4 @@ class Q { template<template<class> class> class Y { }; -Q::template X<int> x; +Q::template X<int> x; // { dg-error "template" "" { target c++98 } } Index: testsuite/g++.dg/parse/tmpl-outside1.C =================================================================== --- testsuite/g++.dg/parse/tmpl-outside1.C (revision 192465) +++ testsuite/g++.dg/parse/tmpl-outside1.C (working copy) @@ -7,4 +7,4 @@ struct X template <int i> struct Y {}; }; -typedef X::template Y<0> y; +typedef X::template Y<0> y; // { dg-error "template|invalid" "" { target c++98 } } Index: testsuite/g++.dg/parse/tmpl-outside2.C =================================================================== --- testsuite/g++.dg/parse/tmpl-outside2.C (revision 192465) +++ testsuite/g++.dg/parse/tmpl-outside2.C (working copy) @@ -15,5 +15,5 @@ void test() int main() { - typename A<double>::template B<int> b; + typename A<double>::template B<int> b; // { dg-error "template|expected" "" { target c++98 } } } Index: testsuite/g++.dg/template/qualttp18.C =================================================================== --- testsuite/g++.dg/template/qualttp18.C (revision 192465) +++ testsuite/g++.dg/template/qualttp18.C (working copy) @@ -14,7 +14,7 @@ template <template <class> class TT> struct X struct C { - X<A::template B> x; + X<A::template B> x; // { dg-error "template" "" { target c++98 } } }; int main()