diff options
Diffstat (limited to 'lib/AST')
-rw-r--r-- | lib/AST/ASTContext.cpp | 56 | ||||
-rw-r--r-- | lib/AST/ASTDiagnostic.cpp | 8 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 1 | ||||
-rw-r--r-- | lib/AST/DeclTemplate.cpp | 31 | ||||
-rw-r--r-- | lib/AST/DumpXML.cpp | 3 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 31 |
6 files changed, 102 insertions, 28 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()) |