diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 32 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 19 |
3 files changed, 36 insertions, 27 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 3b669320e9..c9af67c8b6 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -2450,6 +2450,17 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, Underlying); } +#ifndef NDEBUG +static bool hasAnyPackExpansions(const TemplateArgument *Args, + unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) + if (Args[I].isPackExpansion()) + return true; + + return true; +} +#endif + QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgument *Args, @@ -2461,16 +2472,18 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) Template = TemplateName(QTN->getTemplateDecl()); - bool isTypeAlias = + 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"); + // We can get here with an alias template when the specialization contains + // a pack expansion that does not match up with a parameter pack. + assert((!IsTypeAlias || hasAnyPackExpansions(Args, NumArgs)) && + "Caller must compute aliased type"); + IsTypeAlias = false; CanonType = getCanonicalTemplateSpecializationType(Template, Args, NumArgs); } @@ -2480,13 +2493,11 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, // we don't unique and don't want to lose. void *Mem = Allocate(sizeof(TemplateSpecializationType) + sizeof(TemplateArgument) * NumArgs + - (isTypeAlias ? sizeof(QualType) : 0), + (IsTypeAlias? sizeof(QualType) : 0), TypeAlignment); TemplateSpecializationType *Spec - = new (Mem) TemplateSpecializationType(Template, - Args, NumArgs, - CanonType, - isTypeAlias ? Underlying : QualType()); + = new (Mem) TemplateSpecializationType(Template, Args, NumArgs, CanonType, + IsTypeAlias ? Underlying : QualType()); Types.push_back(Spec); return QualType(Spec, 0); @@ -2498,9 +2509,6 @@ 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()) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 698474b838..ebf5706ed0 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1884,7 +1884,7 @@ TemplateSpecializationType(TemplateName T, false, Canon.isNull()? T.containsUnexpandedParameterPack() : Canon->containsUnexpandedParameterPack()), - Template(T), NumArgs(NumArgs) { + Template(T), NumArgs(NumArgs), TypeAlias(!AliasedType.isNull()) { assert(!T.getAsDependentTemplateName() && "Use DependentTemplateSpecializationType for dependent template-name"); assert((T.getKind() == TemplateName::Template || @@ -1923,10 +1923,7 @@ TemplateSpecializationType(TemplateName T, } // 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) { + if (TypeAlias) { TemplateArgument *Begin = reinterpret_cast<TemplateArgument *>(this + 1); *reinterpret_cast<QualType*>(Begin + getNumArgs()) = AliasedType; } @@ -1943,11 +1940,6 @@ 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/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 7cd604d585..eca491f733 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1918,15 +1918,17 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Check that the template argument list is well-formed for this // template. SmallVector<TemplateArgument, 4> Converted; + bool ExpansionIntoFixedList = false; if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, - false, Converted)) + false, Converted, &ExpansionIntoFixedList)) return QualType(); QualType CanonType; bool InstantiationDependent = false; - if (TypeAliasTemplateDecl *AliasTemplate - = dyn_cast<TypeAliasTemplateDecl>(Template)) { + TypeAliasTemplateDecl *AliasTemplate = 0; + if (!ExpansionIntoFixedList && + (AliasTemplate = dyn_cast<TypeAliasTemplateDecl>(Template))) { // Find the canonical type for this type alias template specialization. TypeAliasDecl *Pattern = AliasTemplate->getTemplatedDecl(); if (Pattern->isInvalidDecl()) @@ -2891,7 +2893,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, - SmallVectorImpl<TemplateArgument> &Converted) { + SmallVectorImpl<TemplateArgument> &Converted, + bool *ExpansionIntoFixedList) { + if (ExpansionIntoFixedList) + *ExpansionIntoFixedList = false; + TemplateParameterList *Params = Template->getTemplateParameters(); unsigned NumParams = Params->size(); unsigned NumArgs = TemplateArgs.size(); @@ -2901,7 +2907,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, bool HasParameterPack = NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack(); - + // C++ [temp.arg]p1: // [...] The type and form of each template-argument specified in // a template-id shall match the type and form specified for the @@ -3088,6 +3094,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, ArgumentPack.size())); ArgumentPack.clear(); } + } else if (ExpansionIntoFixedList) { + // We have expanded a pack into a fixed list. + *ExpansionIntoFixedList = true; } return Invalid; |