diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 3003d0a8d339..4bd29b629de4 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -683,6 +683,8 @@ def err_id_after_template_in_nested_name_spec : Error< "expected template name after 'template' keyword in nested name specifier">; def err_unexpected_template_in_unqualified_id : Error< "'template' keyword not permitted here">; +def err_unexpected_template_after_using : Error< + "'template' keyword not permitted after 'using' keyword">; def err_two_right_angle_brackets_need_space : Error< "a space is required between consecutive right angle brackets (use '> >')">; def err_right_angle_bracket_equal_needs_space : Error< diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 7d2fcbd3e1b1..c4fe23c60c30 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -474,6 +474,13 @@ Parser::ParseUsingDirectiveOrDeclaration(DeclaratorContext Context, return nullptr; } + // Consume unexpected 'template' keywords. + while (Tok.is(tok::kw_template)) { + SourceLocation TemplateLoc = ConsumeToken(); + Diag(TemplateLoc, diag::err_unexpected_template_after_using) + << FixItHint::CreateRemoval(TemplateLoc); + } + // 'using namespace' means this is a using-directive. if (Tok.is(tok::kw_namespace)) { // Template parameters are always an error here. @@ -2542,6 +2549,13 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Eat 'using'. SourceLocation UsingLoc = ConsumeToken(); + // Consume unexpected 'template' keywords. + while (Tok.is(tok::kw_template)) { + SourceLocation TemplateLoc = ConsumeToken(); + Diag(TemplateLoc, diag::err_unexpected_template_after_using) + << FixItHint::CreateRemoval(TemplateLoc); + } + if (Tok.is(tok::kw_namespace)) { Diag(UsingLoc, diag::err_using_namespace_in_class); SkipUntil(tok::semi, StopBeforeMatch); diff --git a/clang/test/Parser/using-template.cpp b/clang/test/Parser/using-template.cpp new file mode 100644 index 000000000000..686873d60b84 --- /dev/null +++ b/clang/test/Parser/using-template.cpp @@ -0,0 +1,52 @@ +// RUN: %clang_cc1 %s -verify + +namespace N1 { +template +struct Foo { + template + struct Bar { + static constexpr bool is_present = false; + }; +}; + +template +struct Foo : public Foo { + using template Foo::Bar; + // expected-error@-1 {{'template' keyword not permitted after 'using' keyword}} +}; +} + +namespace N2 { +namespace foo { + using I = int; +} +using template namespace foo; +// expected-error@-1 {{'template' keyword not permitted after 'using' keyword}} +using template template namespace foo; +// expected-error@-1 2{{'template' keyword not permitted after 'using' keyword}} +I i; +} + +namespace N3 { +namespace foo { + using I = int; +} +using template foo::I; +// expected-error@-1 {{'template' keyword not permitted after 'using' keyword}} +I i; +} + +namespace N4 { +template +class A {}; + +template +using B = A; +B b; + +using template C = A; +// expected-error@-1 {{'template' keyword not permitted after 'using' keyword}} +// expected-error@-2 {{expected unqualified-id}} +C c; +// expected-error@-1 {{no template named 'C'}} +}