r211031 - [C++1z] Implement N4051: 'typename' is permitted instead of 'class' when declaring a template template parameter.
Richard Smith
richard-llvm at metafoo.co.uk
Mon Jun 16 08:51:22 PDT 2014
Author: rsmith
Date: Mon Jun 16 10:51:22 2014
New Revision: 211031
URL: http://llvm.org/viewvc/llvm-project?rev=211031&view=rev
Log:
[C++1z] Implement N4051: 'typename' is permitted instead of 'class' when declaring a template template parameter.
Modified:
cfe/trunk/include/clang/Basic/DiagnosticGroups.td
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/lib/Parse/ParseTemplate.cpp
cfe/trunk/test/FixIt/fixit.cpp
cfe/trunk/test/Parser/cxx-template-decl.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticGroups.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=211031&r1=211030&r2=211031&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticGroups.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticGroups.td Mon Jun 16 10:51:22 2014
@@ -121,6 +121,9 @@ def FormatZeroLength : DiagGroup<"format
def CXXPre1yCompat : DiagGroup<"c++98-c++11-compat">;
def CXXPre1yCompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic",
[CXXPre1yCompat]>;
+def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">;
+def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic",
+ [CXXPre1zCompat]>;
def CXX98CompatBindToTemporaryCopy :
DiagGroup<"c++98-compat-bind-to-temporary-copy">;
@@ -133,11 +136,13 @@ def CXX98Compat : DiagGroup<"c++98-compa
[CXX98CompatBindToTemporaryCopy,
CXX98CompatLocalTypeTemplateArgs,
CXX98CompatUnnamedTypeTemplateArgs,
- CXXPre1yCompat]>;
+ CXXPre1yCompat,
+ CXXPre1zCompat]>;
// Warnings for C++11 features which are Extensions in C++98 mode.
def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
[CXX98Compat,
- CXXPre1yCompatPedantic]>;
+ CXXPre1yCompatPedantic,
+ CXXPre1zCompatPedantic]>;
def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
@@ -157,10 +162,16 @@ def CXX11Compat : DiagGroup<"c++11-compa
[CXX11Narrowing,
CXX11CompatReservedUserDefinedLiteral,
CXX11CompatDeprecatedWritableStr,
- CXXPre1yCompat]>;
+ CXXPre1yCompat,
+ CXXPre1zCompat]>;
def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic",
- [CXXPre1yCompatPedantic]>;
+ [CXXPre1yCompatPedantic,
+ CXXPre1zCompatPedantic]>;
+
+def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>;
+def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
+ [CXXPre1zCompatPedantic]>;
def : DiagGroup<"effc++">;
def DivZero : DiagGroup<"division-by-zero">;
@@ -620,6 +631,10 @@ def CXX11 : DiagGroup<"c++11-extensions"
// earlier C++ versions.
def CXX1y : DiagGroup<"c++1y-extensions">;
+// A warning group for warnings about using C++1z features as extensions in
+// earlier C++ versions.
+def CXX1z : DiagGroup<"c++1z-extensions">;
+
def : DiagGroup<"c++0x-extensions", [CXX11]>;
def DelegatingCtorCycles :
DiagGroup<"delegating-ctor-cycles">;
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=211031&r1=211030&r2=211031&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Jun 16 10:51:22 2014
@@ -566,6 +566,13 @@ def err_expected_comma_greater : Error<
"expected ',' or '>' in template-parameter-list">;
def err_class_on_template_template_param : Error<
"template template parameter requires 'class' after the parameter list">;
+def ext_template_template_param_typename : ExtWarn<
+ "template template parameter using 'typename' is a C++1z extension">,
+ InGroup<CXX1z>;
+def warn_cxx1y_compat_template_template_param_typename : Warning<
+ "template template parameter using 'typename' is "
+ "incompatible with C++ standards before C++1z">,
+ InGroup<CXXPre1zCompat>, DefaultIgnore;
def err_template_spec_syntax_non_template : Error<
"identifier followed by '<' indicates a class template specialization but "
"%0 %select{does not refer to a template|refers to a function template|"
Modified: cfe/trunk/lib/Parse/ParseTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=211031&r1=211030&r2=211031&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseTemplate.cpp (original)
+++ cfe/trunk/lib/Parse/ParseTemplate.cpp Mon Jun 16 10:51:22 2014
@@ -519,10 +519,13 @@ Decl *Parser::ParseTypeParameter(unsigne
/// template parameters.
///
/// type-parameter: [C++ temp.param]
-/// 'template' '<' template-parameter-list '>' 'class'
+/// 'template' '<' template-parameter-list '>' type-parameter-key
/// ...[opt] identifier[opt]
-/// 'template' '<' template-parameter-list '>' 'class' identifier[opt]
-/// = id-expression
+/// 'template' '<' template-parameter-list '>' type-parameter-key
+/// identifier[opt] = id-expression
+/// type-parameter-key:
+/// 'class'
+/// 'typename' [C++1z]
Decl *
Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) {
assert(Tok.is(tok::kw_template) && "Expected 'template' keyword");
@@ -539,20 +542,29 @@ Parser::ParseTemplateTemplateParameter(u
}
}
+ // Provide an ExtWarn if the C++1z feature of using 'typename' here is used.
// Generate a meaningful error if the user forgot to put class before the
// identifier, comma, or greater. Provide a fixit if the identifier, comma,
- // or greater appear immediately or after 'typename' or 'struct'. In the
- // latter case, replace the keyword with 'class'.
+ // or greater appear immediately or after 'struct'. In the latter case,
+ // replace the keyword with 'class'.
if (!TryConsumeToken(tok::kw_class)) {
bool Replace = Tok.is(tok::kw_typename) || Tok.is(tok::kw_struct);
- const Token& Next = Replace ? NextToken() : Tok;
- if (Next.is(tok::identifier) || Next.is(tok::comma) ||
- Next.is(tok::greater) || Next.is(tok::greatergreater) ||
- Next.is(tok::ellipsis))
+ const Token &Next = Tok.is(tok::kw_struct) ? NextToken() : Tok;
+ if (Tok.is(tok::kw_typename)) {
+ Diag(Tok.getLocation(),
+ getLangOpts().CPlusPlus1z
+ ? diag::warn_cxx1y_compat_template_template_param_typename
+ : diag::ext_template_template_param_typename)
+ << (!getLangOpts().CPlusPlus1z
+ ? FixItHint::CreateReplacement(Tok.getLocation(), "class")
+ : FixItHint());
+ } else if (Next.is(tok::identifier) || Next.is(tok::comma) ||
+ Next.is(tok::greater) || Next.is(tok::greatergreater) ||
+ Next.is(tok::ellipsis)) {
Diag(Tok.getLocation(), diag::err_class_on_template_template_param)
<< (Replace ? FixItHint::CreateReplacement(Tok.getLocation(), "class")
: FixItHint::CreateInsertion(Tok.getLocation(), "class "));
- else
+ } else
Diag(Tok.getLocation(), diag::err_class_on_template_template_param);
if (Replace)
Modified: cfe/trunk/test/FixIt/fixit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit.cpp?rev=211031&r1=211030&r2=211031&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit.cpp (original)
+++ cfe/trunk/test/FixIt/fixit.cpp Mon Jun 16 10:51:22 2014
@@ -204,7 +204,7 @@ template<class T> typedef Mystery<T>::ty
}
template<template<typename> Foo, // expected-error {{template template parameter requires 'class' after the parameter list}}
- template<typename> typename Bar, // expected-error {{template template parameter requires 'class' after the parameter list}}
+ template<typename> typename Bar, // expected-warning {{template template parameter using 'typename' is a C++1z extension}}
template<typename> struct Baz> // expected-error {{template template parameter requires 'class' after the parameter list}}
void func();
Modified: cfe/trunk/test/Parser/cxx-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-template-decl.cpp?rev=211031&r1=211030&r2=211031&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx-template-decl.cpp (original)
+++ cfe/trunk/test/Parser/cxx-template-decl.cpp Mon Jun 16 10:51:22 2014
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -verify %s -fdelayed-template-parsing -DDELAYED_TEMPLATE_PARSING
+// RUN: %clang_cc1 -fsyntax-only -verify -std=gnu++1z %s
@@ -24,6 +25,11 @@ template <template X> struct Err1; // ex
template <template <typename> > struct Err2; // expected-error {{template template parameter requires 'class' after the parameter list}}
template <template <typename> Foo> struct Err3; // expected-error {{template template parameter requires 'class' after the parameter list}}
+template <template <typename> typename Foo> struct Cxx1z;
+#if __cplusplus <= 201402L
+// expected-warning at -2 {{extension}}
+#endif
+
// Template function declarations
template <typename T> void foo();
template <typename T, typename U> void foo();
More information about the cfe-commits
mailing list