aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/ASTContext.cpp56
-rw-r--r--lib/AST/ASTDiagnostic.cpp8
-rw-r--r--lib/AST/DeclBase.cpp1
-rw-r--r--lib/AST/DeclTemplate.cpp31
-rw-r--r--lib/AST/DumpXML.cpp3
-rw-r--r--lib/AST/Type.cpp31
-rw-r--r--lib/CodeGen/CGDecl.cpp1
-rw-r--r--lib/CodeGen/CodeGenModule.cpp1
-rw-r--r--lib/Lex/PPMacroExpansion.cpp1
-rw-r--r--lib/Parse/ParseDeclCXX.cpp48
-rw-r--r--lib/Parse/ParseTemplate.cpp8
-rw-r--r--lib/Sema/SemaAccess.cpp4
-rw-r--r--lib/Sema/SemaCXXScopeSpec.cpp21
-rw-r--r--lib/Sema/SemaDecl.cpp41
-rw-r--r--lib/Sema/SemaDeclCXX.cpp100
-rw-r--r--lib/Sema/SemaTemplate.cpp84
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp12
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp55
-rw-r--r--lib/Sema/SemaType.cpp26
-rw-r--r--lib/Sema/TreeTransform.h37
-rw-r--r--lib/Serialization/ASTReader.cpp6
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp8
-rw-r--r--lib/Serialization/ASTWriter.cpp3
-rw-r--r--lib/Serialization/ASTWriterDecl.cpp6
24 files changed, 478 insertions, 114 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index d6535e9f8c..a5ff664449 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -969,13 +969,18 @@ ASTContext::getTypeInfo(const Type *T) const {
return getTypeInfo(
cast<AttributedType>(T)->getEquivalentType().getTypePtr());
- case Type::TemplateSpecialization:
+ case Type::TemplateSpecialization: {
assert(getCanonicalType(T) != T &&
"Cannot request the size of a dependent type");
- // FIXME: this is likely to be wrong once we support template
- // aliases, since a template alias could refer to a typedef that
- // has an __aligned__ attribute on it.
- return getTypeInfo(getCanonicalType(T));
+ const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T);
+ // A type alias template specialization may refer to a typedef with the
+ // aligned attribute on it.
+ if (TST->isTypeAlias())
+ return getTypeInfo(TST->getAliasedType().getTypePtr());
+ else
+ return getTypeInfo(getCanonicalType(T));
+ }
+
}
assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
@@ -2247,10 +2252,10 @@ TypeSourceInfo *
ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
SourceLocation NameLoc,
const TemplateArgumentListInfo &Args,
- QualType CanonType) const {
+ QualType Underlying) const {
assert(!Name.getAsDependentTemplateName() &&
"No dependent template names here!");
- QualType TST = getTemplateSpecializationType(Name, Args, CanonType);
+ QualType TST = getTemplateSpecializationType(Name, Args, Underlying);
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
TemplateSpecializationTypeLoc TL
@@ -2266,7 +2271,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
const TemplateArgumentListInfo &Args,
- QualType Canon) const {
+ QualType Underlying) const {
assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
@@ -2278,35 +2283,46 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
ArgVec.push_back(Args[i].getArgument());
return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs,
- Canon);
+ Underlying);
}
QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
const TemplateArgument *Args,
unsigned NumArgs,
- QualType Canon) const {
+ QualType Underlying) const {
assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
// Look through qualified template names.
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
Template = TemplateName(QTN->getTemplateDecl());
- if (!Canon.isNull())
- Canon = getCanonicalType(Canon);
- else
- Canon = getCanonicalTemplateSpecializationType(Template, Args, NumArgs);
+ bool isTypeAlias =
+ Template.getAsTemplateDecl() &&
+ isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
+
+ QualType CanonType;
+ if (!Underlying.isNull())
+ CanonType = getCanonicalType(Underlying);
+ else {
+ assert(!isTypeAlias &&
+ "Underlying type for template alias must be computed by caller");
+ CanonType = getCanonicalTemplateSpecializationType(Template, Args,
+ NumArgs);
+ }
// Allocate the (non-canonical) template specialization type, but don't
// try to unique it: these types typically have location information that
// we don't unique and don't want to lose.
- void *Mem = Allocate((sizeof(TemplateSpecializationType) +
- sizeof(TemplateArgument) * NumArgs),
+ void *Mem = Allocate(sizeof(TemplateSpecializationType) +
+ sizeof(TemplateArgument) * NumArgs +
+ (isTypeAlias ? sizeof(QualType) : 0),
TypeAlignment);
TemplateSpecializationType *Spec
= new (Mem) TemplateSpecializationType(Template,
Args, NumArgs,
- Canon);
+ CanonType,
+ isTypeAlias ? Underlying : QualType());
Types.push_back(Spec);
return QualType(Spec, 0);
@@ -2318,6 +2334,10 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
unsigned NumArgs) const {
assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
+ assert((!Template.getAsTemplateDecl() ||
+ !isa<TypeAliasTemplateDecl>(Template.getAsTemplateDecl())) &&
+ "Underlying type for template alias must be computed by caller");
+
// Look through qualified template names.
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
Template = TemplateName(QTN->getTemplateDecl());
@@ -2346,7 +2366,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template,
TypeAlignment);
Spec = new (Mem) TemplateSpecializationType(CanonTemplate,
CanonArgs.data(), NumArgs,
- QualType());
+ QualType(), QualType());
Types.push_back(Spec);
TemplateSpecializationTypes.InsertNode(Spec, InsertPos);
}
diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp
index 897b4a4c1f..16d2f85360 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -56,9 +56,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
continue;
}
- // Don't desugar template specializations.
- if (isa<TemplateSpecializationType>(Ty))
- break;
+ // Don't desugar template specializations, unless it's an alias template.
+ if (const TemplateSpecializationType *TST
+ = dyn_cast<TemplateSpecializationType>(Ty))
+ if (!TST->isTypeAlias())
+ break;
// Don't desugar magic Objective-C types.
if (QualType(Ty,0) == Context.getObjCIdType() ||
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 6d517c5440..8f3388ee58 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -439,6 +439,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
case Typedef:
case TypeAlias:
+ case TypeAliasTemplate:
case UnresolvedUsingTypename:
case TemplateTypeParm:
return IDNS_Ordinary | IDNS_Type;
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 6272340691..bc375d0ad2 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -735,3 +735,34 @@ FriendTemplateDecl *FriendTemplateDecl::Create(ASTContext &Context,
EmptyShell Empty) {
return new (Context) FriendTemplateDecl(Empty);
}
+
+//===----------------------------------------------------------------------===//
+// TypeAliasTemplateDecl Implementation
+//===----------------------------------------------------------------------===//
+
+TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
+ DeclContext *DC,
+ SourceLocation L,
+ DeclarationName Name,
+ TemplateParameterList *Params,
+ NamedDecl *Decl) {
+ AdoptTemplateParameterList(Params, DC);
+ return new (C) TypeAliasTemplateDecl(DC, L, Name, Params, Decl);
+}
+
+TypeAliasTemplateDecl *TypeAliasTemplateDecl::Create(ASTContext &C,
+ EmptyShell) {
+ return new (C) TypeAliasTemplateDecl(0, SourceLocation(), DeclarationName(),
+ 0, 0);
+}
+
+void TypeAliasTemplateDecl::DeallocateCommon(void *Ptr) {
+ static_cast<Common *>(Ptr)->~Common();
+}
+RedeclarableTemplateDecl::CommonBase *
+TypeAliasTemplateDecl::newCommon(ASTContext &C) {
+ Common *CommonPtr = new (C) Common;
+ C.AddDeallocation(DeallocateCommon, CommonPtr);
+ return CommonPtr;
+}
+
diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp
index 7d593bc46f..8bb39ba470 100644
--- a/lib/AST/DumpXML.cpp
+++ b/lib/AST/DumpXML.cpp
@@ -619,7 +619,8 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
// TemplateDecl
void visitTemplateDeclChildren(TemplateDecl *D) {
visitTemplateParameters(D->getTemplateParameters());
- dispatch(D->getTemplatedDecl());
+ if (D->getTemplatedDecl())
+ dispatch(D->getTemplatedDecl());
}
// FunctionTemplateDecl
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index ed22235593..b0086d92c8 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -1559,13 +1559,13 @@ anyDependentTemplateArguments(const TemplateArgument *Args, unsigned N) {
TemplateSpecializationType::
TemplateSpecializationType(TemplateName T,
- const TemplateArgument *Args,
- unsigned NumArgs, QualType Canon)
+ const TemplateArgument *Args, unsigned NumArgs,
+ QualType Canon, QualType AliasedType)
: Type(TemplateSpecialization,
Canon.isNull()? QualType(this, 0) : Canon,
- T.isDependent(), false, T.containsUnexpandedParameterPack()),
- Template(T), NumArgs(NumArgs)
-{
+ Canon.isNull()? T.isDependent() : Canon->isDependentType(),
+ false, T.containsUnexpandedParameterPack()),
+ Template(T), NumArgs(NumArgs) {
assert(!T.getAsDependentTemplateName() &&
"Use DependentTemplateSpecializationType for dependent template-name");
assert((!Canon.isNull() ||
@@ -1576,7 +1576,12 @@ TemplateSpecializationType(TemplateName T,
= reinterpret_cast<TemplateArgument *>(this + 1);
for (unsigned Arg = 0; Arg < NumArgs; ++Arg) {
// Update dependent and variably-modified bits.
- if (Args[Arg].isDependent())
+ // If the canonical type exists and is non-dependent, the template
+ // specialization type can be non-dependent even if one of the type
+ // arguments is. Given:
+ // template<typename T> using U = int;
+ // U<T> is always non-dependent, irrespective of the type T.
+ if (Canon.isNull() && Args[Arg].isDependent())
setDependent();
if (Args[Arg].getKind() == TemplateArgument::Type &&
Args[Arg].getAsType()->isVariablyModifiedType())
@@ -1586,6 +1591,15 @@ TemplateSpecializationType(TemplateName T,
new (&TemplateArgs[Arg]) TemplateArgument(Args[Arg]);
}
+
+ // Store the aliased type if this is a type alias template specialization.
+ bool IsTypeAlias = !AliasedType.isNull();
+ assert(IsTypeAlias == isTypeAlias() &&
+ "allocated wrong size for type alias");
+ if (IsTypeAlias) {
+ TemplateArgument *Begin = reinterpret_cast<TemplateArgument *>(this + 1);
+ *reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType;
+ }
}
void
@@ -1599,6 +1613,11 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID,
Args[Idx].Profile(ID, Context);
}
+bool TemplateSpecializationType::isTypeAlias() const {
+ TemplateDecl *D = Template.getAsTemplateDecl();
+ return D && isa<TypeAliasTemplateDecl>(D);
+}
+
QualType
QualifierCollector::apply(const ASTContext &Context, QualType QT) const {
if (!hasNonFastQualifiers())
diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp
index c027375818..0e1054affd 100644
--- a/lib/CodeGen/CGDecl.cpp
+++ b/lib/CodeGen/CGDecl.cpp
@@ -51,6 +51,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
case Decl::ImplicitParam:
case Decl::ClassTemplate:
case Decl::FunctionTemplate:
+ case Decl::TypeAliasTemplate:
case Decl::TemplateTemplateParm:
case Decl::ObjCMethod:
case Decl::ObjCCategory:
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 4ce12ecd60..4bf1e3ad3e 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -2060,6 +2060,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
case Decl::UsingDirective:
case Decl::ClassTemplate:
case Decl::FunctionTemplate:
+ case Decl::TypeAliasTemplate:
case Decl::NamespaceAlias:
break;
case Decl::CXXConstructor:
diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp
index d6e0d3a1c0..3b4f042291 100644
--- a/lib/Lex/PPMacroExpansion.cpp
+++ b/lib/Lex/PPMacroExpansion.cpp
@@ -557,6 +557,7 @@ static bool HasFeature(const Preprocessor &PP, const IdentifierInfo *II) {
.Case("ownership_returns", true)
.Case("ownership_takes", true)
// C++0x features
+ .Case("cxx_alias_templates", LangOpts.CPlusPlus0x)
.Case("cxx_attributes", LangOpts.CPlusPlus0x)
.Case("cxx_auto_type", LangOpts.CPlusPlus0x)
.Case("cxx_decltype", LangOpts.CPlusPlus0x)
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 41b773e007..ae6b3ff011 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -387,13 +387,34 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
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 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
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 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
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 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context,
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 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
MaybeParseMicrosoftAttributes(attrs);
if (Tok.is(tok::kw_using)) {
- // FIXME: Check for template aliases
-
ProhibitAttributes(attrs);
// Eat 'using'.
@@ -1527,7 +1553,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS,
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);
}
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index 12e38daf00..aa89d75c6d 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -905,10 +905,10 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
// C++0x [temp.arg.template]p1:
// A template-argument for a template template-parameter shall be the name
- // of a class template or a template alias, expressed as id-expression.
+ // of a class template or an alias template, expressed as id-expression.
//
- // We parse an id-expression that refers to a class template or template
- // alias. The grammar we parse is:
+ // We parse an id-expression that refers to a class template or alias
+ // template. The grammar we parse is:
//
// nested-name-specifier[opt] template[opt] identifier ...[opt]
//
@@ -969,7 +969,7 @@ ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() {
MemberOfUnknownSpecialization);
if (TNK == TNK_Dependent_template_name || TNK == TNK_Type_template) {
// We have an id-expression that refers to a class template or
- // (C++0x) template alias.
+ // (C++0x) alias template.
Result = ParsedTemplateArgument(SS, Template, Name.StartLocation);
}
}
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index 411d424dd8..63983c3daf 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -445,8 +445,8 @@ static AccessResult MatchesFriend(Sema &S,
continue;
// If the template names don't match, it can't be a dependent
- // match. This isn't true in C++0x because of template aliases.
- if (!S.LangOpts.CPlusPlus0x && CTD->getDeclName() != Friend->getDeclName())
+ // match.
+ if (CTD->getDeclName() != Friend->getDeclName())
continue;
// If the class's context can't instantiate to the friend's
diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp
index 5ee256ab21..ff3890023e 100644
--- a/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/lib/Sema/SemaCXXScopeSpec.cpp
@@ -94,9 +94,13 @@ DeclContext *Sema::computeDeclContext(const CXXScopeSpec &SS,
if (EnteringContext) {
const Type *NNSType = NNS->getAsType();
if (!NNSType) {
- // do nothing, fall out
- } else if (const TemplateSpecializationType *SpecType
- = NNSType->getAs<TemplateSpecializationType>()) {
+ return 0;
+ }
+
+ // Look through type alias templates, per C++0x [temp.dep.type]p1.
+ NNSType = Context.getCanonicalType(NNSType);
+ if (const TemplateSpecializationType *SpecType
+ = NNSType->getAs<TemplateSpecializationType>()) {
// We are entering the context of the nested name specifier, so try to
// match the nested name specifier to either a primary class template
// or a class template partial specialization.
@@ -382,7 +386,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
isDependent = ObjectType->isDependentType();
} else if (SS.isSet()) {
// This nested-name-specifier occurs after another nested-name-specifier,
- // so long into the context associated with the prior nested-name-specifier.
+ // so look into the context associated with the prior nested-name-specifier.
LookupCtx = computeDeclContext(SS, EnteringContext);
isDependent = isDependentScopeSpecifier(SS);
Found.setContextRange(SS.getRange());
@@ -712,8 +716,13 @@ bool Sema::ActOnCXXNestedNameSpecifier(Scope *S,
if (T.isNull())
return true;
- // FIXME: Template aliases will need to check the resulting type to make
- // sure that it's either dependent or a tag type.
+ // Alias template specializations can produce types which are not valid
+ // nested name specifiers.
+ if (!T->isDependentType() && !T->getAs<TagType>()) {
+ Diag(TemplateNameLoc, diag::err_nested_name_spec_non_tag) << T;
+ NoteAllFoundTemplates(Template.get());
+ return true;
+ }
// Provide source-location information for the template specialization
// type.
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 6231fbd111..7845247a24 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -891,19 +891,19 @@ static bool isOutOfScopePreviousDeclaration(NamedDecl *,
/// Filters out lookup results that don't fall within the given scope
/// as determined by isDeclInScope.
-static void FilterLookupForScope(Sema &SemaRef, LookupResult &R,
- DeclContext *Ctx, Scope *S,
- bool ConsiderLinkage,
- bool ExplicitInstantiationOrSpecialization) {
+void Sema::FilterLookupForScope(LookupResult &R,
+ DeclContext *Ctx, Scope *S,
+ bool ConsiderLinkage,
+ bool ExplicitInstantiationOrSpecialization) {
LookupResult::Filter F = R.makeFilter();
while (F.hasNext()) {
NamedDecl *D = F.next();
- if (SemaRef.isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization))
+ if (isDeclInScope(D, Ctx, S, ExplicitInstantiationOrSpecialization))
continue;
if (ConsiderLinkage &&
- isOutOfScopePreviousDeclaration(D, Ctx, SemaRef.Context))
+ isOutOfScopePreviousDeclaration(D, Ctx, Context))
continue;
F.erase();
@@ -3304,15 +3304,13 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Handle attributes prior to checking for duplicates in MergeVarDecl
ProcessDeclAttributes(S, NewTD, D);
+ CheckTypedefForVariablyModifiedType(S, NewTD);
+
return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration);
}
-/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which
-/// declares a typedef-name, either using the 'typedef' type specifier or via
-/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'.
-NamedDecl*
-Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
- LookupResult &Previous, bool &Redeclaration) {
+void
+Sema::CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *NewTD) {
// C99 6.7.7p2: If a typedef name specifies a variably modified type
// then it shall have block scope.
// Note that variably modified types must be fixed before merging the decl so
@@ -3343,10 +3341,18 @@ Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
}
}
}
+}
+
+/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which
+/// declares a typedef-name, either using the 'typedef' type specifier or via
+/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'.
+NamedDecl*
+Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD,
+ LookupResult &Previous, bool &Redeclaration) {
// Merge the decl with the existing one if appropriate. If the decl is
// in an outer scope, it isn't the same thing.
- FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false,
+ FilterLookupForScope(Previous, DC, S, /*ConsiderLinkage*/ false,
/*ExplicitInstantiationOrSpecialization=*/false);
if (!Previous.empty()) {
Redeclaration = true;
@@ -3625,7 +3631,7 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
// Don't consider existing declarations that are in a different
// scope and are out-of-semantic-context declarations (if the new
// declaration has linkage).
- FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage(),
+ FilterLookupForScope(Previous, DC, S, NewVD->hasLinkage(),
isExplicitSpecialization);
if (!getLangOptions().CPlusPlus)
@@ -4072,7 +4078,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
// Set the lexical context.
NewFD->setLexicalDeclContext(CurContext);
// Filter out previous declarations that don't match the scope.
- FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(),
+ FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(),
/*ExplicitInstantiationOrSpecialization=*/false);
} else {
isFriend = D.getDeclSpec().isFriendSpecified();
@@ -4350,7 +4356,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
}
// Filter out previous declarations that don't match the scope.
- FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage(),
+ FilterLookupForScope(Previous, DC, S, NewFD->hasLinkage(),
isExplicitSpecialization ||
isFunctionTemplateSpecialization);
@@ -4417,6 +4423,9 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
bool IsTypeAlias = false;
if (const TypedefType *TT = Param->getType()->getAs<TypedefType>())
IsTypeAlias = isa<TypeAliasDecl>(TT->getDecl());
+ else if (const TemplateSpecializationType *TST =
+ Param->getType()->getAs<TemplateSpecializationType>())
+ IsTypeAlias = TST->isTypeAlias();
Diag(Param->getLocation(), diag::err_param_typedef_of_void)
<< IsTypeAlias;
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 2ef15b672d..6dad78442d 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3467,6 +3467,11 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>())
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
<< DeclaratorType << isa<TypeAliasDecl>(TT->getDecl());
+ else if (const TemplateSpecializationType *TST =
+ DeclaratorType->getAs<TemplateSpecializationType>())
+ if (TST->isTypeAlias())
+ Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
+ << DeclaratorType << 1;
// C++ [class.dtor]p2:
// A destructor is used to destroy objects of its class type. A
@@ -4701,9 +4706,13 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc,
Decl *Sema::ActOnAliasDeclaration(Scope *S,
AccessSpecifier AS,
+ MultiTemplateParamsArg TemplateParamLists,
SourceLocation UsingLoc,
UnqualifiedId &Name,
TypeResult Type) {
+ // Skip up to the relevant declaration scope.
+ while (S->getFlags() & Scope::TemplateParamScope)
+ S = S->getParent();
assert((S->getFlags() & Scope::DeclScope) &&
"got alias-declaration outside of declaration scope");
@@ -4719,8 +4728,11 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
return 0;
if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo,
- UPPC_DeclarationType))
+ UPPC_DeclarationType)) {
Invalid = true;
+ TInfo = Context.getTrivialTypeSourceInfo(Context.IntTy,
+ TInfo->getTypeLoc().getBeginLoc());
+ }
LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration);
LookupName(Previous, S);
@@ -4745,13 +4757,93 @@ Decl *Sema::ActOnAliasDeclaration(Scope *S,
if (Invalid)
NewTD->setInvalidDecl();
+ CheckTypedefForVariablyModifiedType(S, NewTD);
+ Invalid |= NewTD->isInvalidDecl();
+
bool Redeclaration = false;
- ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration);
+
+ NamedDecl *NewND;
+ if (TemplateParamLists.size()) {
+ TypeAliasTemplateDecl *OldDecl = 0;
+ TemplateParameterList *OldTemplateParams = 0;
+
+ if (TemplateParamLists.size() != 1) {
+ Diag(UsingLoc, diag::err_alias_template_extra_headers)
+ << SourceRange(TemplateParamLists.get()[1]->getTemplateLoc(),
+ TemplateParamLists.get()[TemplateParamLists.size()-1]->getRAngleLoc());
+ }
+ TemplateParameterList *TemplateParams = TemplateParamLists.get()[0];
+