diff options
Diffstat (limited to 'lib')
-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 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.cpp | 1 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 1 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 48 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaAccess.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 41 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 100 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 84 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 55 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 26 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 37 | ||||
-rw-r--r-- | lib/Serialization/ASTReader.cpp | 6 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 8 | ||||
-rw-r--r-- | lib/Serialization/ASTWriter.cpp | 3 | ||||
-rw-r--r-- | lib/Serialization/ASTWriterDecl.cpp | 6 |
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]; + |