Implement support for C++0x alias templates.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130953 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 41b773e..ae6b3ff 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -387,13 +387,34 @@
bool IsAliasDecl = Tok.is(tok::equal);
TypeResult TypeAlias;
if (IsAliasDecl) {
- // TODO: Do we want to support attributes somewhere in an alias declaration?
- // Can't follow GCC since it doesn't support them yet!
+ // TODO: Attribute support. C++0x attributes may appear before the equals.
+ // Where can GNU attributes appear?
ConsumeToken();
if (!getLang().CPlusPlus0x)
Diag(Tok.getLocation(), diag::ext_alias_declaration);
+ // Type alias templates cannot be specialized.
+ int SpecKind = -1;
+ if (Name.getKind() == UnqualifiedId::IK_TemplateId)
+ SpecKind = 0;
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization)
+ SpecKind = 1;
+ if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation)
+ SpecKind = 2;
+ if (SpecKind != -1) {
+ SourceRange Range;
+ if (SpecKind == 0)
+ Range = SourceRange(Name.TemplateId->LAngleLoc,
+ Name.TemplateId->RAngleLoc);
+ else
+ Range = TemplateInfo.getSourceRange();
+ Diag(Range.getBegin(), diag::err_alias_declaration_specialization)
+ << SpecKind << Range;
+ SkipUntil(tok::semi);
+ return 0;
+ }
+
// Name must be an identifier.
if (Name.getKind() != UnqualifiedId::IK_Identifier) {
Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier);
@@ -408,7 +429,9 @@
Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier)
<< FixItHint::CreateRemoval(SS.getRange());
- TypeAlias = ParseTypeName(0, Declarator::AliasDeclContext);
+ TypeAlias = ParseTypeName(0, TemplateInfo.Kind ?
+ Declarator::AliasTemplateContext :
+ Declarator::AliasDeclContext);
} else
// Parse (optional) attributes (most likely GNU strong-using extension).
MaybeParseGNUAttributes(attrs);
@@ -421,9 +444,9 @@
tok::semi);
// Diagnose an attempt to declare a templated using-declaration.
- // TODO: in C++0x, alias-declarations can be templates:
+ // In C++0x, alias-declarations can be templates:
// template <...> using id = type;
- if (TemplateInfo.Kind) {
+ if (TemplateInfo.Kind && !IsAliasDecl) {
SourceRange R = TemplateInfo.getSourceRange();
Diag(UsingLoc, diag::err_templated_using_declaration)
<< R << FixItHint::CreateRemoval(R);
@@ -434,9 +457,14 @@
return 0;
}
- if (IsAliasDecl)
- return Actions.ActOnAliasDeclaration(getCurScope(), AS, UsingLoc, Name,
- TypeAlias);
+ if (IsAliasDecl) {
+ TemplateParameterLists *TemplateParams = TemplateInfo.TemplateParams;
+ MultiTemplateParamsArg TemplateParamsArg(Actions,
+ TemplateParams ? TemplateParams->data() : 0,
+ TemplateParams ? TemplateParams->size() : 0);
+ return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg,
+ UsingLoc, Name, TypeAlias);
+ }
return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS,
Name, attrs.getList(),
@@ -1515,8 +1543,6 @@
MaybeParseMicrosoftAttributes(attrs);
if (Tok.is(tok::kw_using)) {
- // FIXME: Check for template aliases
-
ProhibitAttributes(attrs);
// Eat 'using'.
@@ -1527,7 +1553,7 @@
SkipUntil(tok::semi, true, true);
} else {
SourceLocation DeclEnd;
- // Otherwise, it must be using-declaration.
+ // Otherwise, it must be a using-declaration or an alias-declaration.
ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo,
UsingLoc, DeclEnd, AS);
}