diff options
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 2545 |
1 files changed, 1866 insertions, 679 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 568d68c9a7e82..d56b4e114e74c 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1,104 +1,239 @@ //===------- SemaTemplate.cpp - Semantic Analysis for C++ Templates -------===/ - // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. //===----------------------------------------------------------------------===/ - // // This file implements semantic analysis for C++ templates. //===----------------------------------------------------------------------===/ #include "Sema.h" +#include "TreeTransform.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/DeclSpec.h" #include "clang/Basic/LangOptions.h" - +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/Support/Compiler.h" +#include "llvm/ADT/StringExtras.h" using namespace clang; -/// isTemplateName - Determines whether the identifier II is a -/// template name in the current scope, and returns the template -/// declaration if II names a template. An optional CXXScope can be -/// passed to indicate the C++ scope in which the identifier will be -/// found. -TemplateNameKind Sema::isTemplateName(const IdentifierInfo &II, Scope *S, - TemplateTy &TemplateResult, - const CXXScopeSpec *SS) { - NamedDecl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName); - - TemplateNameKind TNK = TNK_Non_template; - TemplateDecl *Template = 0; - - if (IIDecl) { - if ((Template = dyn_cast<TemplateDecl>(IIDecl))) { - if (isa<FunctionTemplateDecl>(IIDecl)) - TNK = TNK_Function_template; - else if (isa<ClassTemplateDecl>(IIDecl) || - isa<TemplateTemplateParmDecl>(IIDecl)) - TNK = TNK_Type_template; - else - assert(false && "Unknown template declaration kind"); - } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(IIDecl)) { - // C++ [temp.local]p1: - // Like normal (non-template) classes, class templates have an - // injected-class-name (Clause 9). The injected-class-name - // can be used with or without a template-argument-list. When - // it is used without a template-argument-list, it is - // equivalent to the injected-class-name followed by the - // template-parameters of the class template enclosed in - // <>. When it is used with a template-argument-list, it - // refers to the specified class template specialization, - // which could be the current specialization or another - // specialization. - if (Record->isInjectedClassName()) { - Record = cast<CXXRecordDecl>(Context.getCanonicalDecl(Record)); - if ((Template = Record->getDescribedClassTemplate())) - TNK = TNK_Type_template; - else if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(Record)) { - Template = Spec->getSpecializedTemplate(); - TNK = TNK_Type_template; - } - } +/// \brief Determine whether the declaration found is acceptable as the name +/// of a template and, if so, return that template declaration. Otherwise, +/// returns NULL. +static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) { + if (!D) + return 0; + + if (isa<TemplateDecl>(D)) + return D; + + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) { + // C++ [temp.local]p1: + // Like normal (non-template) classes, class templates have an + // injected-class-name (Clause 9). The injected-class-name + // can be used with or without a template-argument-list. When + // it is used without a template-argument-list, it is + // equivalent to the injected-class-name followed by the + // template-parameters of the class template enclosed in + // <>. When it is used with a template-argument-list, it + // refers to the specified class template specialization, + // which could be the current specialization or another + // specialization. + if (Record->isInjectedClassName()) { + Record = cast<CXXRecordDecl>(Record->getDeclContext()); + if (Record->getDescribedClassTemplate()) + return Record->getDescribedClassTemplate(); + + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast<ClassTemplateSpecializationDecl>(Record)) + return Spec->getSpecializedTemplate(); } - // FIXME: What follows is a slightly less gross hack than what used to - // follow. - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(IIDecl)) { - if (FD->getDescribedFunctionTemplate()) { - TemplateResult = TemplateTy::make(FD); - return TNK_Function_template; + return 0; + } + + OverloadedFunctionDecl *Ovl = dyn_cast<OverloadedFunctionDecl>(D); + if (!Ovl) + return 0; + + for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), + FEnd = Ovl->function_end(); + F != FEnd; ++F) { + if (FunctionTemplateDecl *FuncTmpl = dyn_cast<FunctionTemplateDecl>(*F)) { + // We've found a function template. Determine whether there are + // any other function templates we need to bundle together in an + // OverloadedFunctionDecl + for (++F; F != FEnd; ++F) { + if (isa<FunctionTemplateDecl>(*F)) + break; } - } else if (OverloadedFunctionDecl *Ovl - = dyn_cast<OverloadedFunctionDecl>(IIDecl)) { - for (OverloadedFunctionDecl::function_iterator F = Ovl->function_begin(), - FEnd = Ovl->function_end(); - F != FEnd; ++F) { - if (isa<FunctionTemplateDecl>(*F)) { - TemplateResult = TemplateTy::make(Ovl); - return TNK_Function_template; + + if (F != FEnd) { + // Build an overloaded function decl containing only the + // function templates in Ovl. + OverloadedFunctionDecl *OvlTemplate + = OverloadedFunctionDecl::Create(Context, + Ovl->getDeclContext(), + Ovl->getDeclName()); + OvlTemplate->addOverload(FuncTmpl); + OvlTemplate->addOverload(*F); + for (++F; F != FEnd; ++F) { + if (isa<FunctionTemplateDecl>(*F)) + OvlTemplate->addOverload(*F); } + + return OvlTemplate; } + + return FuncTmpl; } + } + + return 0; +} - if (TNK != TNK_Non_template) { - if (SS && SS->isSet() && !SS->isInvalid()) { - NestedNameSpecifier *Qualifier - = static_cast<NestedNameSpecifier *>(SS->getScopeRep()); - TemplateResult - = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, - false, - Template)); - } else - TemplateResult = TemplateTy::make(TemplateName(Template)); +TemplateNameKind Sema::isTemplateName(Scope *S, + const IdentifierInfo &II, + SourceLocation IdLoc, + const CXXScopeSpec *SS, + TypeTy *ObjectTypePtr, + bool EnteringContext, + TemplateTy &TemplateResult) { + // Determine where to perform name lookup + DeclContext *LookupCtx = 0; + bool isDependent = false; + if (ObjectTypePtr) { + // This nested-name-specifier occurs in a member access expression, e.g., + // x->B::f, and we are looking into the type of the object. + assert((!SS || !SS->isSet()) && + "ObjectType and scope specifier cannot coexist"); + QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); + LookupCtx = computeDeclContext(ObjectType); + isDependent = ObjectType->isDependentType(); + } else if (SS && SS->isSet()) { + // This nested-name-specifier occurs after another nested-name-specifier, + // so long into the context associated with the prior nested-name-specifier. + + LookupCtx = computeDeclContext(*SS, EnteringContext); + isDependent = isDependentScopeSpecifier(*SS); + } + + LookupResult Found; + bool ObjectTypeSearchedInScope = false; + if (LookupCtx) { + // Perform "qualified" name lookup into the declaration context we + // computed, which is either the type of the base of a member access + // expression or the declaration context associated with a prior + // nested-name-specifier. + + // The declaration context must be complete. + if (!LookupCtx->isDependentContext() && RequireCompleteDeclContext(*SS)) + return TNK_Non_template; + + LookupQualifiedName(Found, LookupCtx, &II, LookupOrdinaryName); + + if (ObjectTypePtr && Found.getKind() == LookupResult::NotFound) { + // C++ [basic.lookup.classref]p1: + // In a class member access expression (5.2.5), if the . or -> token is + // immediately followed by an identifier followed by a <, the + // identifier must be looked up to determine whether the < is the + // beginning of a template argument list (14.2) or a less-than operator. + // The identifier is first looked up in the class of the object + // expression. If the identifier is not found, it is then looked up in + // the context of the entire postfix-expression and shall name a class + // or function template. + // + // FIXME: When we're instantiating a template, do we actually have to + // look in the scope of the template? Seems fishy... + LookupName(Found, S, &II, LookupOrdinaryName); + ObjectTypeSearchedInScope = true; } + } else if (isDependent) { + // We cannot look into a dependent object type or + return TNK_Non_template; + } else { + // Perform unqualified name lookup in the current scope. + LookupName(Found, S, &II, LookupOrdinaryName); } - return TNK; + + // FIXME: Cope with ambiguous name-lookup results. + assert(!Found.isAmbiguous() && + "Cannot handle template name-lookup ambiguities"); + + NamedDecl *Template + = isAcceptableTemplateName(Context, Found.getAsSingleDecl(Context)); + if (!Template) + return TNK_Non_template; + + if (ObjectTypePtr && !ObjectTypeSearchedInScope) { + // C++ [basic.lookup.classref]p1: + // [...] If the lookup in the class of the object expression finds a + // template, the name is also looked up in the context of the entire + // postfix-expression and [...] + // + LookupResult FoundOuter; + LookupName(FoundOuter, S, &II, LookupOrdinaryName); + // FIXME: Handle ambiguities in this lookup better + NamedDecl *OuterTemplate + = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context)); + + if (!OuterTemplate) { + // - if the name is not found, the name found in the class of the + // object expression is used, otherwise + } else if (!isa<ClassTemplateDecl>(OuterTemplate)) { + // - if the name is found in the context of the entire + // postfix-expression and does not name a class template, the name + // found in the class of the object expression is used, otherwise + } else { + // - if the name found is a class template, it must refer to the same + // entity as the one found in the class of the object expression, + // otherwise the program is ill-formed. + if (OuterTemplate->getCanonicalDecl() != Template->getCanonicalDecl()) { + Diag(IdLoc, diag::err_nested_name_member_ref_lookup_ambiguous) + << &II; + Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type) + << QualType::getFromOpaquePtr(ObjectTypePtr); + Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope); + + // Recover by taking the template that we found in the object + // expression's type. + } + } + } + + if (SS && SS->isSet() && !SS->isInvalid()) { + NestedNameSpecifier *Qualifier + = static_cast<NestedNameSpecifier *>(SS->getScopeRep()); + if (OverloadedFunctionDecl *Ovl + = dyn_cast<OverloadedFunctionDecl>(Template)) + TemplateResult + = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, + Ovl)); + else + TemplateResult + = TemplateTy::make(Context.getQualifiedTemplateName(Qualifier, false, + cast<TemplateDecl>(Template))); + } else if (OverloadedFunctionDecl *Ovl + = dyn_cast<OverloadedFunctionDecl>(Template)) { + TemplateResult = TemplateTy::make(TemplateName(Ovl)); + } else { + TemplateResult = TemplateTy::make( + TemplateName(cast<TemplateDecl>(Template))); + } + + if (isa<ClassTemplateDecl>(Template) || + isa<TemplateTemplateParmDecl>(Template)) + return TNK_Type_template; + + assert((isa<FunctionTemplateDecl>(Template) || + isa<OverloadedFunctionDecl>(Template)) && + "Unhandled template kind in Sema::isTemplateName"); + return TNK_Function_template; } /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining @@ -115,7 +250,7 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { // C++ [temp.local]p4: // A template-parameter shall not be redeclared within its // scope (including nested scopes). - Diag(Loc, diag::err_template_param_shadow) + Diag(Loc, diag::err_template_param_shadow) << cast<NamedDecl>(PrevDecl)->getDeclName(); Diag(PrevDecl->getLocation(), diag::note_template_param_here); return true; @@ -125,7 +260,7 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { /// the parameter D to reference the templated declaration and return a pointer /// to the template declaration. Otherwise, do nothing to D and return null. TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) { - if (TemplateDecl *Temp = dyn_cast<TemplateDecl>(D.getAs<Decl>())) { + if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D.getAs<Decl>())) { D = DeclPtrTy::make(Temp->getTemplatedDecl()); return Temp; } @@ -138,24 +273,24 @@ TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) { /// (otherwise, "class" was used), and KeyLoc is the location of the /// "class" or "typename" keyword. ParamName is the name of the /// parameter (NULL indicates an unnamed template parameter) and -/// ParamName is the location of the parameter name (if any). +/// ParamName is the location of the parameter name (if any). /// If the type parameter has a default argument, it will be added /// later via ActOnTypeParameterDefault. -Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, +Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, SourceLocation EllipsisLoc, SourceLocation KeyLoc, IdentifierInfo *ParamName, SourceLocation ParamNameLoc, unsigned Depth, unsigned Position) { - assert(S->isTemplateParamScope() && - "Template type parameter not in template parameter scope!"); + assert(S->isTemplateParamScope() && + "Template type parameter not in template parameter scope!"); bool Invalid = false; if (ParamName) { - NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName); + NamedDecl *PrevDecl = LookupSingleName(S, ParamName, LookupTagName); if (PrevDecl && PrevDecl->isTemplateParameter()) Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc, - PrevDecl); + PrevDecl); } SourceLocation Loc = ParamNameLoc; @@ -163,8 +298,8 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, Loc = KeyLoc; TemplateTypeParmDecl *Param - = TemplateTypeParmDecl::Create(Context, CurContext, Loc, - Depth, Position, ParamName, Typename, + = TemplateTypeParmDecl::Create(Context, CurContext, Loc, + Depth, Position, ParamName, Typename, Ellipsis); if (Invalid) Param->setInvalidDecl(); @@ -179,27 +314,28 @@ Sema::DeclPtrTy Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, } /// ActOnTypeParameterDefault - Adds a default argument (the type -/// Default) to the given template type parameter (TypeParam). -void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam, +/// Default) to the given template type parameter (TypeParam). +void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam, SourceLocation EqualLoc, - SourceLocation DefaultLoc, + SourceLocation DefaultLoc, TypeTy *DefaultT) { - TemplateTypeParmDecl *Parm + TemplateTypeParmDecl *Parm = cast<TemplateTypeParmDecl>(TypeParam.getAs<Decl>()); - QualType Default = QualType::getFromOpaquePtr(DefaultT); + // FIXME: Preserve type source info. + QualType Default = GetTypeFromParser(DefaultT); // C++0x [temp.param]p9: // A default template-argument may be specified for any kind of - // template-parameter that is not a template parameter pack. + // template-parameter that is not a template parameter pack. if (Parm->isParameterPack()) { Diag(DefaultLoc, diag::err_template_param_pack_default_arg); return; } - + // C++ [temp.param]p14: // A template-parameter shall not be used in its own default argument. // FIXME: Implement this check! Needs a recursive walk over the types. - + // Check the template argument itself. if (CheckTemplateArgument(Parm, Default, DefaultLoc)) { Parm->setInvalidDecl(); @@ -214,7 +350,7 @@ void Sema::ActOnTypeParameterDefault(DeclPtrTy TypeParam, /// /// \returns the (possibly-promoted) parameter type if valid; /// otherwise, produces a diagnostic and returns a NULL type. -QualType +QualType Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { // C++ [temp.param]p4: // @@ -223,11 +359,11 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { // // -- integral or enumeration type, if (T->isIntegralType() || T->isEnumeralType() || - // -- pointer to object or pointer to function, - (T->isPointerType() && - (T->getAsPointerType()->getPointeeType()->isObjectType() || - T->getAsPointerType()->getPointeeType()->isFunctionType())) || - // -- reference to object or reference to function, + // -- pointer to object or pointer to function, + (T->isPointerType() && + (T->getAs<PointerType>()->getPointeeType()->isObjectType() || + T->getAs<PointerType>()->getPointeeType()->isFunctionType())) || + // -- reference to object or reference to function, T->isReferenceType() || // -- pointer to member. T->isMemberPointerType() || @@ -258,9 +394,10 @@ Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { /// class Array") has been parsed. S is the current scope and D is /// the parsed declarator. Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, - unsigned Depth, + unsigned Depth, unsigned Position) { - QualType T = GetTypeForDeclarator(D, S); + DeclaratorInfo *DInfo = 0; + QualType T = GetTypeForDeclarator(D, S, &DInfo); assert(S->isTemplateParamScope() && "Non-type template parameter not in template parameter scope!"); @@ -268,7 +405,7 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, IdentifierInfo *ParamName = D.getIdentifier(); if (ParamName) { - NamedDecl *PrevDecl = LookupName(S, ParamName, LookupTagName); + NamedDecl *PrevDecl = LookupSingleName(S, ParamName, LookupTagName); if (PrevDecl && PrevDecl->isTemplateParameter()) Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); @@ -282,7 +419,7 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, NonTypeTemplateParmDecl *Param = NonTypeTemplateParmDecl::Create(Context, CurContext, D.getIdentifierLoc(), - Depth, Position, ParamName, T); + Depth, Position, ParamName, T, DInfo); if (Invalid) Param->setInvalidDecl(); @@ -299,14 +436,14 @@ Sema::DeclPtrTy Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, void Sema::ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParamD, SourceLocation EqualLoc, ExprArg DefaultE) { - NonTypeTemplateParmDecl *TemplateParm + NonTypeTemplateParmDecl *TemplateParm = cast<NonTypeTemplateParmDecl>(TemplateParamD.getAs<Decl>()); Expr *Default = static_cast<Expr *>(DefaultE.get()); - + // C++ [temp.param]p14: // A template-parameter shall not be used in its own default argument. // FIXME: Implement this check! Needs a recursive walk over the types. - + // Check the well-formedness of the default template argument. TemplateArgument Converted; if (CheckTemplateArgument(TemplateParm, TemplateParm->getType(), Default, @@ -328,8 +465,7 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S, IdentifierInfo *Name, SourceLocation NameLoc, unsigned Depth, - unsigned Position) -{ + unsigned Position) { assert(S->isTemplateParamScope() && "Template template parameter not in template parameter scope!"); @@ -363,12 +499,12 @@ Sema::DeclPtrTy Sema::ActOnTemplateTemplateParameter(Scope* S, void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD, SourceLocation EqualLoc, ExprArg DefaultE) { - TemplateTemplateParmDecl *TemplateParm + TemplateTemplateParmDecl *TemplateParm = cast<TemplateTemplateParmDecl>(TemplateParamD.getAs<Decl>()); // Since a template-template parameter's default argument is an // id-expression, it must be a DeclRefExpr. - DeclRefExpr *Default + DeclRefExpr *Default = cast<DeclRefExpr>(static_cast<Expr *>(DefaultE.get())); // C++ [temp.param]p14: @@ -377,12 +513,12 @@ void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD, // Check the well-formedness of the template argument. if (!isa<TemplateDecl>(Default->getDecl())) { - Diag(Default->getSourceRange().getBegin(), + Diag(Default->getSourceRange().getBegin(), diag::err_template_arg_must_be_template) << Default->getSourceRange(); TemplateParm->setInvalidDecl(); return; - } + } if (CheckTemplateArgument(TemplateParm, Default)) { TemplateParm->setInvalidDecl(); return; @@ -397,7 +533,7 @@ void Sema::ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParamD, Sema::TemplateParamsTy * Sema::ActOnTemplateParameterList(unsigned Depth, SourceLocation ExportLoc, - SourceLocation TemplateLoc, + SourceLocation TemplateLoc, SourceLocation LAngleLoc, DeclPtrTy *Params, unsigned NumParams, SourceLocation RAngleLoc) { @@ -405,31 +541,28 @@ Sema::ActOnTemplateParameterList(unsigned Depth, Diag(ExportLoc, diag::note_template_export_unsupported); return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, - (Decl**)Params, NumParams, RAngleLoc); + (NamedDecl**)Params, NumParams, + RAngleLoc); } Sema::DeclResult -Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, +Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, const CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, - MultiTemplateParamsArg TemplateParameterLists, + TemplateParameterList *TemplateParams, AccessSpecifier AS) { - assert(TemplateParameterLists.size() > 0 && "No template parameter lists?"); - assert(TK != TK_Reference && "Can only declare or define class templates"); + assert(TemplateParams && TemplateParams->size() > 0 && + "No template parameters"); + assert(TUK != TUK_Reference && "Can only declare or define class templates"); bool Invalid = false; // Check that we can declare a template here. - if (CheckTemplateDeclScope(S, TemplateParameterLists)) + if (CheckTemplateDeclScope(S, TemplateParams)) return true; - TagDecl::TagKind Kind; - switch (TagSpec) { - default: assert(0 && "Unknown tag type!"); - case DeclSpec::TST_struct: Kind = TagDecl::TK_struct; break; - case DeclSpec::TST_union: Kind = TagDecl::TK_union; break; - case DeclSpec::TST_class: Kind = TagDecl::TK_class; break; - } + TagDecl::TagKind Kind = TagDecl::getTagKindForTypeSpec(TagSpec); + assert(Kind != TagDecl::TK_enum && "can't build template of enumerated type"); // There is no such thing as an unnamed class template. if (!Name) { @@ -438,31 +571,73 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, } // Find any previous declaration with this name. - LookupResult Previous = LookupParsedName(S, &SS, Name, LookupOrdinaryName, - true); + DeclContext *SemanticContext; + LookupResult Previous; + if (SS.isNotEmpty() && !SS.isInvalid()) { + if (RequireCompleteDeclContext(SS)) + return true; + + SemanticContext = computeDeclContext(SS, true); + if (!SemanticContext) { + // FIXME: Produce a reasonable diagnostic here + return true; + } + + LookupQualifiedName(Previous, SemanticContext, Name, LookupOrdinaryName, + true); + } else { + SemanticContext = CurContext; + LookupName(Previous, S, Name, LookupOrdinaryName, true); + } + assert(!Previous.isAmbiguous() && "Ambiguity in class template redecl?"); NamedDecl *PrevDecl = 0; if (Previous.begin() != Previous.end()) PrevDecl = *Previous.begin(); - if (PrevDecl && !isDeclInScope(PrevDecl, CurContext, S)) + if (PrevDecl && TUK == TUK_Friend) { + // C++ [namespace.memdef]p3: + // [...] When looking for a prior declaration of a class or a function + // declared as a friend, and when the name of the friend class or + // function is neither a qualified name nor a template-id, scopes outside + // the innermost enclosing namespace scope are not considered. + DeclContext *OutermostContext = CurContext; + while (!OutermostContext->isFileContext()) + OutermostContext = OutermostContext->getLookupParent(); + + if (OutermostContext->Equals(PrevDecl->getDeclContext()) || + OutermostContext->Encloses(PrevDecl->getDeclContext())) { + SemanticContext = PrevDecl->getDeclContext(); + } else { + // Declarations in outer scopes don't matter. However, the outermost + // context we computed is the semntic context for our new + // declaration. + PrevDecl = 0; + SemanticContext = OutermostContext; + } + } else if (PrevDecl && !isDeclInScope(PrevDecl, SemanticContext, S)) PrevDecl = 0; - - DeclContext *SemanticContext = CurContext; - if (SS.isNotEmpty() && !SS.isInvalid()) { - SemanticContext = computeDeclContext(SS); - - // FIXME: need to match up several levels of template parameter lists here. - } - - // FIXME: member templates! - TemplateParameterList *TemplateParams - = static_cast<TemplateParameterList *>(*TemplateParameterLists.release()); // If there is a previous declaration with the same name, check // whether this is a valid redeclaration. - ClassTemplateDecl *PrevClassTemplate + ClassTemplateDecl *PrevClassTemplate = dyn_cast_or_null<ClassTemplateDecl>(PrevDecl); + + // We may have found the injected-class-name of a class template, + // class template partial specialization, or class template specialization. + // In these cases, grab the template that is being defined or specialized. + if (!PrevClassTemplate && PrevDecl && isa<CXXRecordDecl>(PrevDecl) && + cast<CXXRecordDecl>(PrevDecl)->isInjectedClassName()) { + PrevDecl = cast<CXXRecordDecl>(PrevDecl->getDeclContext()); + PrevClassTemplate + = cast<CXXRecordDecl>(PrevDecl)->getDescribedClassTemplate(); + if (!PrevClassTemplate && isa<ClassTemplateSpecializationDecl>(PrevDecl)) { + PrevClassTemplate + = cast<ClassTemplateSpecializationDecl>(PrevDecl) + ->getSpecializedTemplate(); + } + } + if (PrevClassTemplate) { // Ensure that the template parameter lists are compatible. if (!TemplateParameterListsAreEqual(TemplateParams, @@ -477,16 +652,16 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, // template declaration (7.1.5.3). RecordDecl *PrevRecordDecl = PrevClassTemplate->getTemplatedDecl(); if (!isAcceptableTagRedeclaration(PrevRecordDecl, Kind, KWLoc, *Name)) { - Diag(KWLoc, diag::err_use_with_wrong_tag) + Diag(KWLoc, diag::err_use_with_wrong_tag) << Name - << CodeModificationHint::CreateReplacement(KWLoc, + << CodeModificationHint::CreateReplacement(KWLoc, PrevRecordDecl->getKindName()); Diag(PrevRecordDecl->getLocation(), diag::note_previous_use); Kind = PrevRecordDecl->getTagKind(); } // Check for redefinition of this class template. - if (TK == TK_Definition) { + if (TUK == TUK_Definition) { if (TagDecl *Def = PrevRecordDecl->getDefinition(Context)) { Diag(NameLoc, diag::err_redefinition) << Name; Diag(Def->getLocation(), diag::note_previous_definition); @@ -517,13 +692,13 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, if (CheckTemplateParameterList(TemplateParams, PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0)) Invalid = true; - + // FIXME: If we had a scope specifier, we better have a previous template // declaration! - CXXRecordDecl *NewClass = - CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, - PrevClassTemplate? + CXXRecordDecl *NewClass = + CXXRecordDecl::Create(Context, Kind, SemanticContext, NameLoc, Name, KWLoc, + PrevClassTemplate? PrevClassTemplate->getTemplatedDecl() : 0, /*DelayTypeCreation=*/true); @@ -534,27 +709,60 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, NewClass->setDescribedClassTemplate(NewTemplate); // Build the type for the class template declaration now. - QualType T = - Context.getTypeDeclType(NewClass, - PrevClassTemplate? - PrevClassTemplate->getTemplatedDecl() : 0); + QualType T = + Context.getTypeDeclType(NewClass, + PrevClassTemplate? + PrevClassTemplate->getTemplatedDecl() : 0); assert(T->isDependentType() && "Class template type is not dependent?"); (void)T; - // Set the access specifier. - SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS); + // If we are providing an explicit specialization of a member that is a + // class template, make a note of that. + if (PrevClassTemplate && + PrevClassTemplate->getInstantiatedFromMemberTemplate()) + PrevClassTemplate->setMemberSpecialization(); + // Set the access specifier. + if (!Invalid && TUK != TUK_Friend) + SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS); + // Set the lexical context of these templates NewClass->setLexicalDeclContext(CurContext); NewTemplate->setLexicalDeclContext(CurContext); - if (TK == TK_Definition) + if (TUK == TUK_Definition) NewClass->startDefinition(); if (Attr) ProcessDeclAttributeList(S, NewClass, Attr); - PushOnScopeChains(NewTemplate, S); + if (TUK != TUK_Friend) + PushOnScopeChains(NewTemplate, S); + else { + if (PrevClassTemplate && PrevClassTemplate->getAccess() != AS_none) { + NewTemplate->setAccess(PrevClassTemplate->getAccess()); + NewClass->setAccess(PrevClassTemplate->getAccess()); + } + + NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */ + PrevClassTemplate != NULL); + + // Friend templates are visible in fairly strange ways. + if (!CurContext->isDependentContext()) { + DeclContext *DC = SemanticContext->getLookupContext(); + DC->makeDeclVisibleInContext(NewTemplate, /* Recoverable = */ false); + if (Scope *EnclosingScope = getScopeForDeclContext(S, DC)) + PushOnScopeChains(NewTemplate, EnclosingScope, + /* AddToContext = */ false); + } + + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, + NewClass->getLocation(), + NewTemplate, + /*FIXME:*/NewClass->getLocation()); + Friend->setAccess(AS_public); + CurContext->addDecl(Friend); + } if (Invalid) { NewTemplate->setInvalidDecl(); @@ -585,7 +793,7 @@ Sema::ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, TemplateParameterList *OldParams) { bool Invalid = false; - + // C++ [temp.param]p10: // The set of default template-arguments available for use with a // template declaration or definition is obtained by merging the @@ -618,7 +826,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // If a template parameter of a class template is a template parameter pack, // it must be the last template parameter. if (SawParameterPack) { - Diag(ParameterPackLoc, + Diag(ParameterPackLoc, diag::err_template_param_pack_must_be_last_template_parameter); Invalid = true; } @@ -626,15 +834,15 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // Merge default arguments for template type parameters. if (TemplateTypeParmDecl *NewTypeParm = dyn_cast<TemplateTypeParmDecl>(*NewParam)) { - TemplateTypeParmDecl *OldTypeParm + TemplateTypeParmDecl *OldTypeParm = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0; - + if (NewTypeParm->isParameterPack()) { assert(!NewTypeParm->hasDefaultArgument() && "Parameter packs can't have a default argument!"); SawParameterPack = true; ParameterPackLoc = NewTypeParm->getLocation(); - } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() && + } else if (OldTypeParm && OldTypeParm->hasDefaultArgument() && NewTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewTypeParm->getDefaultArgumentLoc(); @@ -654,13 +862,12 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, PreviousDefaultArgLoc = NewTypeParm->getDefaultArgumentLoc(); } else if (SawDefaultArgument) MissingDefaultArg = true; - } - // Merge default arguments for non-type template parameters - else if (NonTypeTemplateParmDecl *NewNonTypeParm + } else if (NonTypeTemplateParmDecl *NewNonTypeParm = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) { + // Merge default arguments for non-type template parameters NonTypeTemplateParmDecl *OldNonTypeParm = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0; - if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && + if (OldNonTypeParm && OldNonTypeParm->hasDefaultArgument() && NewNonTypeParm->hasDefaultArgument()) { OldDefaultLoc = OldNonTypeParm->getDefaultArgumentLoc(); NewDefaultLoc = NewNonTypeParm->getDefaultArgumentLoc(); @@ -681,15 +888,14 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, SawDefaultArgument = true; PreviousDefaultArgLoc = NewNonTypeParm->getDefaultArgumentLoc(); } else if (SawDefaultArgument) - MissingDefaultArg = true; - } + MissingDefaultArg = true; + } else { // Merge default arguments for template template parameters - else { TemplateTemplateParmDecl *NewTemplateParm = cast<TemplateTemplateParmDecl>(*NewParam); TemplateTemplateParmDecl *OldTemplateParm = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0; - if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && + if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && NewTemplateParm->hasDefaultArgument()) { OldDefaultLoc = OldTemplateParm->getDefaultArgumentLoc(); NewDefaultLoc = NewTemplateParm->getDefaultArgumentLoc(); @@ -709,7 +915,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, SawDefaultArgument = true; PreviousDefaultArgLoc = NewTemplateParm->getDefaultArgumentLoc(); } else if (SawDefaultArgument) - MissingDefaultArg = true; + MissingDefaultArg = true; } if (RedundantDefaultArg) { @@ -724,7 +930,7 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, // If a template-parameter has a default template-argument, // all subsequent template-parameters shall have a default // template-argument supplied. - Diag((*NewParam)->getLocation(), + Diag((*NewParam)->getLocation(), diag::err_template_param_default_arg_missing); Diag(PreviousDefaultArgLoc, diag::note_template_param_prev_default_arg); Invalid = true; @@ -739,11 +945,157 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, return Invalid; } +/// \brief Match the given template parameter lists to the given scope +/// specifier, returning the template parameter list that applies to the +/// name. +/// +/// \param DeclStartLoc the start of the declaration that has a scope +/// specifier or a template parameter list. +/// +/// \param SS the scope specifier that will be matched to the given template +/// parameter lists. This scope specifier precedes a qualified name that is +/// being declared. +/// +/// \param ParamLists the template parameter lists, from the outermost to the +/// innermost template parameter lists. +/// +/// \param NumParamLists the number of template parameter lists in ParamLists. +/// +/// \param IsExplicitSpecialization will be set true if the entity being +/// declared is an explicit specialization, false otherwise. +/// +/// \returns the template parameter list, if any, that corresponds to the +/// name that is preceded by the scope specifier @p SS. This template +/// parameter list may be have template parameters (if we're declaring a +/// template) or may have no template parameters (if we're declaring a +/// template specialization), or may be NULL (if we were's declaring isn't +/// itself a template). +TemplateParameterList * +Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, + const CXXScopeSpec &SS, + TemplateParameterList **ParamLists, + unsigned NumParamLists, + bool &IsExplicitSpecialization) { + IsExplicitSpecialization = false; + + // Find the template-ids that occur within the nested-name-specifier. These + // template-ids will match up with the template parameter lists. + llvm::SmallVector<const TemplateSpecializationType *, 4> + TemplateIdsInSpecifier; + for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); + NNS; NNS = NNS->getPrefix()) { + if (const TemplateSpecializationType *SpecType + = dyn_cast_or_null<TemplateSpecializationType>(NNS->getAsType())) { + TemplateDecl *Template = SpecType->getTemplateName().getAsTemplateDecl(); + if (!Template) + continue; // FIXME: should this be an error? probably... + + if (const RecordType *Record = SpecType->getAs<RecordType>()) { + ClassTemplateSpecializationDecl *SpecDecl + = cast<ClassTemplateSpecializationDecl>(Record->getDecl()); + // If the nested name specifier refers to an explicit specialization, + // we don't need a template<> header. + // FIXME: revisit this approach once we cope with specializations + // properly. + if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) + continue; + } + + TemplateIdsInSpecifier.push_back(SpecType); + } + } + + // Reverse the list of template-ids in the scope specifier, so that we can + // more easily match up the template-ids and the template parameter lists. + std::reverse(TemplateIdsInSpecifier.begin(), TemplateIdsInSpecifier.end()); + + SourceLocation FirstTemplateLoc = DeclStartLoc; + if (NumParamLists) + FirstTemplateLoc = ParamLists[0]->getTemplateLoc(); + + // Match the template-ids found in the specifier to the template parameter + // lists. + unsigned Idx = 0; + for (unsigned NumTemplateIds = TemplateIdsInSpecifier.size(); + Idx != NumTemplateIds; ++Idx) { + QualType TemplateId = QualType(TemplateIdsInSpecifier[Idx], 0); + bool DependentTemplateId = TemplateId->isDependentType(); + if (Idx >= NumParamLists) { + // We have a template-id without a corresponding template parameter + // list. + if (DependentTemplateId) { + // FIXME: the location information here isn't great. + Diag(SS.getRange().getBegin(), + diag::err_template_spec_needs_template_parameters) + << TemplateId + << SS.getRange(); + } else { + Diag(SS.getRange().getBegin(), diag::err_template_spec_needs_header) + << SS.getRange() + << CodeModificationHint::CreateInsertion(FirstTemplateLoc, + "template<> "); + IsExplicitSpecialization = true; + } + return 0; + } + + // Check the template parameter list against its corresponding template-id. + if (DependentTemplateId) { + TemplateDecl *Template + = TemplateIdsInSpecifier[Idx]->getTemplateName().getAsTemplateDecl(); + + if (ClassTemplateDecl *ClassTemplate + = dyn_cast<ClassTemplateDecl>(Template)) { + TemplateParameterList *ExpectedTemplateParams = 0; + // Is this template-id naming the primary template? + if (Context.hasSameType(TemplateId, + ClassTemplate->getInjectedClassNameType(Context))) + ExpectedTemplateParams = ClassTemplate->getTemplateParameters(); + // ... or a partial specialization? + else if (ClassTemplatePartialSpecializationDecl *PartialSpec + = ClassTemplate->findPartialSpecialization(TemplateId)) + ExpectedTemplateParams = PartialSpec->getTemplateParameters(); + + if (ExpectedTemplateParams) + TemplateParameterListsAreEqual(ParamLists[Idx], + ExpectedTemplateParams, + true); + } + } else if (ParamLists[Idx]->size() > 0) + Diag(ParamLists[Idx]->getTemplateLoc(), + diag::err_template_param_list_matches_nontemplate) + << TemplateId + << ParamLists[Idx]->getSourceRange(); + else + IsExplicitSpecialization = true; + } + + // If there were at least as many template-ids as there were template + // parameter lists, then there are no template parameter lists remaining for + // the declaration itself. + if (Idx >= NumParamLists) + return 0; + + // If there were too many template parameter lists, complain about that now. + if (Idx != NumParamLists - 1) { + while (Idx < NumParamLists - 1) { + Diag(ParamLists[Idx]->getTemplateLoc(), + diag::err_template_spec_extra_headers) + << SourceRange(ParamLists[Idx]->getTemplateLoc(), + ParamLists[Idx]->getRAngleLoc()); + ++Idx; + } + } + + // Return the last template parameter list, which corresponds to the + // entity being declared. + return ParamLists[NumParamLists - 1]; +} + /// \brief Translates template arguments as provided by the parser /// into template arguments used by semantic analysis. -static void -translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - SourceLocation *TemplateArgLocs, +void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, + SourceLocation *TemplateArgLocs, llvm::SmallVector<TemplateArgument, 16> &TemplateArgs) { TemplateArgs.reserve(TemplateArgsIn.size()); @@ -752,72 +1104,12 @@ translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, for (unsigned Arg = 0, Last = TemplateArgsIn.size(); Arg != Last; ++Arg) { TemplateArgs.push_back( ArgIsType[Arg]? TemplateArgument(TemplateArgLocs[Arg], - QualType::getFromOpaquePtr(Args[Arg])) + //FIXME: Preserve type source info. + Sema::GetTypeFromParser(Args[Arg])) : TemplateArgument(reinterpret_cast<Expr *>(Args[Arg]))); } } -/// \brief Build a canonical version of a template argument list. -/// -/// This function builds a canonical version of the given template -/// argument list, where each of the template arguments has been -/// converted into its canonical form. This routine is typically used -/// to canonicalize a template argument list when the template name -/// itself is dependent. When the template name refers to an actual -/// template declaration, Sema::CheckTemplateArgumentList should be -/// used to check and canonicalize the template arguments. -/// -/// \param TemplateArgs The incoming template arguments. -/// -/// \param NumTemplateArgs The number of template arguments in \p -/// TemplateArgs. -/// -/// \param Canonical A vector to be filled with the canonical versions -/// of the template arguments. -/// -/// \param Context The ASTContext in which the template arguments live. -static void CanonicalizeTemplateArguments(const TemplateArgument *TemplateArgs, - unsigned NumTemplateArgs, - llvm::SmallVectorImpl<TemplateArgument> &Canonical, - ASTContext &Context) { - Canonical.reserve(NumTemplateArgs); - for (unsigned Idx = 0; Idx < NumTemplateArgs; ++Idx) { - switch (TemplateArgs[Idx].getKind()) { - case TemplateArgument::Null: - assert(false && "Should never see a NULL template argument here"); - break; - - case TemplateArgument::Expression: - // FIXME: Build canonical expression (!) - Canonical.push_back(TemplateArgs[Idx]); - break; - - case TemplateArgument::Declaration: - Canonical.push_back( - TemplateArgument(SourceLocation(), - Context.getCanonicalDecl(TemplateArgs[Idx].getAsDecl()))); - break; - - case TemplateArgument::Integral: - Canonical.push_back(TemplateArgument(SourceLocation(), - *TemplateArgs[Idx].getAsIntegral(), - TemplateArgs[Idx].getIntegralType())); - break; - - case TemplateArgument::Type: { - QualType CanonType - = Context.getCanonicalType(TemplateArgs[Idx].getAsType()); - Canonical.push_back(TemplateArgument(SourceLocation(), CanonType)); - break; - } - - case TemplateArgument::Pack: - assert(0 && "FIXME: Implement!"); - break; - } - } -} - QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, SourceLocation LAngleLoc, @@ -828,34 +1120,20 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (!Template) { // The template name does not resolve to a template, so we just // build a dependent template-id type. - - // Canonicalize the template arguments to build the canonical - // template-id type. - llvm::SmallVector<TemplateArgument, 16> CanonicalTemplateArgs; - CanonicalizeTemplateArguments(TemplateArgs, NumTemplateArgs, - CanonicalTemplateArgs, Context); - - TemplateName CanonName = Context.getCanonicalTemplateName(Name); - QualType CanonType - = Context.getTemplateSpecializationType(CanonName, - &CanonicalTemplateArgs[0], - CanonicalTemplateArgs.size()); - - // Build the dependent template-id type. return Context.getTemplateSpecializationType(Name, TemplateArgs, - NumTemplateArgs, CanonType); + NumTemplateArgs); } // Check that the template argument list is well-formed for this // template. TemplateArgumentListBuilder Converted(Template->getTemplateParameters(), NumTemplateArgs); - if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, + if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, TemplateArgs, NumTemplateArgs, RAngleLoc, false, Converted)) return QualType(); - assert((Converted.structuredSize() == + assert((Converted.structuredSize() == Template->getTemplateParameters()->size()) && "Converted template argument list is too short!"); @@ -872,17 +1150,24 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // // template<typename T, typename U = T> struct A; TemplateName CanonName = Context.getCanonicalTemplateName(Name); - CanonType = Context.getTemplateSpecializationType(CanonName, + CanonType = Context.getTemplateSpecializationType(CanonName, Converted.getFlatArguments(), Converted.flatSize()); - } else if (ClassTemplateDecl *ClassTemplate + + // FIXME: CanonType is not actually the canonical type, and unfortunately + // it is a TemplateTypeSpecializationType that we will never use again. + // In the future, we need to teach getTemplateSpecializationType to only + // build the canonical type and return that to us. + CanonType = Context.getCanonicalType(CanonType); + } else if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(Template)) { // Find the class template specialization declaration that // corresponds to these arguments. llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationDecl::Profile(ID, + ClassTemplateSpecializationDecl::Profile(ID, Converted.getFlatArguments(), - Converted.flatSize()); + Converted.flatSize(), + Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *Decl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); @@ -890,9 +1175,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // This is the first time we have referenced this class template // specialization. Create the canonical declaration and add it to // the set of specializations. - Decl = ClassTemplateSpecializationDecl::Create(Context, + Decl = ClassTemplateSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), - TemplateLoc, + ClassTemplate->getLocation(), ClassTemplate, Converted, 0); ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos); @@ -901,17 +1186,18 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, CanonType = Context.getTypeDeclType(Decl); } - + // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. + //FIXME: Preserve type source info. return Context.getTemplateSpecializationType(Name, TemplateArgs, NumTemplateArgs, CanonType); } Action::TypeResult Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc) { @@ -933,6 +1219,38 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, return Result.getAsOpaquePtr(); } +Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult, + TagUseKind TUK, + DeclSpec::TST TagSpec, + SourceLocation TagLoc) { + if (TypeResult.isInvalid()) + return Sema::TypeResult(); + + QualType Type = QualType::getFromOpaquePtr(TypeResult.get()); + + // Verify the tag specifier. + TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec); + + if (const RecordType *RT = Type->getAs<RecordType>()) { + RecordDecl *D = RT->getDecl(); + + IdentifierInfo *Id = D->getIdentifier(); + assert(Id && "templated class must have an identifier"); + + if (!isAcceptableTagRedeclaration(D, TagKind, TagLoc, *Id)) { + Diag(TagLoc, diag::err_use_with_wrong_tag) + << Type + << CodeModificationHint::CreateReplacement(SourceRange(TagLoc), + D->getKindName()); + Diag(D->getLocation(), diag::note_previous_use); + } + } + + QualType ElabType = Context.getElaboratedType(Type, TagKind); + + return ElabType.getAsOpaquePtr(); +} + Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template, SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, @@ -941,14 +1259,14 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template, SourceLocation RAngleLoc) { // FIXME: Can we do any checking at this point? I guess we could check the // template arguments that we have against the template name, if the template - // name refers to a single template. That's not a terribly common case, + // name refers to a single template. That's not a terribly common case, // though. - return Owned(TemplateIdRefExpr::Create(Context, + return Owned(TemplateIdRefExpr::Create(Context, /*FIXME: New type?*/Context.OverloadTy, /*FIXME: Necessary?*/0, /*FIXME: Necessary?*/SourceRange(), Template, TemplateNameLoc, LAngleLoc, - TemplateArgs, + TemplateArgs, NumTemplateArgs, RAngleLoc)); } @@ -959,16 +1277,52 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD, SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc) { TemplateName Template = TemplateD.getAsVal<TemplateName>(); - + // Translate the parser's template argument list in our AST format. llvm::SmallVector<TemplateArgument, 16> TemplateArgs; translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); - + TemplateArgsIn.release(); + return BuildTemplateIdExpr(Template, TemplateNameLoc, LAngleLoc, TemplateArgs.data(), TemplateArgs.size(), RAngleLoc); } +Sema::OwningExprResult +Sema::ActOnMemberTemplateIdReferenceExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + const CXXScopeSpec &SS, + TemplateTy TemplateD, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc) { + TemplateName Template = TemplateD.getAsVal<TemplateName>(); + + // FIXME: We're going to end up looking up the template based on its name, + // twice! + DeclarationName Name; + if (TemplateDecl *ActualTemplate = Template.getAsTemplateDecl()) + Name = ActualTemplate->getDeclName(); + else if (OverloadedFunctionDecl *Ovl = Template.getAsOverloadedFunctionDecl()) + Name = Ovl->getDeclName(); + else + Name = Template.getAsDependentTemplateName()->getName(); + + // Translate the parser's template argument list in our AST format. + llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + TemplateArgsIn.release(); + + // Do we have the save the actual template name? We might need it... + return BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, TemplateNameLoc, + Name, true, LAngleLoc, + TemplateArgs.data(), TemplateArgs.size(), + RAngleLoc, DeclPtrTy(), &SS); +} + /// \brief Form a dependent template name. /// /// This action forms a dependent template name given the template @@ -976,20 +1330,15 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD, /// example, given "MetaFun::template apply", the scope specifier \p /// SS will be "MetaFun::", \p TemplateKWLoc contains the location /// of the "template" keyword, and "apply" is the \p Name. -Sema::TemplateTy +Sema::TemplateTy Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, const IdentifierInfo &Name, SourceLocation NameLoc, - const CXXScopeSpec &SS) { - if (!SS.isSet() || SS.isInvalid()) - return TemplateTy(); - - NestedNameSpecifier *Qualifier - = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - - // FIXME: member of the current instantiation - - if (!Qualifier->isDependent()) { + const CXXScopeSpec &SS, + TypeTy *ObjectType) { + if ((ObjectType && + computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) || + (SS.isSet() && computeDeclContext(SS, false))) { // C++0x [temp.names]p5: // If a name prefixed by the keyword template is not the name of // a template, the program is ill-formed. [Note: the keyword @@ -1007,7 +1356,8 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, // "template" keyword is now permitted). We follow the C++0x // rules, even in C++03 mode, retroactively applying the DR. TemplateTy Template; - TemplateNameKind TNK = isTemplateName(Name, 0, Template, &SS); + TemplateNameKind TNK = isTemplateName(0, Name, NameLoc, &SS, ObjectType, + false, Template); if (TNK == TNK_Non_template) { Diag(NameLoc, diag::err_template_kw_refers_to_non_template) << &Name; @@ -1017,10 +1367,12 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, return Template; } + NestedNameSpecifier *Qualifier + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); return TemplateTy::make(Context.getDependentTemplateName(Qualifier, &Name)); } -bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, +bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, const TemplateArgument &Arg, TemplateArgumentListBuilder &Converted) { // Check template type parameter. @@ -1033,13 +1385,13 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, // is not a type. Diag(Arg.getLocation(), diag::err_template_arg_must_be_type); Diag(Param->getLocation(), diag::note_template_param_here); - + return true; - } + } if (CheckTemplateArgument(Param, Arg.getAsType(), Arg.getLocation())) return true; - + // Add the converted template type argument. Converted.Append( TemplateArgument(Arg.getLocation(), @@ -1062,9 +1414,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, unsigned NumArgs = NumTemplateArgs; bool Invalid = false; - bool HasParameterPack = + bool HasParameterPack = NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack(); - + if ((NumArgs > NumParams && !HasParameterPack) || (NumArgs < Params->getMinRequiredArguments() && !PartialTemplateArgs)) { @@ -1084,8 +1436,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, << Params->getSourceRange(); Invalid = true; } - - // C++ [temp.arg]p1: + + // 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 // corresponding parameter declared by the template in its @@ -1096,7 +1448,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, Param != ParamEnd; ++Param, ++ArgIdx) { if (ArgIdx > NumArgs && PartialTemplateArgs) break; - + // Decode the template argument TemplateArgument Arg; if (ArgIdx >= NumArgs) { @@ -1109,7 +1461,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, Converted.EndPack(); break; } - + if (!TTP->hasDefaultArgument()) break; @@ -1118,49 +1470,51 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // If the argument type is dependent, instantiate it now based // on the previously-computed template arguments. if (ArgType->isDependentType()) { - InstantiatingTemplate Inst(*this, TemplateLoc, + InstantiatingTemplate Inst(*this, TemplateLoc, Template, Converted.getFlatArguments(), Converted.flatSize(), SourceRange(TemplateLoc, RAngleLoc)); TemplateArgumentList TemplateArgs(Context, Converted, /*TakeArgs=*/false); - ArgType = InstantiateType(ArgType, TemplateArgs, - TTP->getDefaultArgumentLoc(), - TTP->getDeclName()); + ArgType = SubstType(ArgType, + MultiLevelTemplateArgumentList(TemplateArgs), + TTP->getDefaultArgumentLoc(), + TTP->getDeclName()); } if (ArgType.isNull()) return true; Arg = TemplateArgument(TTP->getLocation(), ArgType); - } else if (NonTypeTemplateParmDecl *NTTP + } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { if (!NTTP->hasDefaultArgument()) break; - InstantiatingTemplate Inst(*this, TemplateLoc, + InstantiatingTemplate Inst(*this, TemplateLoc, Template, Converted.getFlatArguments(), Converted.flatSize(), SourceRange(TemplateLoc, RAngleLoc)); - + TemplateArgumentList TemplateArgs(Context, Converted, /*TakeArgs=*/false); - Sema::OwningExprResult E = InstantiateExpr(NTTP->getDefaultArgument(), - TemplateArgs); + Sema::OwningExprResult E + = SubstExpr(NTTP->getDefaultArgument(), + MultiLevelTemplateArgumentList(TemplateArgs)); if (E.isInvalid()) return true; - + Arg = TemplateArgument(E.takeAs<Expr>()); } else { - TemplateTemplateParmDecl *TempParm - = cast<TemplateTemplateParmDecl>(*Param); + TemplateTemplateParmDecl *TempParm + = cast<TemplateTemplateParmDecl>(*Param); if (!TempParm->hasDefaultArgument()) break; - // FIXME: Instantiate default argument + // FIXME: Subst default argument Arg = TemplateArgument(TempParm->getDefaultArgument()); } } else { @@ -1177,35 +1531,36 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted)) Invalid = true; } - + Converted.EndPack(); } else { if (CheckTemplateTypeArgument(TTP, Arg, Converted)) Invalid = true; } - } else if (NonTypeTemplateParmDecl *NTTP + } else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*Param)) { // Check non-type template parameters. - // Instantiate the type of the non-type template parameter with - // the template arguments we've seen thus far. + // Do substitution on the type of the non-type template parameter + // with the template arguments we've seen thus far. QualType NTTPType = NTTP->getType(); if (NTTPType->isDependentType()) { - // Instantiate the type of the non-type template parameter. - InstantiatingTemplate Inst(*this, TemplateLoc, + // Do substitution on the type of the non-type template parameter. + InstantiatingTemplate Inst(*this, TemplateLoc, Template, Converted.getFlatArguments(), Converted.flatSize(), SourceRange(TemplateLoc, RAngleLoc)); TemplateArgumentList TemplateArgs(Context, Converted, /*TakeArgs=*/false); - NTTPType = InstantiateType(NTTPType, TemplateArgs, - NTTP->getLocation(), - NTTP->getDeclName()); + NTTPType = SubstType(NTTPType, + MultiLevelTemplateArgumentList(TemplateArgs), + NTTP->getLocation(), + NTTP->getDeclName()); // If that worked, check the non-type template parameter type // for validity. if (!NTTPType.isNull()) - NTTPType = CheckNonTypeTemplateParameterType(NTTPType, + NTTPType = CheckNonTypeTemplateParameterType(NTTPType, NTTP->getLocation()); if (NTTPType.isNull()) { Invalid = true; @@ -1217,7 +1572,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, case TemplateArgument::Null: assert(false && "Should never see a NULL template argument here"); break; - + case TemplateArgument::Expression: { Expr *E = Arg.getAsExpr(); TemplateArgument Result; @@ -1238,7 +1593,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, case TemplateArgument::Type: // We have a non-type template parameter but the template // argument is a type. - + // C++ [temp.arg]p2: // In a template-argument, an ambiguity between a type-id and // an expression is resolved to a type-id, regardless of the @@ -1254,37 +1609,37 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, Diag((*Param)->getLocation(), diag::note_template_param_here); Invalid = true; break; - + case TemplateArgument::Pack: assert(0 && "FIXME: Implement!"); break; } - } else { + } else { // Check template template parameters. - TemplateTemplateParmDecl *TempParm + TemplateTemplateParmDecl *TempParm = cast<TemplateTemplateParmDecl>(*Param); - + switch (Arg.getKind()) { case TemplateArgument::Null: assert(false && "Should never see a NULL template argument here"); break; - + case TemplateArgument::Expression: { Expr *ArgExpr = Arg.getAsExpr(); if (ArgExpr && isa<DeclRefExpr>(ArgExpr) && isa<TemplateDecl>(cast<DeclRefExpr>(ArgExpr)->getDecl())) { if (CheckTemplateArgument(TempParm, cast<DeclRefExpr>(ArgExpr))) Invalid = true; - + // Add the converted template argument. - Decl *D - = Context.getCanonicalDecl(cast<DeclRefExpr>(ArgExpr)->getDecl()); + Decl *D + = cast<DeclRefExpr>(ArgExpr)->getDecl()->getCanonicalDecl(); Converted.Append(TemplateArgument(Arg.getLocation(), D)); continue; } } // fall through - + case TemplateArgument::Type: { // We have a template template parameter but the template // argument does not refer to a template. @@ -1298,11 +1653,11 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // it to the list of converted arguments. Converted.Append(Arg); break; - + case TemplateArgument::Integral: assert(false && "Integral argument with template template parameter"); break; - + case TemplateArgument::Pack: assert(0 && "FIXME: Implement!"); break; @@ -1318,7 +1673,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, /// /// This routine implements the semantics of C++ [temp.arg.type]. It /// returns true if an error occurred, and false otherwise. -bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, +bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, QualType Arg, SourceLocation ArgLoc) { // C++ [temp.arg.type]p2: // A local type, a type with no linkage, an unnamed type or a type @@ -1327,14 +1682,14 @@ bool Sema::CheckTemplateArgument(TemplateTypeParmDecl *Param, // // FIXME: Perform the recursive and no-linkage type checks. const TagType *Tag = 0; - if (const EnumType *EnumT = Arg->getAsEnumType()) + if (const EnumType *EnumT = Arg->getAs<EnumType>()) Tag = EnumT; - else if (const RecordType *RecordT = Arg->getAsRecordType()) + else if (const RecordType *RecordT = Arg->getAs<RecordType>()) Tag = RecordT; if (Tag && Tag->getDecl()->getDeclContext()->isFunctionOrMethod()) return Diag(ArgLoc, diag::err_template_arg_local_type) << QualType(Tag, 0); - else if (Tag && !Tag->getDecl()->getDeclName() && + else if (Tag && !Tag->getDecl()->getDeclName() && !Tag->getDecl()->getTypedefForAnonDecl()) { Diag(ArgLoc, diag::err_template_arg_unnamed_type); Diag(Tag->getDecl()->getLocation(), diag::note_template_unnamed_type_here); @@ -1359,7 +1714,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, return false; // C++ [temp.arg.nontype]p1: - // + // // A template-argument for a non-type, non-template // template-parameter shall be one of: [...] // @@ -1370,11 +1725,11 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, // the name refers to a function or array, or if the // corresponding template-parameter is a reference; or DeclRefExpr *DRE = 0; - + // Ignore (and complain about) any excess parentheses. while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_extra_parens) << Arg->getSourceRange(); Invalid = true; @@ -1390,7 +1745,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, DRE = dyn_cast<DeclRefExpr>(Arg); if (!DRE || !isa<ValueDecl>(DRE->getDecl())) - return Diag(Arg->getSourceRange().getBegin(), + return Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_object_or_func_form) << Arg->getSourceRange(); @@ -1402,14 +1757,14 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, // Cannot refer to non-static member functions if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(DRE->getDecl())) if (!Method->isStatic()) - return Diag(Arg->getSourceRange().getBegin(), + return Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_method) << Method << Arg->getSourceRange(); - + // Functions must have external linkage. if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) { if (Func->getStorageClass() == FunctionDecl::Static) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_function_not_extern) << Func << Arg->getSourceRange(); Diag(Func->getLocation(), diag::note_template_arg_internal_object) @@ -1424,7 +1779,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { if (!Var->hasGlobalStorage()) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_object_not_extern) << Var << Arg->getSourceRange(); Diag(Var->getLocation(), diag::note_template_arg_internal_object) @@ -1436,19 +1791,19 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, Entity = Var; return Invalid; } - + // We found something else, but we don't know specifically what it is. - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_object_or_func) << Arg->getSourceRange(); - Diag(DRE->getDecl()->getLocation(), + Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); return true; } /// \brief Checks whether the given template argument is a pointer to /// member constant according to C++ [temp.arg.nontype]p1. -bool +bool Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { bool Invalid = false; @@ -1461,7 +1816,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { return false; // C++ [temp.arg.nontype]p1: - // + // // A template-argument for a non-type, non-template // template-parameter shall be one of: [...] // @@ -1471,7 +1826,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { // Ignore (and complain about) any excess parentheses. while (ParenExpr *Parens = dyn_cast<ParenExpr>(Arg)) { if (!Invalid) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_extra_parens) << Arg->getSourceRange(); Invalid = true; @@ -1501,10 +1856,10 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { } // We found something else, but we don't know specifically what it is. - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_pointer_to_member_form) << Arg->getSourceRange(); - Diag(DRE->getDecl()->getLocation(), + Diag(DRE->getDecl()->getLocation(), diag::note_template_arg_refers_here); return true; } @@ -1519,7 +1874,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) { /// /// If no error was detected, Converted receives the converted template argument. bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, - QualType InstantiatedParamType, Expr *&Arg, + QualType InstantiatedParamType, Expr *&Arg, TemplateArgument &Converted) { SourceLocation StartLoc = Arg->getSourceRange().getBegin(); @@ -1555,7 +1910,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, SourceLocation NonConstantLoc; llvm::APSInt Value; if (!ArgType->isIntegralType() && !ArgType->isEnumeralType()) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_integral_or_enumeral) << ArgType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); @@ -1584,7 +1939,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ImpCastExprToType(Arg, ParamType); } else { // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); @@ -1592,7 +1947,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } QualType IntegerType = Context.getCanonicalType(ParamType); - if (const EnumType *Enum = IntegerType->getAsEnumType()) + if (const EnumType *Enum = IntegerType->getAs<EnumType>()) IntegerType = Context.getCanonicalType(Enum->getDecl()->getIntegerType()); if (!Arg->isValueDependent()) { @@ -1610,7 +1965,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // Check that we don't overflow the template parameter type. unsigned AllowedBits = Context.getTypeSize(IntegerType); if (Value.getActiveBits() > AllowedBits) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_too_large) << Value.toString(10) << Param->getType() << Arg->getSourceRange(); @@ -1634,7 +1989,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } Converted = TemplateArgument(StartLoc, Value, - ParamType->isEnumeralType() ? ParamType + ParamType->isEnumeralType() ? ParamType : IntegerType); return false; } @@ -1648,13 +2003,13 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // function is selected from the set (13.4). // In C++0x, any std::nullptr_t value can be converted. (ParamType->isPointerType() && - ParamType->getAsPointerType()->getPointeeType()->isFunctionType()) || + ParamType->getAs<PointerType>()->getPointeeType()->isFunctionType()) || // -- For a non-type template-parameter of type reference to // function, no conversions apply. If the template-argument // represents a set of overloaded functions, the matching // function is selected from the set (13.4). (ParamType->isReferenceType() && - ParamType->getAsReferenceType()->getPointeeType()->isFunctionType()) || + ParamType->getAs<ReferenceType>()->getPointeeType()->isFunctionType()) || // -- For a non-type template-parameter of type pointer to // member function, no conversions apply. If the // template-argument represents a set of overloaded member @@ -1662,9 +2017,9 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // the set (13.4). // Again, C++0x allows a std::nullptr_t value. (ParamType->isMemberPointerType() && - ParamType->getAsMemberPointerType()->getPointeeType() + ParamType->getAs<MemberPointerType>()->getPointeeType() ->isFunctionType())) { - if (Context.hasSameUnqualifiedType(ArgType, + if (Context.hasSameUnqualifiedType(ArgType, ParamType.getNonReferenceType())) { // We don't have to do anything: the types already match. } else if (ArgType->isNullPtrType() && (ParamType->isPointerType() || @@ -1674,7 +2029,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } else if (ArgType->isFunctionType() && ParamType->isPointerType()) { ArgType = Context.getPointerType(ArgType); ImpCastExprToType(Arg, ArgType); - } else if (FunctionDecl *Fn + } else if (FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) { if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin())) return true; @@ -1687,31 +2042,33 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, } } - if (!Context.hasSameUnqualifiedType(ArgType, + if (!Context.hasSameUnqualifiedType(ArgType, ParamType.getNonReferenceType())) { // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); return true; } - + if (ParamType->isMemberPointerType()) { NamedDecl *Member = 0; if (CheckTemplateArgumentPointerToMember(Arg, Member)) return true; - Member = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Member)); + if (Member) + Member = cast<NamedDecl>(Member->getCanonicalDecl()); Converted = TemplateArgument(StartLoc, Member); return false; } - + NamedDecl *Entity = 0; if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) return true; - Entity = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Entity)); + if (Entity) + Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); Converted = TemplateArgument(StartLoc, Entity); return false; } @@ -1721,7 +2078,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, // object, qualification conversions (4.4) and the // array-to-pointer conversion (4.2) are applied. // C++0x also allows a value of std::nullptr_t. - assert(ParamType->getAsPointerType()->getPointeeType()->isObjectType() && + assert(ParamType->getAs<PointerType>()->getPointeeType()->isObjectType() && "Only object pointers allowed here"); if (ArgType->isNullPtrType()) { @@ -1736,26 +2093,27 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ArgType = ParamType; ImpCastExprToType(Arg, ParamType); } - + if (!Context.hasSameUnqualifiedType(ArgType, ParamType)) { // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); return true; } - + NamedDecl *Entity = 0; if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) return true; - Entity = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Entity)); + if (Entity) + Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); Converted = TemplateArgument(StartLoc, Entity); return false; } - - if (const ReferenceType *ParamRefType = ParamType->getAsReferenceType()) { + + if (const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>()) { // -- For a non-type template-parameter of type reference to // object, no conversions apply. The type referred to by the // reference may be more cv-qualified than the (otherwise @@ -1766,7 +2124,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, "Only object references allowed here"); if (!Context.hasSameUnqualifiedType(ParamRefType->getPointeeType(), ArgType)) { - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_no_ref_bind) << InstantiatedParamType << Arg->getType() << Arg->getSourceRange(); @@ -1774,10 +2132,10 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, return true; } - unsigned ParamQuals + unsigned ParamQuals = Context.getCanonicalType(ParamType).getCVRQualifiers(); unsigned ArgQuals = Context.getCanonicalType(ArgType).getCVRQualifiers(); - + if ((ParamQuals | ArgQuals) != ParamQuals) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_ref_bind_ignores_quals) @@ -1786,12 +2144,12 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, Diag(Param->getLocation(), diag::note_template_param_here); return true; } - + NamedDecl *Entity = 0; if (CheckTemplateArgumentAddressOfObjectOrFunction(Arg, Entity)) return true; - Entity = cast<NamedDecl>(Context.getCanonicalDecl(Entity)); + Entity = cast<NamedDecl>(Entity->getCanonicalDecl()); Converted = TemplateArgument(StartLoc, Entity); return false; } @@ -1809,18 +2167,19 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, ImpCastExprToType(Arg, ParamType); } else { // We can't perform this conversion. - Diag(Arg->getSourceRange().getBegin(), + Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_not_convertible) << Arg->getType() << InstantiatedParamType << Arg->getSourceRange(); Diag(Param->getLocation(), diag::note_template_param_here); - return true; + return true; } NamedDecl *Member = 0; if (CheckTemplateArgumentPointerToMember(Arg, Member)) return true; - - Member = cast_or_null<NamedDecl>(Context.getCanonicalDecl(Member)); + + if (Member) + Member = cast<NamedDecl>(Member->getCanonicalDecl()); Converted = TemplateArgument(StartLoc, Member); return false; } @@ -1846,9 +2205,9 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, // Note that we also allow template template parameters here, which // will happen when we are dealing with, e.g., class template // partial specializations. - if (!isa<ClassTemplateDecl>(Template) && + if (!isa<ClassTemplateDecl>(Template) && !isa<TemplateTemplateParmDecl>(Template)) { - assert(isa<FunctionTemplateDecl>(Template) && + assert(isa<FunctionTemplateDecl>(Template) && "Only function templates are possible here"); Diag(Arg->getLocStart(), diag::err_template_arg_not_class_template); Diag(Template->getLocation(), diag::note_template_arg_refers_here_func) @@ -1864,7 +2223,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, /// \brief Determine whether the given template parameter lists are /// equivalent. /// -/// \param New The new template parameter list, typically written in the +/// \param New The new template parameter list, typically written in the /// source code as part of a new template declaration. /// /// \param Old The old template parameter list, typically found via @@ -1886,7 +2245,7 @@ bool Sema::CheckTemplateArgument(TemplateTemplateParmDecl *Param, /// /// \returns True if the template parameter lists are equal, false /// otherwise. -bool +bool Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, TemplateParameterList *Old, bool Complain, @@ -1898,7 +2257,7 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, if (TemplateArgLoc.isValid()) { Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch); NextDiag = diag::note_template_param_list_different_arity; - } + } Diag(New->getTemplateLoc(), NextDiag) << (New->size() > Old->size()) << IsTemplateTemplateParm @@ -1939,15 +2298,15 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, // types within the template parameter list of the template template // parameter can be checked, and (2) the template type parameter depths // will match up. - QualType OldParmType + QualType OldParmType = Context.getTypeDeclType(cast<TemplateTypeParmDecl>(*OldParm)); - QualType NewParmType + QualType NewParmType = Context.getTypeDeclType(cast<TemplateTypeParmDecl>(*NewParm)); - assert(Context.getCanonicalType(OldParmType) == - Context.getCanonicalType(NewParmType) && + assert(Context.getCanonicalType(OldParmType) == + Context.getCanonicalType(NewParmType) && "type parameter mismatch?"); #endif - } else if (NonTypeTemplateParmDecl *OldNTTP + } else if (NonTypeTemplateParmDecl *OldNTTP = dyn_cast<NonTypeTemplateParmDecl>(*OldParm)) { // The types of non-type template parameters must agree. NonTypeTemplateParmDecl *NewNTTP @@ -1957,14 +2316,14 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, if (Complain) { unsigned NextDiag = diag::err_template_nontype_parm_different_type; if (TemplateArgLoc.isValid()) { - Diag(TemplateArgLoc, + Diag(TemplateArgLoc, diag::err_template_arg_template_params_mismatch); NextDiag = diag::note_template_nontype_parm_different_type; } Diag(NewNTTP->getLocation(), NextDiag) << NewNTTP->getType() << IsTemplateTemplateParm; - Diag(OldNTTP->getLocation(), + Diag(OldNTTP->getLocation(), diag::note_template_nontype_parm_prev_declaration) << OldNTTP->getType(); } @@ -1974,9 +2333,9 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, // The template parameter lists of template template // parameters must agree. // FIXME: Could we perform a faster "type" comparison here? - assert(isa<TemplateTemplateParmDecl>(*OldParm) && + assert(isa<TemplateTemplateParmDecl>(*OldParm) && "Only template template parameters handled here"); - TemplateTemplateParmDecl *OldTTP + TemplateTemplateParmDecl *OldTTP = cast<TemplateTemplateParmDecl>(*OldParm); TemplateTemplateParmDecl *NewTTP = cast<TemplateTemplateParmDecl>(*NewParm); @@ -1996,56 +2355,105 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New, /// /// If the template declaration is valid in this scope, returns /// false. Otherwise, issues a diagnostic and returns true. -bool -Sema::CheckTemplateDeclScope(Scope *S, - MultiTemplateParamsArg &TemplateParameterLists) { - assert(TemplateParameterLists.size() > 0 && "Not a template"); - +bool +Sema::CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams) { // Find the nearest enclosing declaration scope. while ((S->getFlags() & Scope::DeclScope) == 0 || (S->getFlags() & Scope::TemplateParamScope) != 0) S = S->getParent(); - - TemplateParameterList *TemplateParams = - static_cast<TemplateParameterList*>(*TemplateParameterLists.get()); - SourceLocation TemplateLoc = TemplateParams->getTemplateLoc(); - SourceRange TemplateRange - = SourceRange(TemplateLoc, TemplateParams->getRAngleLoc()); // C++ [temp]p2: // A template-declaration can appear only as a namespace scope or // class scope declaration. DeclContext *Ctx = static_cast<DeclContext *>(S->getEntity()); - while (Ctx && isa<LinkageSpecDecl>(Ctx)) { - if (cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx) - return Diag(TemplateLoc, diag::err_template_linkage) - << TemplateRange; + if (Ctx && isa<LinkageSpecDecl>(Ctx) && + cast<LinkageSpecDecl>(Ctx)->getLanguage() != LinkageSpecDecl::lang_cxx) + return Diag(TemplateParams->getTemplateLoc(), diag::err_template_linkage) + << TemplateParams->getSourceRange(); + while (Ctx && isa<LinkageSpecDecl>(Ctx)) Ctx = Ctx->getParent(); - } if (Ctx && (Ctx->isFileContext() || Ctx->isRecord())) return false; - return Diag(TemplateLoc, diag::err_template_outside_namespace_or_class_scope) - << TemplateRange; + return Diag(TemplateParams->getTemplateLoc(), + diag::err_template_outside_namespace_or_class_scope) + << TemplateParams->getSourceRange(); +} + +/// \brief Determine what kind of template specialization the given declaration +/// is. +static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) { + if (!D) + return TSK_Undeclared; + + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) + return Record->getTemplateSpecializationKind(); + if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) + return Function->getTemplateSpecializationKind(); + if (VarDecl *Var = dyn_cast<VarDecl>(D)) + return Var->getTemplateSpecializationKind(); + + return TSK_Undeclared; } -/// \brief Check whether a class template specialization or explicit -/// instantiation in the current context is well-formed. +/// \brief Check whether a specialization or explicit instantiation is +/// well-formed in the current context. /// -/// This routine determines whether a class template specialization or -/// explicit instantiation can be declared in the current context -/// (C++ [temp.expl.spec]p2, C++0x [temp.explicit]p2) and emits -/// appropriate diagnostics if there was an error. It returns true if -// there was an error that we cannot recover from, and false otherwise. -bool -Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate, - ClassTemplateSpecializationDecl *PrevDecl, - SourceLocation TemplateNameLoc, - SourceRange ScopeSpecifierRange, - bool PartialSpecialization, - bool ExplicitInstantiation) { +/// This routine determines whether a template specialization or +/// explicit instantiation can be declared in the current context +/// (C++ [temp.expl.spec]p2, C++0x [temp.explicit]p2). +/// +/// \param S the semantic analysis object for which this check is being +/// performed. +/// +/// \param Specialized the entity being specialized or instantiated, which +/// may be a kind of template (class template, function template, etc.) or +/// a member of a class template (member function, static data member, +/// member class). +/// +/// \param PrevDecl the previous declaration of this entity, if any. +/// +/// \param Loc the location of the explicit specialization or instantiation of +/// this entity. +/// +/// \param IsPartialSpecialization whether this is a partial specialization of +/// a class template. +/// +/// \param TSK the kind of specialization or implicit instantiation being +/// performed. +/// +/// \returns true if there was an error that we cannot recover from, false +/// otherwise. +static bool CheckTemplateSpecializationScope(Sema &S, + NamedDecl *Specialized, + NamedDecl *PrevDecl, + SourceLocation Loc, + bool IsPartialSpecialization, + TemplateSpecializationKind TSK) { + // Keep these "kind" numbers in sync with the %select statements in the + // various diagnostics emitted by this routine. + int EntityKind = 0; + bool isTemplateSpecialization = false; + if (isa<ClassTemplateDecl>(Specialized)) { + EntityKind = IsPartialSpecialization? 1 : 0; + isTemplateSpecialization = true; + } else if (isa<FunctionTemplateDecl>(Specialized)) { + EntityKind = 2; + isTemplateSpecialization = true; + } else if (isa<CXXMethodDecl>(Specialized)) + EntityKind = 3; + else if (isa<VarDecl>(Specialized)) + EntityKind = 4; + else if (isa<RecordDecl>(Specialized)) + EntityKind = 5; + else { + S.Diag(Loc, diag::err_template_spec_unknown_kind) << TSK; + S.Diag(Specialized->getLocation(), diag::note_specialized_entity) << TSK; + return true; + } + // C++ [temp.expl.spec]p2: // An explicit specialization shall be declared in the namespace // of which the template is a member, or, for member templates, in @@ -2059,66 +2467,79 @@ Sema::CheckClassTemplateSpecializationScope(ClassTemplateDecl *ClassTemplate, // the explicit specialization was declared, or in a namespace // that encloses the one in which the explicit specialization was // declared. - if (CurContext->getLookupContext()->isFunctionOrMethod()) { - int Kind = ExplicitInstantiation? 2 : PartialSpecialization? 1 : 0; - Diag(TemplateNameLoc, diag::err_template_spec_decl_function_scope) - << Kind << ClassTemplate; + if (S.CurContext->getLookupContext()->isFunctionOrMethod()) { + S.Diag(Loc, diag::err_template_spec_decl_function_scope) + << TSK << Specialized; return true; } - DeclContext *DC = CurContext->getEnclosingNamespaceContext(); - DeclContext *TemplateContext - = ClassTemplate->getDeclContext()->getEnclosingNamespaceContext(); - if ((!PrevDecl || PrevDecl->getSpecializationKind() == TSK_Undeclared) && - !ExplicitInstantiation) { - // There is no prior declaration of this entity, so this - // specialization must be in the same context as the template - // itself. - if (DC != TemplateContext) { - if (isa<TranslationUnitDecl>(TemplateContext)) - Diag(TemplateNameLoc, diag::err_template_spec_decl_out_of_scope_global) - << PartialSpecialization - << ClassTemplate << ScopeSpecifierRange; - else if (isa<NamespaceDecl>(TemplateContext)) - Diag(TemplateNameLoc, diag::err_template_spec_decl_out_of_scope) - << PartialSpecialization << ClassTemplate - << cast<NamedDecl>(TemplateContext) << ScopeSpecifierRange; - - Diag(ClassTemplate->getLocation(), diag::note_template_decl_here); - } - - return false; + if (S.CurContext->isRecord() && !IsPartialSpecialization) { + S.Diag(Loc, diag::err_template_spec_decl_class_scope) + << TSK << Specialized; + return true; } - - // We have a previous declaration of this entity. Make sure that - // this redeclaration (or definition) occurs in an enclosing namespace. - if (!CurContext->Encloses(TemplateContext)) { - // FIXME: In C++98, we would like to turn these errors into warnings, - // dependent on a -Wc++0x flag. - bool SuppressedDiag = false; - int Kind = ExplicitInstantiation? 2 : PartialSpecialization? 1 : 0; - if (isa<TranslationUnitDecl>(TemplateContext)) { - if (!ExplicitInstantiation || getLangOptions().CPlusPlus0x) - Diag(TemplateNameLoc, diag::err_template_spec_redecl_global_scope) - << Kind << ClassTemplate << ScopeSpecifierRange; - else - SuppressedDiag = true; - } else if (isa<NamespaceDecl>(TemplateContext)) { - if (!ExplicitInstantiation || getLangOptions().CPlusPlus0x) - Diag(TemplateNameLoc, diag::err_template_spec_redecl_out_of_scope) - << Kind << ClassTemplate - << cast<NamedDecl>(TemplateContext) << ScopeSpecifierRange; - else - SuppressedDiag = true; + + // C++ [temp.class.spec]p6: + // A class template partial specialization may be declared or redeclared + // in any namespace scope in which its definition may be defined (14.5.1 + // and 14.5.2). + bool ComplainedAboutScope = false; + DeclContext *SpecializedContext + = Specialized->getDeclContext()->getEnclosingNamespaceContext(); + DeclContext *DC = S.CurContext->getEnclosingNamespaceContext(); + if (TSK == TSK_ExplicitSpecialization) { + if ((!PrevDecl || + getTemplateSpecializationKind(PrevDecl) == TSK_Undeclared || + getTemplateSpecializationKind(PrevDecl) == TSK_ImplicitInstantiation)){ + // There is no prior declaration of this entity, so this + // specialization must be in the same context as the template + // itself. + if (!DC->Equals(SpecializedContext)) { + if (isa<TranslationUnitDecl>(SpecializedContext)) + S.Diag(Loc, diag::err_template_spec_decl_out_of_scope_global) + << EntityKind << Specialized; + else if (isa<NamespaceDecl>(SpecializedContext)) + S.Diag(Loc, diag::err_template_spec_decl_out_of_scope) + << EntityKind << Specialized + << cast<NamedDecl>(SpecializedContext); + + S.Diag(Specialized->getLocation(), diag::note_specialized_entity) + << TSK; + ComplainedAboutScope = true; + } } - - if (!SuppressedDiag) - Diag(ClassTemplate->getLocation(), diag::note_template_decl_here); } - + + // Make sure that this redeclaration (or definition) occurs in an enclosing + // namespace. We perform this check for explicit specializations and, in + // C++0x, for explicit instantiations as well (per DR275). + // FIXME: -Wc++0x should make these warnings. + // Note that HandleDeclarator() performs this check for explicit + // specializations of function templates, static data members, and member + // functions, so we skip the check here for those kinds of entities. + // FIXME: HandleDeclarator's diagnostics aren't quite as good, though. + // Should we refactor that check, so that it occurs later? + if (!ComplainedAboutScope && !DC->Encloses(SpecializedContext) && + ((TSK == TSK_ExplicitSpecialization && + !(isa<FunctionTemplateDecl>(Specialized) || isa<VarDecl>(Specialized) || + isa<FunctionDecl>(Specialized))) || + S.getLangOptions().CPlusPlus0x)) { + if (isa<TranslationUnitDecl>(SpecializedContext)) + S.Diag(Loc, diag::err_template_spec_redecl_global_scope) + << EntityKind << Specialized; + else if (isa<NamespaceDecl>(SpecializedContext)) + S.Diag(Loc, diag::err_template_spec_redecl_out_of_scope) + << EntityKind << Specialized + << cast<NamedDecl>(SpecializedContext); + + S.Diag(Specialized->getLocation(), diag::note_specialized_entity) << TSK; + } + + // FIXME: check for specialization-after-instantiation errors and such. + return false; } - + /// \brief Check the non-type template arguments of a class template /// partial specialization according to C++ [temp.class.spec]p9. /// @@ -2142,16 +2563,16 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( // FIXME: the interface to this function will have to change to // accommodate variadic templates. MirrorsPrimaryTemplate = true; - + const TemplateArgument *ArgList = TemplateArgs.getFlatArguments(); - + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { // Determine whether the template argument list of the partial // specialization is identical to the implicit argument list of // the primary template. The caller may need to diagnostic this as // an error per C++ [temp.class.spec]p9b3. if (MirrorsPrimaryTemplate) { - if (TemplateTypeParmDecl *TTP + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(TemplateParams->getParam(I))) { if (Context.getCanonicalType(Context.getTypeDeclType(TTP)) != Context.getCanonicalType(ArgList[I].getAsType())) @@ -2161,11 +2582,11 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( TemplateParams->getParam(I))) { // FIXME: We should settle on either Declaration storage or // Expression storage for template template parameters. - TemplateTemplateParmDecl *ArgDecl + TemplateTemplateParmDecl *ArgDecl = dyn_cast_or_null<TemplateTemplateParmDecl>( ArgList[I].getAsDecl()); if (!ArgDecl) - if (DeclRefExpr *DRE + if (DeclRefExpr *DRE = dyn_cast_or_null<DeclRefExpr>(ArgList[I].getAsExpr())) ArgDecl = dyn_cast<TemplateTemplateParmDecl>(DRE->getDecl()); @@ -2176,7 +2597,7 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( } } - NonTypeTemplateParmDecl *Param + NonTypeTemplateParmDecl *Param = dyn_cast<NonTypeTemplateParmDecl>(TemplateParams->getParam(I)); if (!Param) { continue; @@ -2197,9 +2618,9 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( // specialized non-type arguments, so skip any non-specialized // arguments. if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr)) - if (NonTypeTemplateParmDecl *NTTP + if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(DRE->getDecl())) { - if (MirrorsPrimaryTemplate && + if (MirrorsPrimaryTemplate && (Param->getIndex() != NTTP->getIndex() || Param->getDepth() != NTTP->getDepth())) MirrorsPrimaryTemplate = false; @@ -2215,7 +2636,7 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( // specialization except when the argument expression is a // simple identifier. if (ArgExpr->isTypeDependent() || ArgExpr->isValueDependent()) { - Diag(ArgExpr->getLocStart(), + Diag(ArgExpr->getLocStart(), diag::err_dependent_non_type_arg_in_partial_spec) << ArgExpr->getSourceRange(); return true; @@ -2225,7 +2646,7 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( // specialized non-type argument shall not be dependent on a // parameter of the specialization. if (Param->getType()->isDependentType()) { - Diag(ArgExpr->getLocStart(), + Diag(ArgExpr->getLocStart(), diag::err_dependent_typed_non_type_arg_in_partial_spec) << Param->getType() << ArgExpr->getSourceRange(); @@ -2240,8 +2661,9 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs( } Sema::DeclResult -Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, - SourceLocation KWLoc, +Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, + TagUseKind TUK, + SourceLocation KWLoc, const CXXScopeSpec &SS, TemplateTy TemplateD, SourceLocation TemplateNameLoc, @@ -2251,65 +2673,72 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, SourceLocation RAngleLoc, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists) { + assert(TUK != TUK_Reference && "References are not specializations"); + // Find the class template we're specializing TemplateName Name = TemplateD.getAsVal<TemplateName>(); - ClassTemplateDecl *ClassTemplate + ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Name.getAsTemplateDecl()); + bool isExplicitSpecialization = false; bool isPartialSpecialization = false; // Check the validity of the template headers that introduce this // template. - // FIXME: Once we have member templates, we'll need to check - // C++ [temp.expl.spec]p17-18, where we could have multiple levels of - // template<> headers. - if (TemplateParameterLists.size() == 0) - Diag(KWLoc, diag::err_template_spec_needs_header) - << CodeModificationHint::CreateInsertion(KWLoc, "template<> "); - else { - TemplateParameterList *TemplateParams - = static_cast<TemplateParameterList*>(*TemplateParameterLists.get()); - if (TemplateParameterLists.size() > 1) { - Diag(TemplateParams->getTemplateLoc(), - diag::err_template_spec_extra_headers); - return true; - } - - if (TemplateParams->size() > 0) { - isPartialSpecialization = true; - - // C++ [temp.class.spec]p10: - // The template parameter list of a specialization shall not - // contain default template argument values. - for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { - Decl *Param = TemplateParams->getParam(I); - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { - if (TTP->hasDefaultArgument()) { - Diag(TTP->getDefaultArgumentLoc(), - diag::err_default_arg_in_partial_spec); - TTP->setDefaultArgument(QualType(), SourceLocation(), false); - } - } else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(Param)) { - if (Expr *DefArg = NTTP->getDefaultArgument()) { - Diag(NTTP->getDefaultArgumentLoc(), - diag::err_default_arg_in_partial_spec) - << DefArg->getSourceRange(); - NTTP->setDefaultArgument(0); - DefArg->Destroy(Context); - } - } else { - TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param); - if (Expr *DefArg = TTP->getDefaultArgument()) { - Diag(TTP->getDefaultArgumentLoc(), - diag::err_default_arg_in_partial_spec) - << DefArg->getSourceRange(); - TTP->setDefaultArgument(0); - DefArg->Destroy(Context); - } + // FIXME: We probably shouldn't complain about these headers for + // friend declarations. + TemplateParameterList *TemplateParams + = MatchTemplateParametersToScopeSpecifier(TemplateNameLoc, SS, + (TemplateParameterList**)TemplateParameterLists.get(), + TemplateParameterLists.size(), + isExplicitSpecialization); + if (TemplateParams && TemplateParams->size() > 0) { + isPartialSpecialization = true; + + // C++ [temp.class.spec]p10: + // The template parameter list of a specialization shall not + // contain default template argument values. + for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) { + Decl *Param = TemplateParams->getParam(I); + if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (TTP->hasDefaultArgument()) { + Diag(TTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec); + TTP->setDefaultArgument(QualType(), SourceLocation(), false); + } + } else if (NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (Expr *DefArg = NTTP->getDefaultArgument()) { + Diag(NTTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec) + << DefArg->getSourceRange(); + NTTP->setDefaultArgument(0); + DefArg->Destroy(Context); + } + } else { + TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(Param); + if (Expr *DefArg = TTP->getDefaultArgument()) { + Diag(TTP->getDefaultArgumentLoc(), + diag::err_default_arg_in_partial_spec) + << DefArg->getSourceRange(); + TTP->setDefaultArgument(0); + DefArg->Destroy(Context); } } } + } else if (TemplateParams) { + if (TUK == TUK_Friend) + Diag(KWLoc, diag::err_template_spec_friend) + << CodeModificationHint::CreateRemoval( + SourceRange(TemplateParams->getTemplateLoc(), + TemplateParams->getRAngleLoc())) + << SourceRange(LAngleLoc, RAngleLoc); + else + isExplicitSpecialization = true; + } else if (TUK != TUK_Friend) { + Diag(KWLoc, diag::err_template_spec_needs_header) + << CodeModificationHint::CreateInsertion(KWLoc, "template<> "); + isExplicitSpecialization = true; } // Check that the specialization uses the same tag kind as the @@ -2322,13 +2751,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, case DeclSpec::TST_class: Kind = TagDecl::TK_class; break; } if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), - Kind, KWLoc, + Kind, KWLoc, *ClassTemplate->getIdentifier())) { - Diag(KWLoc, diag::err_use_with_wrong_tag) + Diag(KWLoc, diag::err_use_with_wrong_tag) << ClassTemplate - << CodeModificationHint::CreateReplacement(KWLoc, + << CodeModificationHint::CreateReplacement(KWLoc, ClassTemplate->getTemplatedDecl()->getKindName()); - Diag(ClassTemplate->getTemplatedDecl()->getLocation(), + Diag(ClassTemplate->getTemplatedDecl()->getLocation(), diag::note_previous_use); Kind = ClassTemplate->getTemplatedDecl()->getTagKind(); } @@ -2341,15 +2770,15 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // template. TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), TemplateArgs.size()); - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, TemplateArgs.data(), TemplateArgs.size(), RAngleLoc, false, Converted)) return true; - assert((Converted.structuredSize() == + assert((Converted.structuredSize() == ClassTemplate->getTemplateParameters()->size()) && "Converted template argument list is too short!"); - + // Find the class template (partial) specialization declaration that // corresponds to these arguments. llvm::FoldingSetNodeID ID; @@ -2363,35 +2792,38 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, if (MirrorsPrimaryTemplate) { // C++ [temp.class.spec]p9b3: // - // -- The argument list of the specialization shall not be identical - // to the implicit argument list of the primary template. + // -- The argument list of the specialization shall not be identical + // to the implicit argument list of the primary template. Diag(TemplateNameLoc, diag::err_partial_spec_args_match_primary_template) - << (TK == TK_Definition) - << CodeModificationHint::CreateRemoval(SourceRange(LAngleLoc, + << (TUK == TUK_Definition) + << CodeModificationHint::CreateRemoval(SourceRange(LAngleLoc, RAngleLoc)); - return ActOnClassTemplate(S, TagSpec, TK, KWLoc, SS, + return CheckClassTemplate(S, TagSpec, TUK, KWLoc, SS, ClassTemplate->getIdentifier(), TemplateNameLoc, Attr, - move(TemplateParameterLists), + TemplateParams, AS_none); } + // FIXME: Diagnose friend partial specializations + // FIXME: Template parameter list matters, too - ClassTemplatePartialSpecializationDecl::Profile(ID, + ClassTemplatePartialSpecializationDecl::Profile(ID, Converted.getFlatArguments(), - Converted.flatSize()); - } - else + Converted.flatSize(), + Context); + } else ClassTemplateSpecializationDecl::Profile(ID, Converted.getFlatArguments(), - Converted.flatSize()); + Converted.flatSize(), + Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = 0; if (isPartialSpecialization) PrevDecl - = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID, + = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID, InsertPos); else PrevDecl @@ -2401,29 +2833,41 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // Check whether we can declare a class template specialization in // the current scope. - if (CheckClassTemplateSpecializationScope(ClassTemplate, PrevDecl, - TemplateNameLoc, - SS.getRange(), - isPartialSpecialization, - /*ExplicitInstantiation=*/false)) + if (TUK != TUK_Friend && + CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl, + TemplateNameLoc, isPartialSpecialization, + TSK_ExplicitSpecialization)) return true; - - if (PrevDecl && PrevDecl->getSpecializationKind() == TSK_Undeclared) { + + // The canonical type + QualType CanonType; + if (PrevDecl && + (PrevDecl->getSpecializationKind() == TSK_Undeclared || + TUK == TUK_Friend)) { // Since the only prior class template specialization with these - // arguments was referenced but not declared, reuse that + // arguments was referenced but not declared, or we're only + // referencing this specialization as a friend, reuse that // declaration node as our own, updating its source location to // reflect our new declaration. Specialization = PrevDecl; Specialization->setLocation(TemplateNameLoc); PrevDecl = 0; + CanonType = Context.getTypeDeclType(Specialization); } else if (isPartialSpecialization) { + // Build the canonical type that describes the converted template + // arguments of the class template partial specialization. + CanonType = Context.getTemplateSpecializationType( + TemplateName(ClassTemplate), + Converted.getFlatArguments(), + Converted.flatSize()); + // Create a new class template partial specialization declaration node. - TemplateParameterList *TemplateParams + TemplateParameterList *TemplateParams = static_cast<TemplateParameterList*>(*TemplateParameterLists.get()); ClassTemplatePartialSpecializationDecl *PrevPartial = cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl); - ClassTemplatePartialSpecializationDecl *Partial - = ClassTemplatePartialSpecializationDecl::Create(Context, + ClassTemplatePartialSpecializationDecl *Partial + = ClassTemplatePartialSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), TemplateNameLoc, TemplateParams, @@ -2445,7 +2889,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // will never be used. llvm::SmallVector<bool, 8> DeducibleParams; DeducibleParams.resize(TemplateParams->size()); - MarkDeducedTemplateParameters(Partial->getTemplateArgs(), DeducibleParams); + MarkUsedTemplateParameters(Partial->getTemplateArgs(), true, + DeducibleParams); unsigned NumNonDeducible = 0; for (unsigned I = 0, N = DeducibleParams.size(); I != N; ++I) if (!DeducibleParams[I]) @@ -2459,25 +2904,24 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, if (!DeducibleParams[I]) { NamedDecl *Param = cast<NamedDecl>(TemplateParams->getParam(I)); if (Param->getDeclName()) - Diag(Param->getLocation(), + Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter) << Param->getDeclName(); else - Diag(Param->getLocation(), + Diag(Param->getLocation(), diag::note_partial_spec_unused_parameter) << std::string("<anonymous>"); } } } - } else { // Create a new class template specialization declaration node for - // this explicit specialization. + // this explicit specialization or friend declaration. Specialization - = ClassTemplateSpecializationDecl::Create(Context, + = ClassTemplateSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), TemplateNameLoc, - ClassTemplate, + ClassTemplate, Converted, PrevDecl); @@ -2485,21 +2929,40 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, ClassTemplate->getSpecializations().RemoveNode(PrevDecl); ClassTemplate->getSpecializations().GetOrInsertNode(Specialization); } else { - ClassTemplate->getSpecializations().InsertNode(Specialization, + ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); } + + CanonType = Context.getTypeDeclType(Specialization); } - // Note that this is an explicit specialization. - Specialization->setSpecializationKind(TSK_ExplicitSpecialization); + // C++ [temp.expl.spec]p6: + // If a template, a member template or the member of a class template is + // explicitly specialized then that specialization shall be declared + // before the first use of that specialization that would cause an implicit + // instantiation to take place, in every translation unit in which such a + // use occurs; no diagnostic is required. + if (PrevDecl && PrevDecl->getPointOfInstantiation().isValid()) { + SourceRange Range(TemplateNameLoc, RAngleLoc); + Diag(TemplateNameLoc, diag::err_specialization_after_instantiation) + << Context.getTypeDeclType(Specialization) << Range; + + Diag(PrevDecl->getPointOfInstantiation(), + diag::note_instantiation_required_here) + << (PrevDecl->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation); + return true; + } + + // If this is not a friend, note that this is an explicit specialization. + if (TUK != TUK_Friend) + Specialization->setSpecializationKind(TSK_ExplicitSpecialization); // Check that this isn't a redefinition of this specialization. - if (TK == TK_Definition) { + if (TUK == TUK_Definition) { if (RecordDecl *Def = Specialization->getDefinition(Context)) { - // FIXME: Should also handle explicit specialization after implicit - // instantiation with a special diagnostic. SourceRange Range(TemplateNameLoc, RAngleLoc); - Diag(TemplateNameLoc, diag::err_redefinition) + Diag(TemplateNameLoc, diag::err_redefinition) << Context.getTypeDeclType(Specialization) << Range; Diag(Def->getLocation(), diag::note_previous_definition); Specialization->setInvalidDecl(); @@ -2514,12 +2977,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // actually wrote the specialization, rather than formatting the // name based on the "canonical" representation used to store the // template arguments in the specialization. - QualType WrittenTy - = Context.getTemplateSpecializationType(Name, + QualType WrittenTy + = Context.getTemplateSpecializationType(Name, TemplateArgs.data(), TemplateArgs.size(), - Context.getTypeDeclType(Specialization)); - Specialization->setTypeAsWritten(WrittenTy); + CanonType); + if (TUK != TUK_Friend) + Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); // C++ [temp.expl.spec]p9: @@ -2531,56 +2995,343 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // but we also maintain the lexical context where the actual // definition occurs. Specialization->setLexicalDeclContext(CurContext); - + // We may be starting the definition of this specialization. - if (TK == TK_Definition) + if (TUK == TUK_Definition) Specialization->startDefinition(); - // Add the specialization into its lexical context, so that it can - // be seen when iterating through the list of declarations in that - // context. However, specializations are not found by name lookup. - CurContext->addDecl(Specialization); + if (TUK == TUK_Friend) { + FriendDecl *Friend = FriendDecl::Create(Context, CurContext, + TemplateNameLoc, + WrittenTy.getTypePtr(), + /*FIXME:*/KWLoc); + Friend->setAccess(AS_public); + CurContext->addDecl(Friend); + } else { + // Add the specialization into its lexical context, so that it can + // be seen when iterating through the list of declarations in that + // context. However, specializations are not found by name lookup. + CurContext->addDecl(Specialization); + } return DeclPtrTy::make(Specialization); } -Sema::DeclPtrTy -Sema::ActOnTemplateDeclarator(Scope *S, +Sema::DeclPtrTy +Sema::ActOnTemplateDeclarator(Scope *S, MultiTemplateParamsArg TemplateParameterLists, Declarator &D) { return HandleDeclarator(S, D, move(TemplateParameterLists), false); } -Sema::DeclPtrTy -Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, +Sema::DeclPtrTy +Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, MultiTemplateParamsArg TemplateParameterLists, Declarator &D) { assert(getCurFunctionDecl() == 0 && "Function parsing confused"); assert(D.getTypeObject(0).Kind == DeclaratorChunk::Function && "Not a function declarator!"); DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; - + if (FTI.hasPrototype) { - // FIXME: Diagnose arguments without names in C. + // FIXME: Diagnose arguments without names in C. } - + Scope *ParentScope = FnBodyScope->getParent(); - - DeclPtrTy DP = HandleDeclarator(ParentScope, D, + + DeclPtrTy DP = HandleDeclarator(ParentScope, D, move(TemplateParameterLists), /*IsFunctionDefinition=*/true); - FunctionTemplateDecl *FunctionTemplate - = cast_or_null<FunctionTemplateDecl>(DP.getAs<Decl>()); - if (FunctionTemplate) - return ActOnStartOfFunctionDef(FnBodyScope, + if (FunctionTemplateDecl *FunctionTemplate + = dyn_cast_or_null<FunctionTemplateDecl>(DP.getAs<Decl>())) + return ActOnStartOfFunctionDef(FnBodyScope, DeclPtrTy::make(FunctionTemplate->getTemplatedDecl())); - + if (FunctionDecl *Function = dyn_cast_or_null<FunctionDecl>(DP.getAs<Decl>())) + return ActOnStartOfFunctionDef(FnBodyScope, DeclPtrTy::make(Function)); return DeclPtrTy(); } +/// \brief Perform semantic analysis for the given function template +/// specialization. +/// +/// This routine performs all of the semantic analysis required for an +/// explicit function template specialization. On successful completion, +/// the function declaration \p FD will become a function template +/// specialization. +/// +/// \param FD the function declaration, which will be updated to become a +/// function template specialization. +/// +/// \param HasExplicitTemplateArgs whether any template arguments were +/// explicitly provided. +/// +/// \param LAngleLoc the location of the left angle bracket ('<'), if +/// template arguments were explicitly provided. +/// +/// \param ExplicitTemplateArgs the explicitly-provided template arguments, +/// if any. +/// +/// \param NumExplicitTemplateArgs the number of explicitly-provided template +/// arguments. This number may be zero even when HasExplicitTemplateArgs is +/// true as in, e.g., \c void sort<>(char*, char*); +/// +/// \param RAngleLoc the location of the right angle bracket ('>'), if +/// template arguments were explicitly provided. +/// +/// \param PrevDecl the set of declarations that +bool +Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, + bool HasExplicitTemplateArgs, + SourceLocation LAngleLoc, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, + SourceLocation RAngleLoc, + NamedDecl *&PrevDecl) { + // The set of function template specializations that could match this + // explicit function template specialization. + typedef llvm::SmallVector<FunctionDecl *, 8> CandidateSet; + CandidateSet Candidates; + + DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext(); + for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) { + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)) { + // Only consider templates found within the same semantic lookup scope as + // FD. + if (!FDLookupContext->Equals(Ovl->getDeclContext()->getLookupContext())) + continue; + + // C++ [temp.expl.spec]p11: + // A trailing template-argument can be left unspecified in the + // template-id naming an explicit function template specialization + // provided it can be deduced from the function argument type. + // Perform template argument deduction to determine whether we may be + // specializing this template. + // FIXME: It is somewhat wasteful to build + TemplateDeductionInfo Info(Context); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult TDK + = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + FD->getType(), + Specialization, + Info)) { + // FIXME: Template argument deduction failed; record why it failed, so + // that we can provide nifty diagnostics. + (void)TDK; + continue; + } + + // Record this candidate. + Candidates.push_back(Specialization); + } + } + + // Find the most specialized function template. + FunctionDecl *Specialization = getMostSpecialized(Candidates.data(), + Candidates.size(), + TPOC_Other, + FD->getLocation(), + PartialDiagnostic(diag::err_function_template_spec_no_match) + << FD->getDeclName(), + PartialDiagnostic(diag::err_function_template_spec_ambiguous) + << FD->getDeclName() << HasExplicitTemplateArgs, + PartialDiagnostic(diag::note_function_template_spec_matched)); + if (!Specialization) + return true; + + // FIXME: Check if the prior specialization has a point of instantiation. + // If so, we have run afoul of . + + // Check the scope of this explicit specialization. + if (CheckTemplateSpecializationScope(*this, + Specialization->getPrimaryTemplate(), + Specialization, FD->getLocation(), + false, TSK_ExplicitSpecialization)) + return true; + + // C++ [temp.expl.spec]p6: + // If a template, a member template or the member of a class template is + // explicitly specialized then that spe- cialization shall be declared + // before the first use of that specialization that would cause an implicit + // instantiation to take place, in every translation unit in which such a + // use occurs; no diagnostic is required. + FunctionTemplateSpecializationInfo *SpecInfo + = Specialization->getTemplateSpecializationInfo(); + assert(SpecInfo && "Function template specialization info missing?"); + if (SpecInfo->getPointOfInstantiation().isValid()) { + Diag(FD->getLocation(), diag::err_specialization_after_instantiation) + << FD; + Diag(SpecInfo->getPointOfInstantiation(), + diag::note_instantiation_required_here) + << (Specialization->getTemplateSpecializationKind() + != TSK_ImplicitInstantiation); + return true; + } + + // Mark the prior declaration as an explicit specialization, so that later + // clients know that this is an explicit specialization. + SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization); + + // Turn the given function declaration into a function template + // specialization, with the template arguments from the previous + // specialization. + FD->setFunctionTemplateSpecialization(Context, + Specialization->getPrimaryTemplate(), + new (Context) TemplateArgumentList( + *Specialization->getTemplateSpecializationArgs()), + /*InsertPos=*/0, + TSK_ExplicitSpecialization); + + // The "previous declaration" for this function template specialization is + // the prior function template specialization. + PrevDecl = Specialization; + return false; +} + +/// \brief Perform semantic analysis for the given non-template member +/// specialization. +/// +/// This routine performs all of the semantic analysis required for an +/// explicit member function specialization. On successful completion, +/// the function declaration \p FD will become a member function +/// specialization. +/// +/// \param Member the member declaration, which will be updated to become a +/// specialization. +/// +/// \param PrevDecl the set of declarations, one of which may be specialized +/// by this function specialization. +bool +Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) { + assert(!isa<TemplateDecl>(Member) && "Only for non-template members"); + + // Try to find the member we are instantiating. + NamedDecl *Instantiation = 0; + NamedDecl *InstantiatedFrom = 0; + MemberSpecializationInfo *MSInfo = 0; + + if (!PrevDecl) { + // Nowhere to look anyway. + } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) { + for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl)) { + if (Context.hasSameType(Function->getType(), Method->getType())) { + Instantiation = Method; + InstantiatedFrom = Method->getInstantiatedFromMemberFunction(); + MSInfo = Method->getMemberSpecializationInfo(); + break; + } + } + } + } else if (isa<VarDecl>(Member)) { + if (VarDecl *PrevVar = dyn_cast<VarDecl>(PrevDecl)) + if (PrevVar->isStaticDataMember()) { + Instantiation = PrevDecl; + InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember(); + MSInfo = PrevVar->getMemberSpecializationInfo(); + } + } else if (isa<RecordDecl>(Member)) { + if (CXXRecordDecl *PrevRecord = dyn_cast<CXXRecordDecl>(PrevDecl)) { + Instantiation = PrevDecl; + InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass(); + MSInfo = PrevRecord->getMemberSpecializationInfo(); + } + } + + if (!Instantiation) { + // There is no previous declaration that matches. Since member + // specializations are always out-of-line, the caller will complain about + // this mismatch later. + return false; + } + + // Make sure that this is a specialization of a member. + if (!InstantiatedFrom) { + Diag(Member->getLocation(), diag::err_spec_member_not_instantiated) + << Member; + Diag(Instantiation->getLocation(), diag::note_specialized_decl); + return true; + } + + // C++ [temp.expl.spec]p6: + // If a template, a member template or the member of a class template is + // explicitly specialized then that spe- cialization shall be declared + // before the first use of that specialization that would cause an implicit + // instantiation to take place, in every translation unit in which such a + // use occurs; no diagnostic is required. + assert(MSInfo && "Member specialization info missing?"); + if (MSInfo->getPointOfInstantiation().isValid()) { + Diag(Member->getLocation(), diag::err_specialization_after_instantiation) + << Member; + Diag(MSInfo->getPointOfInstantiation(), + diag::note_instantiation_required_here) + << (MSInfo->getTemplateSpecializationKind() != TSK_ImplicitInstantiation); + return true; + } + + // Check the scope of this explicit specialization. + if (CheckTemplateSpecializationScope(*this, + InstantiatedFrom, + Instantiation, Member->getLocation(), + false, TSK_ExplicitSpecialization)) + return true; + + // Note that this is an explicit instantiation of a member. + // the original declaration to note that it is an explicit specialization + // (if it was previously an implicit instantiation). This latter step + // makes bookkeeping easier. + if (isa<FunctionDecl>(Member)) { + FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation); + if (InstantiationFunction->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationFunction->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationFunction->setLocation(Member->getLocation()); + } + + cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction( + cast<CXXMethodDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); + } else if (isa<VarDecl>(Member)) { + VarDecl *InstantiationVar = cast<VarDecl>(Instantiation); + if (InstantiationVar->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationVar->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationVar->setLocation(Member->getLocation()); + } + + Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member), + cast<VarDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); + } else { + assert(isa<CXXRecordDecl>(Member) && "Only member classes remain"); + CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation); + if (InstantiationClass->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationClass->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationClass->setLocation(Member->getLocation()); + } + + cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( + cast<CXXRecordDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); + } + + // Save the caller the trouble of having to figure out which declaration + // this specialization matches. + PrevDecl = Instantiation; + return false; +} + // Explicit instantiation of a class template specialization +// FIXME: Implement extern template semantics Sema::DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, - unsigned TagSpec, +Sema::ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, TemplateTy TemplateD, @@ -2592,7 +3343,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, AttributeList *Attr) { // Find the class template we're specializing TemplateName Name = TemplateD.getAsVal<TemplateName>(); - ClassTemplateDecl *ClassTemplate + ClassTemplateDecl *ClassTemplate = cast<ClassTemplateDecl>(Name.getAsTemplateDecl()); // Check that the specialization uses the same tag kind as the @@ -2605,29 +3356,21 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, case DeclSpec::TST_class: Kind = TagDecl::TK_class; break; } if (!isAcceptableTagRedeclaration(ClassTemplate->getTemplatedDecl(), - Kind, KWLoc, + Kind, KWLoc, *ClassTemplate->getIdentifier())) { - Diag(KWLoc, diag::err_use_with_wrong_tag) + Diag(KWLoc, diag::err_use_with_wrong_tag) << ClassTemplate - << CodeModificationHint::CreateReplacement(KWLoc, + << CodeModificationHint::CreateReplacement(KWLoc, ClassTemplate->getTemplatedDecl()->getKindName()); - Diag(ClassTemplate->getTemplatedDecl()->getLocation(), + Diag(ClassTemplate->getTemplatedDecl()->getLocation(), diag::note_previous_use); Kind = ClassTemplate->getTemplatedDecl()->getTagKind(); } - // C++0x [temp.explicit]p2: - // [...] An explicit instantiation shall appear in an enclosing - // namespace of its template. [...] - // - // This is C++ DR 275. - if (CheckClassTemplateSpecializationScope(ClassTemplate, 0, - TemplateNameLoc, - SS.getRange(), - /*PartialSpecialization=*/false, - /*ExplicitInstantiation=*/true)) - return true; - + TemplateSpecializationKind TSK + = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition + : TSK_ExplicitInstantiationDeclaration; + // Translate the parser's template argument list in our AST format. llvm::SmallVector<TemplateArgument, 16> TemplateArgs; translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); @@ -2636,35 +3379,47 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // template. TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), TemplateArgs.size()); - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, TemplateArgs.data(), TemplateArgs.size(), RAngleLoc, false, Converted)) return true; - assert((Converted.structuredSize() == + assert((Converted.structuredSize() == ClassTemplate->getTemplateParameters()->size()) && "Converted template argument list is too short!"); - + // Find the class template specialization declaration that // corresponds to these arguments. llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationDecl::Profile(ID, + ClassTemplateSpecializationDecl::Profile(ID, Converted.getFlatArguments(), - Converted.flatSize()); + Converted.flatSize(), + Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + // C++0x [temp.explicit]p2: + // [...] An explicit instantiation shall appear in an enclosing + // namespace of its template. [...] + // + // This is C++ DR 275. + if (CheckTemplateSpecializationScope(*this, ClassTemplate, PrevDecl, + TemplateNameLoc, false, + TSK)) + return true; + ClassTemplateSpecializationDecl *Specialization = 0; bool SpecializationRequiresInstantiation = true; if (PrevDecl) { - if (PrevDecl->getSpecializationKind() == TSK_ExplicitInstantiation) { + if (PrevDecl->getSpecializationKind() + == TSK_ExplicitInstantiationDefinition) { // This particular specialization has already been declared or // instantiated. We cannot explicitly instantiate it. Diag(TemplateNameLoc, diag::err_explicit_instantiation_duplicate) << Context.getTypeDeclType(PrevDecl); - Diag(PrevDecl->getLocation(), + Diag(PrevDecl->getLocation(), diag::note_previous_explicit_instantiation); return DeclPtrTy::make(PrevDecl); } @@ -2676,10 +3431,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // an explicit specialization for that template, the explicit // instantiation has no effect. if (!getLangOptions().CPlusPlus0x) { - Diag(TemplateNameLoc, + Diag(TemplateNameLoc, diag::ext_explicit_instantiation_after_specialization) << Context.getTypeDeclType(PrevDecl); - Diag(PrevDecl->getLocation(), + Diag(PrevDecl->getLocation(), diag::note_previous_template_specialization); } @@ -2689,14 +3444,14 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // accurate reproduction of the source code; we don't actually // use it for anything, since it is semantically irrelevant. Specialization - = ClassTemplateSpecializationDecl::Create(Context, + = ClassTemplateSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), TemplateNameLoc, ClassTemplate, Converted, 0); Specialization->setLexicalDeclContext(CurContext); CurContext->addDecl(Specialization); - return DeclPtrTy::make(Specialization); + return DeclPtrTy::make(PrevDecl); } // If we have already (implicitly) instantiated this @@ -2704,25 +3459,37 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation) SpecializationRequiresInstantiation = false; - // Since the only prior class template specialization with these - // arguments was referenced but not declared, reuse that - // declaration node as our own, updating its source location to - // reflect our new declaration. - Specialization = PrevDecl; - Specialization->setLocation(TemplateNameLoc); - PrevDecl = 0; - } else { + if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation || + PrevDecl->getSpecializationKind() == TSK_Undeclared) { + // Since the only prior class template specialization with these + // arguments was referenced but not declared, reuse that + // declaration node as our own, updating its source location to + // reflect our new declaration. + Specialization = PrevDecl; + Specialization->setLocation(TemplateNameLoc); + PrevDecl = 0; + } + } + + if (!Specialization) { // Create a new class template specialization declaration node for // this explicit specialization. Specialization - = ClassTemplateSpecializationDecl::Create(Context, + = ClassTemplateSpecializationDecl::Create(Context, ClassTemplate->getDeclContext(), TemplateNameLoc, ClassTemplate, - Converted, 0); + Converted, PrevDecl); - ClassTemplate->getSpecializations().InsertNode(Specialization, - InsertPos); + if (PrevDecl) { + // Remove the previous declaration from the folding set, since we want + // to introduce a new declaration. + ClassTemplate->getSpecializations().RemoveNode(PrevDecl); + ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + } + + // Insert the new specialization. + ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); } // Build the fully-sugared type for this explicit instantiation as @@ -2732,8 +3499,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // the explicit instantiation, rather than formatting the name based // on the "canonical" representation used to store the template // arguments in the specialization. - QualType WrittenTy - = Context.getTemplateSpecializationType(Name, + QualType WrittenTy + = Context.getTemplateSpecializationType(Name, TemplateArgs.data(), TemplateArgs.size(), Context.getTypeDeclType(Specialization)); @@ -2746,6 +3513,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, Specialization->setLexicalDeclContext(CurContext); CurContext->addDecl(Specialization); + Specialization->setPointOfInstantiation(TemplateNameLoc); + // C++ [temp.explicit]p3: // A definition of a class template or class member template // shall be in scope at the point of the explicit instantiation of @@ -2754,17 +3523,20 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // This check comes when we actually try to perform the // instantiation. if (SpecializationRequiresInstantiation) - InstantiateClassTemplateSpecialization(Specialization, true); + InstantiateClassTemplateSpecialization(Specialization, TSK); else // Instantiate the members of this class template specialization. - InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization); + InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization, + TSK); return DeclPtrTy::make(Specialization); } // Explicit instantiation of a member class of a class template. Sema::DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, - unsigned TagSpec, +Sema::ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, IdentifierInfo *Name, @@ -2772,8 +3544,13 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, AttributeList *Attr) { bool Owned = false; - DeclPtrTy TagD = ActOnTag(S, TagSpec, Action::TK_Reference, - KWLoc, SS, Name, NameLoc, Attr, AS_none, Owned); + bool IsDependent = false; + DeclPtrTy TagD = ActOnTag(S, TagSpec, Action::TUK_Reference, + KWLoc, SS, Name, NameLoc, Attr, AS_none, + MultiTemplateParamsArg(*this, 0, 0), + Owned, IsDependent); + assert(!IsDependent && "explicit instantiation of dependent name not yet handled"); + if (!TagD) return true; @@ -2804,7 +3581,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, if (getLangOptions().CPlusPlus0x) { // FIXME: In C++98, we would like to turn these errors into warnings, // dependent on a -Wc++0x flag. - DeclContext *PatternContext + DeclContext *PatternContext = Pattern->getDeclContext()->getEnclosingNamespaceContext(); if (!CurContext->Encloses(PatternContext)) { Diag(TemplateLoc, diag::err_explicit_instantiation_out_of_scope) @@ -2813,17 +3590,21 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, } } + TemplateSpecializationKind TSK + = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition + : TSK_ExplicitInstantiationDeclaration; + if (!Record->getDefinition(Context)) { // If the class has a definition, instantiate it (and all of its // members, recursively). Pattern = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context)); - if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern, + if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern, getTemplateInstantiationArgs(Record), - /*ExplicitInstantiation=*/true)) + TSK)) return true; - } else // Instantiate all of the members of class. - InstantiateClassMembers(TemplateLoc, Record, - getTemplateInstantiationArgs(Record)); + } else // Instantiate all of the members of the class. + InstantiateClassMembers(TemplateLoc, Record, + getTemplateInstantiationArgs(Record), TSK); // FIXME: We don't have any representation for explicit instantiations of // member classes. Such a representation is not needed for compilation, but it @@ -2832,10 +3613,221 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, return TagD; } +Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, + SourceLocation ExternLoc, + SourceLocation TemplateLoc, + Declarator &D) { + // Explicit instantiations always require a name. + DeclarationName Name = GetNameForDeclarator(D); + if (!Name) { + if (!D.isInvalidType()) + Diag(D.getDeclSpec().getSourceRange().getBegin(), + diag::err_explicit_instantiation_requires_name) + << D.getDeclSpec().getSourceRange() + << D.getSourceRange(); + + return true; + } + + // The scope passed in may not be a decl scope. Zip up the scope tree until + // we find one that is. + while ((S->getFlags() & Scope::DeclScope) == 0 || + (S->getFlags() & Scope::TemplateParamScope) != 0) + S = S->getParent(); + + // Determine the type of the declaration. + QualType R = GetTypeForDeclarator(D, S, 0); + if (R.isNull()) + return true; + + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { + // Cannot explicitly instantiate a typedef. + Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_of_typedef) + << Name; + return true; + } + + // Determine what kind of explicit instantiation we have. + TemplateSpecializationKind TSK + = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition + : TSK_ExplicitInstantiationDeclaration; + + LookupResult Previous; + LookupParsedName(Previous, S, &D.getCXXScopeSpec(), + Name, LookupOrdinaryName); + + if (!R->isFunctionType()) { + // C++ [temp.explicit]p1: + // A [...] static data member of a class template can be explicitly + // instantiated from the member definition associated with its class + // template. + if (Previous.isAmbiguous()) { + return DiagnoseAmbiguousLookup(Previous, Name, D.getIdentifierLoc(), + D.getSourceRange()); + } + + VarDecl *Prev = dyn_cast_or_null<VarDecl>( + Previous.getAsSingleDecl(Context)); + if (!Prev || !Prev->isStaticDataMember()) { + // We expect to see a data data member here. + Diag(D.getIdentifierLoc(), diag::err_explicit_instantiation_not_known) + << Name; + for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); + P != PEnd; ++P) + Diag((*P)->getLocation(), diag::note_explicit_instantiation_here); + return true; + } + + if (!Prev->getInstantiatedFromStaticDataMember()) { + // FIXME: Check for explicit specialization? + Diag(D.getIdentifierLoc(), + diag::err_explicit_instantiation_data_member_not_instantiated) + << Prev; + Diag(Prev->getLocation(), diag::note_explicit_instantiation_here); + // FIXME: Can we provide a note showing where this was declared? + return true; + } + + // Instantiate static data member. + // FIXME: Check for prior specializations and such. + Prev->setTemplateSpecializationKind(TSK); + if (TSK == TSK_ExplicitInstantiationDefinition) + InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false); + + // FIXME: Create an ExplicitInstantiation node? + return DeclPtrTy(); + } + + // If the declarator is a template-id, translate the parser's template + // argument list into our AST format. + bool HasExplicitTemplateArgs = false; + llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + if (D.getKind() == Declarator::DK_TemplateId) { + TemplateIdAnnotation *TemplateId = D.getTemplateId(); + ASTTemplateArgsPtr TemplateArgsPtr(*this, + TemplateId->getTemplateArgs(), + TemplateId->getTemplateArgIsType(), + TemplateId->NumArgs); + translateTemplateArguments(TemplateArgsPtr, + TemplateId->getTemplateArgLocations(), + TemplateArgs); + HasExplicitTemplateArgs = true; + TemplateArgsPtr.release(); + } + + // C++ [temp.explicit]p1: + // A [...] function [...] can be explicitly instantiated from its template. + // A member function [...] of a class template can be explicitly + // instantiated from the member definition associated with its class + // template. + llvm::SmallVector<FunctionDecl *, 8> Matches; + for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); + P != PEnd; ++P) { + NamedDecl *Prev = *P; + if (!HasExplicitTemplateArgs) { + if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(Prev)) { + if (Context.hasSameUnqualifiedType(Method->getType(), R)) { + Matches.clear(); + Matches.push_back(Method); + break; + } + } + } + + FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Prev); + if (!FunTmpl) + continue; + + TemplateDeductionInfo Info(Context); + FunctionDecl *Specialization = 0; + if (TemplateDeductionResult TDK + = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs, + TemplateArgs.data(), TemplateArgs.size(), + R, Specialization, Info)) { + // FIXME: Keep track of almost-matches? + (void)TDK; + continue; + } + + Matches.push_back(Specialization); + } + + // Find the most specialized function template specialization. + FunctionDecl *Specialization + = getMostSpecialized(Matches.data(), Matches.size(), TPOC_Other, + D.getIdentifierLoc(), + PartialDiagnostic(diag::err_explicit_instantiation_not_known) << Name, + PartialDiagnostic(diag::err_explicit_instantiation_ambiguous) << Name, + PartialDiagnostic(diag::note_explicit_instantiation_candidate)); + + if (!Specialization) + return true; + + switch (Specialization->getTemplateSpecializationKind()) { + case TSK_Undeclared: + Diag(D.getIdentifierLoc(), + diag::err_explicit_instantiation_member_function_not_instantiated) + << Specialization + << (Specialization->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization); + Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here); + return true; + + case TSK_ExplicitSpecialization: + // C++ [temp.explicit]p4: + // For a given set of template parameters, if an explicit instantiation + // of a template appears after a declaration of an explicit + // specialization for that template, the explicit instantiation has no + // effect. + break; + + case TSK_ExplicitInstantiationDefinition: + // FIXME: Check that we aren't trying to perform an explicit instantiation + // declaration now. + // Fall through + + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + // Instantiate the function, if this is an explicit instantiation + // definition. + if (TSK == TSK_ExplicitInstantiationDefinition) + InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization, + false); + + Specialization->setTemplateSpecializationKind(TSK); + break; + } + + // FIXME: Create some kind of ExplicitInstantiationDecl here. + return DeclPtrTy(); +} + +Sema::TypeResult +Sema::ActOnDependentTag(Scope *S, unsigned TagSpec, TagUseKind TUK, + const CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation TagLoc, SourceLocation NameLoc) { + // This has to hold, because SS is expected to be defined. + assert(Name && "Expected a name in a dependent tag"); + + NestedNameSpecifier *NNS + = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); + if (!NNS) + return true; + + QualType T = CheckTypenameType(NNS, *Name, SourceRange(TagLoc, NameLoc)); + if (T.isNull()) + return true; + + TagDecl::TagKind TagKind = TagDecl::getTagKindForTypeSpec(TagSpec); + QualType ElabType = Context.getElaboratedType(T, TagKind); + + return ElabType.getAsOpaquePtr(); +} + Sema::TypeResult Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, const IdentifierInfo &II, SourceLocation IdLoc) { - NestedNameSpecifier *NNS + NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); if (!NNS) return true; @@ -2849,17 +3841,23 @@ Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, Sema::TypeResult Sema::ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, SourceLocation TemplateLoc, TypeTy *Ty) { - QualType T = QualType::getFromOpaquePtr(Ty); - NestedNameSpecifier *NNS + QualType T = GetTypeFromParser(Ty); + NestedNameSpecifier *NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); - const TemplateSpecializationType *TemplateId - = T->getAsTemplateSpecializationType(); + const TemplateSpecializationType *TemplateId + = T->getAs<TemplateSpecializationType>(); assert(TemplateId && "Expected a template specialization type"); - if (NNS->isDependent()) - return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr(); + if (computeDeclContext(SS, false)) { + // If we can compute a declaration context, then the "typename" + // keyword was superfluous. Just build a QualifiedNameType to keep + // track of the nested-name-specifier. - return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr(); + // FIXME: Note that the QualifiedNameType had the "typename" keyword! + return Context.getQualifiedNameType(NNS, T).getAsOpaquePtr(); + } + + return Context.getTypenameType(NNS, TemplateId).getAsOpaquePtr(); } /// \brief Build the type that describes a C++ typename specifier, @@ -2875,6 +3873,12 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, // instantiation, then build a typename type. if (!CurrentInstantiation) return Context.getTypenameType(NNS, &II); + + // The nested-name-specifier refers to the current instantiation, so the + // "typename" keyword itself is superfluous. In C++03, the program is + // actually ill-formed. However, DR 382 (in C++0x CD1) allows such + // extraneous "typename" keywords, and we retroactively apply this DR to + // C++03 code. } DeclContext *Ctx = 0; @@ -2893,20 +3897,17 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, assert(Ctx && "No declaration context?"); DeclarationName Name(&II); - LookupResult Result = LookupQualifiedName(Ctx, Name, LookupOrdinaryName, - false); + LookupResult Result; + LookupQualifiedName(Result, Ctx, Name, LookupOrdinaryName, false); unsigned DiagID = 0; Decl *Referenced = 0; switch (Result.getKind()) { case LookupResult::NotFound: - if (Ctx->isTranslationUnit()) - DiagID = diag::err_typename_nested_not_found_global; - else - DiagID = diag::err_typename_nested_not_found; + DiagID = diag::err_typename_nested_not_found; break; case LookupResult::Found: - if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getAsDecl())) { + if (TypeDecl *Type = dyn_cast<TypeDecl>(Result.getFoundDecl())) { // We found a type. Build a QualifiedNameType, since the // typename-specifier was just sugar. FIXME: Tell // QualifiedNameType that it has a "typename" prefix. @@ -2914,7 +3915,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, } DiagID = diag::err_typename_nested_not_type; - Referenced = Result.getAsDecl(); + Referenced = Result.getFoundDecl(); break; case LookupResult::FoundOverloaded: @@ -2922,21 +3923,207 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, Referenced = *Result.begin(); break; - case LookupResult::AmbiguousBaseSubobjectTypes: - case LookupResult::AmbiguousBaseSubobjects: - case LookupResult::AmbiguousReference: + case LookupResult::Ambiguous: DiagnoseAmbiguousLookup(Result, Name, Range.getEnd(), Range); return QualType(); } // If we get here, it's because name lookup did not find a // type. Emit an appropriate diagnostic and return an error. - if (NamedDecl *NamedCtx = dyn_cast<NamedDecl>(Ctx)) - Diag(Range.getEnd(), DiagID) << Range << Name << NamedCtx; - else - Diag(Range.getEnd(), DiagID) << Range << Name; + Diag(Range.getEnd(), DiagID) << Range << Name << Ctx; if (Referenced) Diag(Referenced->getLocation(), diag::note_typename_refers_here) << Name; return QualType(); } + +namespace { + // See Sema::RebuildTypeInCurrentInstantiation + class VISIBILITY_HIDDEN CurrentInstantiationRebuilder + : public TreeTransform<CurrentInstantiationRebuilder> { + SourceLocation Loc; + DeclarationName Entity; + + public: + CurrentInstantiationRebuilder(Sema &SemaRef, + SourceLocation Loc, + DeclarationName Entity) + : TreeTransform<CurrentInstantiationRebuilder>(SemaRef), + Loc(Loc), Entity(Entity) { } + + /// \brief Determine whether the given type \p T has already been + /// transformed. + /// + /// For the purposes of type reconstruction, a type has already been + /// transformed if it is NULL or if it is not dependent. + bool AlreadyTransformed(QualType T) { + return T.isNull() || !T->isDependentType(); + } + + /// \brief Returns the location of the entity whose type is being + /// rebuilt. + SourceLocation getBaseLocation() { return Loc; } + + /// \brief Returns the name of the entity whose type is being rebuilt. + DeclarationName getBaseEntity() { return Entity; } + + /// \brief Transforms an expression by returning the expression itself + /// (an identity function). + /// + /// FIXME: This is completely unsafe; we will need to actually clone the + /// expressions. + Sema::OwningExprResult TransformExpr(Expr *E) { + return getSema().Owned(E); + } + + /// \brief Transforms a typename type by determining whether the type now + /// refers to a member of the current instantiation, and then + /// type-checking and building a QualifiedNameType (when possible). + QualType TransformTypenameType(const TypenameType *T); + }; +} + +QualType +CurrentInstantiationRebuilder::TransformTypenameType(const TypenameType *T) { + NestedNameSpecifier *NNS + = TransformNestedNameSpecifier(T->getQualifier(), + /*FIXME:*/SourceRange(getBaseLocation())); + if (!NNS) + return QualType(); + + // If the nested-name-specifier did not change, and we cannot compute the + // context corresponding to the nested-name-specifier, then this + // typename type will not change; exit early. + CXXScopeSpec SS; + SS.setRange(SourceRange(getBaseLocation())); + SS.setScopeRep(NNS); + if (NNS == T->getQualifier() && getSema().computeDeclContext(SS) == 0) + return QualType(T, 0); + + // Rebuild the typename type, which will probably turn into a + // QualifiedNameType. + if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) { + QualType NewTemplateId + = TransformType(QualType(TemplateId, 0)); + if (NewTemplateId.isNull()) + return QualType(); + + if (NNS == T->getQualifier() && + NewTemplateId == QualType(TemplateId, 0)) + return QualType(T, 0); + + return getDerived().RebuildTypenameType(NNS, NewTemplateId); + } + + return getDerived().RebuildTypenameType(NNS, T->getIdentifier()); +} + +/// \brief Rebuilds a type within the context of the current instantiation. +/// +/// The type \p T is part of the type of an out-of-line member definition of +/// a class template (or class template partial specialization) that was parsed +/// and constructed before we entered the scope of the class template (or +/// partial specialization thereof). This routine will rebuild that type now +/// that we have entered the declarator's scope, which may produce different +/// canonical types, e.g., +/// +/// \code +/// template<typename T> +/// struct X { +/// typedef T* pointer; +/// pointer data(); +/// }; +/// +/// template<typename T> +/// typename X<T>::pointer X<T>::data() { ... } +/// \endcode +/// +/// Here, the type "typename X<T>::pointer" will be created as a TypenameType, +/// since we do not know that we can look into X<T> when we parsed the type. +/// This function will rebuild the type, performing the lookup of "pointer" +/// in X<T> and returning a QualifiedNameType whose canonical type is the same +/// as the canonical type of T*, allowing the return types of the out-of-line +/// definition and the declaration to match. +QualType Sema::RebuildTypeInCurrentInstantiation(QualType T, SourceLocation Loc, + DeclarationName Name) { + if (T.isNull() || !T->isDependentType()) + return T; + + CurrentInstantiationRebuilder Rebuilder(*this, Loc, Name); + return Rebuilder.TransformType(T); +} + +/// \brief Produces a formatted string that describes the binding of +/// template parameters to template arguments. +std::string +Sema::getTemplateArgumentBindingsText(const TemplateParameterList *Params, + const TemplateArgumentList &Args) { + std::string Result; + + if (!Params || Params->size() == 0) + return Result; + + for (unsigned I = 0, N = Params->size(); I != N; ++I) { + if (I == 0) + Result += "[with "; + else + Result += ", "; + + if (const IdentifierInfo *Id = Params->getParam(I)->getIdentifier()) { + Result += Id->getName(); + } else { + Result += '$'; + Result += llvm::utostr(I); + } + + Result += " = "; + + switch (Args[I].getKind()) { + case TemplateArgument::Null: + Result += "<no value>"; + break; + + case TemplateArgument::Type: { + std::string TypeStr; + Args[I].getAsType().getAsStringInternal(TypeStr, + Context.PrintingPolicy); + Result += TypeStr; + break; + } + + case TemplateArgument::Declaration: { + bool Unnamed = true; + if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(Args[I].getAsDecl())) { + if (ND->getDeclName()) { + Unnamed = false; + Result += ND->getNameAsString(); + } + } + + if (Unnamed) { + Result += "<anonymous>"; + } + break; + } + + case TemplateArgument::Integral: { + Result += Args[I].getAsIntegral()->toString(10); + break; + } + + case TemplateArgument::Expression: { + assert(false && "No expressions in deduced template arguments!"); + Result += "<expression>"; + break; + } + + case TemplateArgument::Pack: + // FIXME: Format template argument packs + Result += "<template argument pack>"; + break; + } + } + + Result += ']'; + return Result; +} |