diff options
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 723 |
1 files changed, 501 insertions, 222 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 31cd300..f47577e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -20,7 +20,6 @@ #include "clang/Parse/Template.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" -#include "llvm/Support/Compiler.h" #include "llvm/ADT/StringExtras.h" using namespace clang; @@ -59,44 +58,20 @@ static NamedDecl *isAcceptableTemplateName(ASTContext &Context, NamedDecl *D) { 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; - } - - 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 0; +} - return FuncTmpl; - } +static void FilterAcceptableTemplateNames(ASTContext &C, LookupResult &R) { + LookupResult::Filter filter = R.makeFilter(); + while (filter.hasNext()) { + NamedDecl *Orig = filter.next(); + NamedDecl *Repl = isAcceptableTemplateName(C, Orig->getUnderlyingDecl()); + if (!Repl) + filter.erase(); + else if (Repl != Orig) + filter.replace(Repl); } - - return 0; + filter.done(); } TemplateNameKind Sema::isTemplateName(Scope *S, @@ -117,18 +92,65 @@ TemplateNameKind Sema::isTemplateName(Scope *S, Name.OperatorFunctionId.Operator); break; + case UnqualifiedId::IK_LiteralOperatorId: + TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier); + break; + default: return TNK_Non_template; } - + + QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); + + LookupResult R(*this, TName, SourceLocation(), LookupOrdinaryName); + R.suppressDiagnostics(); + LookupTemplateName(R, S, SS, ObjectType, EnteringContext); + if (R.empty()) + return TNK_Non_template; + + NamedDecl *Template = R.getAsSingleDecl(Context); + + if (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; +} + +void Sema::LookupTemplateName(LookupResult &Found, + Scope *S, const CXXScopeSpec &SS, + QualType ObjectType, + bool EnteringContext) { // Determine where to perform name lookup DeclContext *LookupCtx = 0; bool isDependent = false; - if (ObjectTypePtr) { + if (!ObjectType.isNull()) { // 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.isSet() && "ObjectType and scope specifier cannot coexist"); - QualType ObjectType = QualType::getFromOpaquePtr(ObjectTypePtr); LookupCtx = computeDeclContext(ObjectType); isDependent = ObjectType->isDependentType(); assert((isDependent || !ObjectType->isIncompleteType()) && @@ -141,10 +163,9 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // The declaration context must be complete. if (LookupCtx && RequireCompleteDeclContext(SS)) - return TNK_Non_template; + return; } - LookupResult Found(*this, TName, SourceLocation(), LookupOrdinaryName); bool ObjectTypeSearchedInScope = false; if (LookupCtx) { // Perform "qualified" name lookup into the declaration context we @@ -153,7 +174,7 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // nested-name-specifier. LookupQualifiedName(Found, LookupCtx); - if (ObjectTypePtr && Found.empty()) { + if (!ObjectType.isNull() && Found.empty()) { // 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 @@ -166,12 +187,12 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // // FIXME: When we're instantiating a template, do we actually have to // look in the scope of the template? Seems fishy... - LookupName(Found, S); + if (S) LookupName(Found, S); ObjectTypeSearchedInScope = true; } } else if (isDependent) { // We cannot look into a dependent object type or - return TNK_Non_template; + return; } else { // Perform unqualified name lookup in the current scope. LookupName(Found, S); @@ -181,27 +202,26 @@ TemplateNameKind Sema::isTemplateName(Scope *S, assert(!Found.isAmbiguous() && "Cannot handle template name-lookup ambiguities"); - NamedDecl *Template - = isAcceptableTemplateName(Context, Found.getAsSingleDecl(Context)); - if (!Template) - return TNK_Non_template; + FilterAcceptableTemplateNames(Context, Found); + if (Found.empty()) + return; - if (ObjectTypePtr && !ObjectTypeSearchedInScope) { + if (S && !ObjectType.isNull() && !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(*this, TName, SourceLocation(), LookupOrdinaryName); + LookupResult FoundOuter(*this, Found.getLookupName(), Found.getNameLoc(), + LookupOrdinaryName); LookupName(FoundOuter, S); + FilterAcceptableTemplateNames(Context, FoundOuter); // FIXME: Handle ambiguities in this lookup better - NamedDecl *OuterTemplate - = isAcceptableTemplateName(Context, FoundOuter.getAsSingleDecl(Context)); - if (!OuterTemplate) { + if (FoundOuter.empty()) { // - if the name is not found, the name found in the class of the // object expression is used, otherwise - } else if (!isa<ClassTemplateDecl>(OuterTemplate)) { + } else if (!FoundOuter.getAsSingle<ClassTemplateDecl>()) { // - 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 @@ -209,49 +229,165 @@ TemplateNameKind Sema::isTemplateName(Scope *S, // - 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(Name.getSourceRange().getBegin(), + if (!Found.isSingleResult() || + Found.getFoundDecl()->getCanonicalDecl() + != FoundOuter.getFoundDecl()->getCanonicalDecl()) { + Diag(Found.getNameLoc(), diag::err_nested_name_member_ref_lookup_ambiguous) - << TName - << Name.getSourceRange(); - Diag(Template->getLocation(), diag::note_ambig_member_ref_object_type) - << QualType::getFromOpaquePtr(ObjectTypePtr); - Diag(OuterTemplate->getLocation(), diag::note_ambig_member_ref_scope); + << Found.getLookupName(); + Diag(Found.getRepresentativeDecl()->getLocation(), + diag::note_ambig_member_ref_object_type) + << ObjectType; + Diag(FoundOuter.getFoundDecl()->getLocation(), + diag::note_ambig_member_ref_scope); // Recover by taking the template that we found in the object // expression's type. } } } +} - if (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))); +/// Constructs a full type for the given nested-name-specifier. +static QualType GetTypeForQualifier(ASTContext &Context, + NestedNameSpecifier *Qualifier) { + // Three possibilities: + + // 1. A namespace (global or not). + assert(!Qualifier->getAsNamespace() && "can't construct type for namespace"); + + // 2. A type (templated or not). + Type *Ty = Qualifier->getAsType(); + if (Ty) return QualType(Ty, 0); + + // 3. A dependent identifier. + assert(Qualifier->getAsIdentifier()); + return Context.getTypenameType(Qualifier->getPrefix(), + Qualifier->getAsIdentifier()); +} + +static bool HasDependentTypeAsBase(ASTContext &Context, + CXXRecordDecl *Record, + CanQualType T) { + for (CXXRecordDecl::base_class_iterator I = Record->bases_begin(), + E = Record->bases_end(); I != E; ++I) { + CanQualType BaseT = Context.getCanonicalType((*I).getType()); + if (BaseT == T) + return true; + + // We have to recurse here to cover some really bizarre cases. + // Obviously, we can only have the dependent type as an indirect + // base class through a dependent base class, and usually it's + // impossible to know which instantiation a dependent base class + // will have. But! If we're actually *inside* the dependent base + // class, then we know its instantiation and can therefore be + // reasonably expected to look into it. + + // template <class T> class A : Base<T> { + // class Inner : A<T> { + // void foo() { + // Base<T>::foo(); // statically known to be an implicit member + // reference + // } + // }; + // }; + + CanQual<RecordType> RT = BaseT->getAs<RecordType>(); + + // Base might be a dependent member type, in which case we + // obviously can't look into it. + if (!RT) continue; + + CXXRecordDecl *BaseRecord = cast<CXXRecordDecl>(RT->getDecl()); + if (BaseRecord->isDefinition() && + HasDependentTypeAsBase(Context, BaseRecord, T)) + return true; } - if (isa<ClassTemplateDecl>(Template) || - isa<TemplateTemplateParmDecl>(Template)) - return TNK_Type_template; + return false; +} - assert((isa<FunctionTemplateDecl>(Template) || - isa<OverloadedFunctionDecl>(Template)) && - "Unhandled template kind in Sema::isTemplateName"); - return TNK_Function_template; +/// Checks whether the given dependent nested-name specifier +/// introduces an implicit member reference. This is only true if the +/// nested-name specifier names a type identical to one of the current +/// instance method's context's (possibly indirect) base classes. +static bool IsImplicitDependentMemberReference(Sema &SemaRef, + NestedNameSpecifier *Qualifier, + QualType &ThisType) { + // If the context isn't a C++ method, then it isn't an implicit + // member reference. + CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(SemaRef.CurContext); + if (!MD || MD->isStatic()) + return false; + + ASTContext &Context = SemaRef.Context; + + // We want to check whether the method's context is known to inherit + // from the type named by the nested name specifier. The trivial + // case here is: + // template <class T> class Base { ... }; + // template <class T> class Derived : Base<T> { + // void foo() { + // Base<T>::foo(); + // } + // }; + + QualType QT = GetTypeForQualifier(Context, Qualifier); + CanQualType T = Context.getCanonicalType(QT); + + // And now, just walk the non-dependent type hierarchy, trying to + // find the given type as a literal base class. + CXXRecordDecl *Record = cast<CXXRecordDecl>(MD->getParent()); + if (Context.getCanonicalType(Context.getTypeDeclType(Record)) == T || + HasDependentTypeAsBase(Context, Record, T)) { + ThisType = MD->getThisType(Context); + return true; + } + + return false; +} + +/// ActOnDependentIdExpression - Handle a dependent declaration name +/// that was just parsed. +Sema::OwningExprResult +Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + bool CheckForImplicitMember, + const TemplateArgumentListInfo *TemplateArgs) { + NestedNameSpecifier *Qualifier + = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + + QualType ThisType; + if (CheckForImplicitMember && + IsImplicitDependentMemberReference(*this, Qualifier, ThisType)) { + Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); + + // Since the 'this' expression is synthesized, we don't need to + // perform the double-lookup check. + NamedDecl *FirstQualifierInScope = 0; + + return Owned(CXXDependentScopeMemberExpr::Create(Context, This, true, + /*Op*/ SourceLocation(), + Qualifier, SS.getRange(), + FirstQualifierInScope, + Name, NameLoc, + TemplateArgs)); + } + + return BuildDependentDeclRefExpr(SS, Name, NameLoc, TemplateArgs); +} + +Sema::OwningExprResult +Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo *TemplateArgs) { + return Owned(DependentScopeDeclRefExpr::Create(Context, + static_cast<NestedNameSpecifier*>(SS.getScopeRep()), + SS.getRange(), + Name, NameLoc, + TemplateArgs)); } /// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining @@ -317,12 +453,11 @@ static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, /// \brief Translates template arguments as provided by the parser /// into template arguments used by semantic analysis. -void Sema::translateTemplateArguments(ASTTemplateArgsPtr &TemplateArgsIn, - llvm::SmallVectorImpl<TemplateArgumentLoc> &TemplateArgs) { - TemplateArgs.reserve(TemplateArgsIn.size()); - +void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, + TemplateArgumentListInfo &TemplateArgs) { for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) - TemplateArgs.push_back(translateTemplateArgument(*this, TemplateArgsIn[I])); + TemplateArgs.addArgument(translateTemplateArgument(*this, + TemplateArgsIn[I])); } /// ActOnTypeParameter - Called when a C++ template type parameter @@ -595,7 +730,7 @@ Sema::ActOnTemplateParameterList(unsigned Depth, DeclPtrTy *Params, unsigned NumParams, SourceLocation RAngleLoc) { if (ExportLoc.isValid()) - Diag(ExportLoc, diag::note_template_export_unsupported); + Diag(ExportLoc, diag::warn_template_export_unsupported); return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, (NamedDecl**)Params, NumParams, @@ -756,7 +891,8 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, // merging in the template parameter list from the previous class // template declaration. if (CheckTemplateParameterList(TemplateParams, - PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0)) + PrevClassTemplate? PrevClassTemplate->getTemplateParameters() : 0, + TPC_ClassTemplate)) Invalid = true; // FIXME: If we had a scope specifier, we better have a previous template @@ -837,6 +973,55 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, return DeclPtrTy::make(NewTemplate); } +/// \brief Diagnose the presence of a default template argument on a +/// template parameter, which is ill-formed in certain contexts. +/// +/// \returns true if the default template argument should be dropped. +static bool DiagnoseDefaultTemplateArgument(Sema &S, + Sema::TemplateParamListContext TPC, + SourceLocation ParamLoc, + SourceRange DefArgRange) { + switch (TPC) { + case Sema::TPC_ClassTemplate: + return false; + + case Sema::TPC_FunctionTemplate: + // C++ [temp.param]p9: + // A default template-argument shall not be specified in a + // function template declaration or a function template + // definition [...] + // (This sentence is not in C++0x, per DR226). + if (!S.getLangOptions().CPlusPlus0x) + S.Diag(ParamLoc, + diag::err_template_parameter_default_in_function_template) + << DefArgRange; + return false; + + case Sema::TPC_ClassTemplateMember: + // C++0x [temp.param]p9: + // A default template-argument shall not be specified in the + // template-parameter-lists of the definition of a member of a + // class template that appears outside of the member's class. + S.Diag(ParamLoc, diag::err_template_parameter_default_template_member) + << DefArgRange; + return true; + + case Sema::TPC_FriendFunctionTemplate: + // C++ [temp.param]p9: + // A default template-argument shall not be specified in a + // friend template declaration. + S.Diag(ParamLoc, diag::err_template_parameter_default_friend_template) + << DefArgRange; + return true; + + // FIXME: C++0x [temp.param]p9 allows default template-arguments + // for friend function templates if there is only a single + // declaration (and it is a definition). Strange! + } + + return false; +} + /// \brief Checks the validity of a template parameter list, possibly /// considering the template parameter list from a previous /// declaration. @@ -855,9 +1040,13 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, /// arguments will be merged from the old template parameter list to /// the new template parameter list. /// +/// \param TPC Describes the context in which we are checking the given +/// template parameter list. +/// /// \returns true if an error occurred, false otherwise. bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, - TemplateParameterList *OldParams) { + TemplateParameterList *OldParams, + TemplateParamListContext TPC) { bool Invalid = false; // C++ [temp.param]p10: @@ -897,9 +1086,17 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, Invalid = true; } - // Merge default arguments for template type parameters. if (TemplateTypeParmDecl *NewTypeParm = dyn_cast<TemplateTypeParmDecl>(*NewParam)) { + // Check the presence of a default argument here. + if (NewTypeParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewTypeParm->getLocation(), + NewTypeParm->getDefaultArgumentInfo()->getTypeLoc() + .getFullSourceRange())) + NewTypeParm->removeDefaultArgument(); + + // Merge default arguments for template type parameters. TemplateTypeParmDecl *OldTypeParm = OldParams? cast<TemplateTypeParmDecl>(*OldParam) : 0; @@ -929,6 +1126,15 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, MissingDefaultArg = true; } else if (NonTypeTemplateParmDecl *NewNonTypeParm = dyn_cast<NonTypeTemplateParmDecl>(*NewParam)) { + // Check the presence of a default argument here. + if (NewNonTypeParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewNonTypeParm->getLocation(), + NewNonTypeParm->getDefaultArgument()->getSourceRange())) { + NewNonTypeParm->getDefaultArgument()->Destroy(Context); + NewNonTypeParm->setDefaultArgument(0); + } + // Merge default arguments for non-type template parameters NonTypeTemplateParmDecl *OldNonTypeParm = OldParams? cast<NonTypeTemplateParmDecl>(*OldParam) : 0; @@ -955,9 +1161,16 @@ bool Sema::CheckTemplateParameterList(TemplateParameterList *NewParams, } else if (SawDefaultArgument) MissingDefaultArg = true; } else { - // Merge default arguments for template template parameters + // Check the presence of a default argument here. TemplateTemplateParmDecl *NewTemplateParm = cast<TemplateTemplateParmDecl>(*NewParam); + if (NewTemplateParm->hasDefaultArgument() && + DiagnoseDefaultTemplateArgument(*this, TPC, + NewTemplateParm->getLocation(), + NewTemplateParm->getDefaultArgument().getSourceRange())) + NewTemplateParm->setDefaultArgument(TemplateArgumentLoc()); + + // Merge default arguments for template template parameters TemplateTemplateParmDecl *OldTemplateParm = OldParams? cast<TemplateTemplateParmDecl>(*OldParam) : 0; if (OldTemplateParm && OldTemplateParm->hasDefaultArgument() && @@ -1049,6 +1262,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // template-ids will match up with the template parameter lists. llvm::SmallVector<const TemplateSpecializationType *, 4> TemplateIdsInSpecifier; + llvm::SmallVector<ClassTemplateSpecializationDecl *, 4> + ExplicitSpecializationsInSpecifier; for (NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep(); NNS; NNS = NNS->getPrefix()) { if (const TemplateSpecializationType *SpecType @@ -1062,10 +1277,10 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, = 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) + if (SpecDecl->getSpecializationKind() == TSK_ExplicitSpecialization) { + ExplicitSpecializationsInSpecifier.push_back(SpecDecl); continue; + } } TemplateIdsInSpecifier.push_back(SpecType); @@ -1128,6 +1343,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, ExpectedTemplateParams, true, TPL_TemplateMatch); } + + CheckTemplateParameterList(ParamLists[Idx], 0, TPC_ClassTemplateMember); } else if (ParamLists[Idx]->size() > 0) Diag(ParamLists[Idx]->getTemplateLoc(), diag::err_template_param_list_matches_nontemplate) @@ -1146,10 +1363,20 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // If there were too many template parameter lists, complain about that now. if (Idx != NumParamLists - 1) { while (Idx < NumParamLists - 1) { + bool isExplicitSpecHeader = ParamLists[Idx]->size() == 0; Diag(ParamLists[Idx]->getTemplateLoc(), - diag::err_template_spec_extra_headers) + isExplicitSpecHeader? diag::warn_template_spec_extra_headers + : diag::err_template_spec_extra_headers) << SourceRange(ParamLists[Idx]->getTemplateLoc(), ParamLists[Idx]->getRAngleLoc()); + + if (isExplicitSpecHeader && !ExplicitSpecializationsInSpecifier.empty()) { + Diag(ExplicitSpecializationsInSpecifier.back()->getLocation(), + diag::note_explicit_template_spec_does_not_need_header) + << ExplicitSpecializationsInSpecifier.back(); + ExplicitSpecializationsInSpecifier.pop_back(); + } + ++Idx; } } @@ -1161,24 +1388,19 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) { + const TemplateArgumentListInfo &TemplateArgs) { TemplateDecl *Template = Name.getAsTemplateDecl(); if (!Template) { // The template name does not resolve to a template, so we just // build a dependent template-id type. - return Context.getTemplateSpecializationType(Name, TemplateArgs, - NumTemplateArgs); + return Context.getTemplateSpecializationType(Name, TemplateArgs); } // Check that the template argument list is well-formed for this // template. TemplateArgumentListBuilder Converted(Template->getTemplateParameters(), - NumTemplateArgs); - if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, - TemplateArgs, NumTemplateArgs, RAngleLoc, + TemplateArgs.size()); + if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs, false, Converted)) return QualType(); @@ -1190,8 +1412,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, if (Name.isDependent() || TemplateSpecializationType::anyDependentTemplateArguments( - TemplateArgs, - NumTemplateArgs)) { + TemplateArgs)) { // This class template specialization is a dependent // type. Therefore, its canonical type is another class template // specialization type that contains all of the converted @@ -1240,8 +1461,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, // Build the fully-sugared type for this class template // specialization, which refers back to the class template // specialization we created or found. - return Context.getTemplateSpecializationType(Name, TemplateArgs, - NumTemplateArgs, CanonType); + return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); } Action::TypeResult @@ -1252,13 +1472,10 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, TemplateName Template = TemplateD.getAsVal<TemplateName>(); // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); - QualType Result = CheckTemplateIdType(Template, TemplateLoc, LAngleLoc, - TemplateArgs.data(), - TemplateArgs.size(), - RAngleLoc); + QualType Result = CheckTemplateIdType(Template, TemplateLoc, TemplateArgs); TemplateArgsIn.release(); if (Result.isNull()) @@ -1310,64 +1527,72 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult, return ElabType.getAsOpaquePtr(); } -Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, - TemplateName Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc) { +Sema::OwningExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, + LookupResult &R, + bool RequiresADL, + const TemplateArgumentListInfo &TemplateArgs) { // 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, // though. - - // Cope with an implicit member access in a C++ non-static member function. - NamedDecl *D = Template.getAsTemplateDecl(); - if (!D) - D = Template.getAsOverloadedFunctionDecl(); - - CXXScopeSpec SS; - SS.setRange(QualifierRange); - SS.setScopeRep(Qualifier); - QualType ThisType, MemberType; - if (D && isImplicitMemberReference(&SS, D, TemplateNameLoc, - ThisType, MemberType)) { - Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); - return Owned(MemberExpr::Create(Context, This, true, - Qualifier, QualifierRange, - D, TemplateNameLoc, true, - LAngleLoc, TemplateArgs, - NumTemplateArgs, RAngleLoc, - Context.OverloadTy)); + + // These should be filtered out by our callers. + assert(!R.empty() && "empty lookup results when building templateid"); + assert(!R.isAmbiguous() && "ambiguous lookup when building templateid"); + + NestedNameSpecifier *Qualifier = 0; + SourceRange QualifierRange; + if (SS.isSet()) { + Qualifier = static_cast<NestedNameSpecifier*>(SS.getScopeRep()); + QualifierRange = SS.getRange(); } - return Owned(TemplateIdRefExpr::Create(Context, Context.OverloadTy, - Qualifier, QualifierRange, - Template, TemplateNameLoc, LAngleLoc, - TemplateArgs, - NumTemplateArgs, RAngleLoc)); + bool Dependent + = UnresolvedLookupExpr::ComputeDependence(R.begin(), R.end(), + &TemplateArgs); + UnresolvedLookupExpr *ULE + = UnresolvedLookupExpr::Create(Context, Dependent, + Qualifier, QualifierRange, + R.getLookupName(), R.getNameLoc(), + RequiresADL, TemplateArgs); + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + ULE->addDecl(*I); + + return Owned(ULE); } -Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS, - TemplateTy TemplateD, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc) { - TemplateName Template = TemplateD.getAsVal<TemplateName>(); +// We actually only call this from template instantiation. +Sema::OwningExprResult +Sema::BuildQualifiedTemplateIdExpr(const CXXScopeSpec &SS, + DeclarationName Name, + SourceLocation NameLoc, + const TemplateArgumentListInfo &TemplateArgs) { + DeclContext *DC; + if (!(DC = computeDeclContext(SS, false)) || + DC->isDependentContext() || + RequireCompleteDeclContext(SS)) + return BuildDependentDeclRefExpr(SS, Name, NameLoc, &TemplateArgs); + + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + LookupTemplateName(R, (Scope*) 0, SS, QualType(), /*Entering*/ false); + + if (R.isAmbiguous()) + return ExprError(); + + if (R.empty()) { + Diag(NameLoc, diag::err_template_kw_refers_to_non_template) + << Name << SS.getRange(); + return ExprError(); + } - // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; - translateTemplateArguments(TemplateArgsIn, TemplateArgs); - TemplateArgsIn.release(); + if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) { + Diag(NameLoc, diag::err_template_kw_refers_to_class_template) + << (NestedNameSpecifier*) SS.getScopeRep() << Name << SS.getRange(); + Diag(Temp->getLocation(), diag::note_referenced_class_template); + return ExprError(); + } - return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(), - SS.getRange(), - Template, TemplateNameLoc, LAngleLoc, - TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc); + return BuildTemplateIdExpr(SS, R, /* ADL */ false, TemplateArgs); } /// \brief Form a dependent template name. @@ -1381,10 +1606,11 @@ Sema::TemplateTy Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, const CXXScopeSpec &SS, UnqualifiedId &Name, - TypeTy *ObjectType) { + TypeTy *ObjectType, + bool EnteringContext) { if ((ObjectType && computeDeclContext(QualType::getFromOpaquePtr(ObjectType))) || - (SS.isSet() && computeDeclContext(SS, false))) { + (SS.isSet() && computeDeclContext(SS, EnteringContext))) { // 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 @@ -1403,7 +1629,7 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, // rules, even in C++03 mode, retroactively applying the DR. TemplateTy Template; TemplateNameKind TNK = isTemplateName(0, SS, Name, ObjectType, - false, Template); + EnteringContext, Template); if (TNK == TNK_Non_template) { Diag(Name.getSourceRange().getBegin(), diag::err_template_kw_refers_to_non_template) @@ -1426,7 +1652,10 @@ Sema::ActOnDependentTemplateName(SourceLocation TemplateKWLoc, case UnqualifiedId::IK_OperatorFunctionId: return TemplateTy::make(Context.getDependentTemplateName(Qualifier, Name.OperatorFunctionId.Operator)); - + + case UnqualifiedId::IK_LiteralOperatorId: + assert(false && "We don't support these; Parse shouldn't have allowed propagation"); + default: break; } @@ -1609,6 +1838,65 @@ SubstDefaultTemplateArgument(Sema &SemaRef, AllTemplateArgs); } +/// \brief If the given template parameter has a default template +/// argument, substitute into that default template argument and +/// return the corresponding template argument. +TemplateArgumentLoc +Sema::SubstDefaultTemplateArgumentIfAvailable(TemplateDecl *Template, + SourceLocation TemplateLoc, + SourceLocation RAngleLoc, + Decl *Param, + TemplateArgumentListBuilder &Converted) { + if (TemplateTypeParmDecl *TypeParm = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (!TypeParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + DeclaratorInfo *DI = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TypeParm, + Converted); + if (DI) + return TemplateArgumentLoc(TemplateArgument(DI->getType()), DI); + + return TemplateArgumentLoc(); + } + + if (NonTypeTemplateParmDecl *NonTypeParm + = dyn_cast<NonTypeTemplateParmDecl>(Param)) { + if (!NonTypeParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + OwningExprResult Arg = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + NonTypeParm, + Converted); + if (Arg.isInvalid()) + return TemplateArgumentLoc(); + + Expr *ArgE = Arg.takeAs<Expr>(); + return TemplateArgumentLoc(TemplateArgument(ArgE), ArgE); + } + + TemplateTemplateParmDecl *TempTempParm + = cast<TemplateTemplateParmDecl>(Param); + if (!TempTempParm->hasDefaultArgument()) + return TemplateArgumentLoc(); + + TemplateName TName = SubstDefaultTemplateArgument(*this, Template, + TemplateLoc, + RAngleLoc, + TempTempParm, + Converted); + if (TName.isNull()) + return TemplateArgumentLoc(); + + return TemplateArgumentLoc(TemplateArgument(TName), + TempTempParm->getDefaultArgument().getTemplateQualifierRange(), + TempTempParm->getDefaultArgument().getTemplateNameLoc()); +} + /// \brief Check that the given template argument corresponds to the given /// template parameter. bool Sema::CheckTemplateArgument(NamedDecl *Param, @@ -1679,12 +1967,11 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, // parsed as a template template argument. However, since we now // know that we need a non-type template argument, convert this // template name into an expression. - Expr *E = new (Context) UnresolvedDeclRefExpr(DTN->getIdentifier(), - Context.DependentTy, - Arg.getTemplateNameLoc(), + Expr *E = DependentScopeDeclRefExpr::Create(Context, + DTN->getQualifier(), Arg.getTemplateQualifierRange(), - DTN->getQualifier(), - /*isAddressOfOperand=*/false); + DTN->getIdentifier(), + Arg.getTemplateNameLoc()); TemplateArgument Result; if (CheckTemplateArgument(NTTP, NTTPType, E, Result)) @@ -1798,17 +2085,16 @@ bool Sema::CheckTemplateArgument(NamedDecl *Param, /// for specializing the given template. bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *TemplateArgs, - unsigned NumTemplateArgs, - SourceLocation RAngleLoc, + const TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, TemplateArgumentListBuilder &Converted) { TemplateParameterList *Params = Template->getTemplateParameters(); unsigned NumParams = Params->size(); - unsigned NumArgs = NumTemplateArgs; + unsigned NumArgs = TemplateArgs.size(); bool Invalid = false; + SourceLocation RAngleLoc = TemplateArgs.getRAngleLoc(); + bool HasParameterPack = NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack(); @@ -2048,7 +2334,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, // Functions must have external linkage. if (FunctionDecl *Func = dyn_cast<FunctionDecl>(DRE->getDecl())) { - if (Func->getStorageClass() == FunctionDecl::Static) { + if (Func->getLinkage() != NamedDecl::ExternalLinkage) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_function_not_extern) << Func << Arg->getSourceRange(); @@ -2063,7 +2349,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg, } if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) { - if (!Var->hasGlobalStorage()) { + if (Var->getLinkage() != NamedDecl::ExternalLinkage) { Diag(Arg->getSourceRange().getBegin(), diag::err_template_arg_object_not_extern) << Var << Arg->getSourceRange(); @@ -3046,16 +3332,17 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + TemplateArgumentListInfo TemplateArgs; + TemplateArgs.setLAngleLoc(LAngleLoc); + TemplateArgs.setRAngleLoc(RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); // Check that the template argument list is well-formed for this // template. TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), TemplateArgs.size()); - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, - TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, false, Converted)) + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, + TemplateArgs, false, Converted)) return true; assert((Converted.structuredSize() == @@ -3154,8 +3441,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TemplateParams, ClassTemplate, Converted, - TemplateArgs.data(), - TemplateArgs.size(), + TemplateArgs, PrevPartial); if (PrevPartial) { @@ -3267,10 +3553,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // name based on the "canonical" representation used to store the // template arguments in the specialization. QualType WrittenTy - = Context.getTemplateSpecializationType(Name, - TemplateArgs.data(), - TemplateArgs.size(), - CanonType); + = Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType); if (TUK != TUK_Friend) Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); @@ -3533,11 +3816,7 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, /// \param PrevDecl the set of declarations that bool Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, - bool HasExplicitTemplateArgs, - SourceLocation LAngleLoc, - const TemplateArgumentLoc *ExplicitTemplateArgs, - unsigned NumExplicitTemplateArgs, - SourceLocation RAngleLoc, + const TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. @@ -3564,9 +3843,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, TemplateDeductionInfo Info(Context); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK - = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs, - ExplicitTemplateArgs, - NumExplicitTemplateArgs, + = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FD->getType(), Specialization, Info)) { @@ -3589,7 +3866,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, PartialDiagnostic(diag::err_function_template_spec_no_match) << FD->getDeclName(), PartialDiagnostic(diag::err_function_template_spec_ambiguous) - << FD->getDeclName() << HasExplicitTemplateArgs, + << FD->getDeclName() << (ExplicitTemplateArgs != 0), PartialDiagnostic(diag::note_function_template_spec_matched)); if (!Specialization) return true; @@ -3901,16 +4178,15 @@ Sema::ActOnExplicitInstantiation(Scope *S, : TSK_ExplicitInstantiationDeclaration; // Translate the parser's template argument list in our AST format. - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + TemplateArgumentListInfo TemplateArgs(LAngleLoc, RAngleLoc); translateTemplateArguments(TemplateArgsIn, TemplateArgs); // Check that the template argument list is well-formed for this // template. TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(), TemplateArgs.size()); - if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, - TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, false, Converted)) + if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, + TemplateArgs, false, Converted)) return true; assert((Converted.structuredSize() == @@ -3938,6 +4214,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, ClassTemplateSpecializationDecl *Specialization = 0; + bool ReusedDecl = false; if (PrevDecl) { bool SuppressNew = false; if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK, @@ -3959,6 +4236,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization = PrevDecl; Specialization->setLocation(TemplateNameLoc); PrevDecl = 0; + ReusedDecl = true; } } @@ -3991,18 +4269,18 @@ Sema::ActOnExplicitInstantiation(Scope *S, // on the "canonical" representation used to store the template // arguments in the specialization. QualType WrittenTy - = Context.getTemplateSpecializationType(Name, - TemplateArgs.data(), - TemplateArgs.size(), + = Context.getTemplateSpecializationType(Name, TemplateArgs, Context.getTypeDeclType(Specialization)); Specialization->setTypeAsWritten(WrittenTy); TemplateArgsIn.release(); - // Add the explicit instantiation into its lexical context. However, - // since explicit instantiations are never found by name lookup, we - // just put it into the declaration context directly. - Specialization->setLexicalDeclContext(CurContext); - CurContext->addDecl(Specialization); + if (!ReusedDecl) { + // Add the explicit instantiation into its lexical context. However, + // since explicit instantiations are never found by name lookup, we + // just put it into the declaration context directly. + Specialization->setLexicalDeclContext(CurContext); + CurContext->addDecl(Specialization); + } // C++ [temp.explicit]p3: // A definition of a class template or class member template @@ -4277,14 +4555,15 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // If the declarator is a template-id, translate the parser's template // argument list into our AST format. bool HasExplicitTemplateArgs = false; - llvm::SmallVector<TemplateArgumentLoc, 16> TemplateArgs; + TemplateArgumentListInfo TemplateArgs; if (D.getName().getKind() == UnqualifiedId::IK_TemplateId) { TemplateIdAnnotation *TemplateId = D.getName().TemplateId; + TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc); + TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc); ASTTemplateArgsPtr TemplateArgsPtr(*this, TemplateId->getTemplateArgs(), TemplateId->NumArgs); - translateTemplateArguments(TemplateArgsPtr, - TemplateArgs); + translateTemplateArguments(TemplateArgsPtr, TemplateArgs); HasExplicitTemplateArgs = true; TemplateArgsPtr.release(); } @@ -4315,8 +4594,8 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, TemplateDeductionInfo Info(Context); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK - = DeduceTemplateArguments(FunTmpl, HasExplicitTemplateArgs, - TemplateArgs.data(), TemplateArgs.size(), + = DeduceTemplateArguments(FunTmpl, + (HasExplicitTemplateArgs ? &TemplateArgs : 0), R, Specialization, Info)) { // FIXME: Keep track of almost-matches? (void)TDK; @@ -4365,12 +4644,12 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (SuppressNew) return DeclPtrTy(); } + + Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization, false, /*DefinitionRequired=*/true); - - Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); // C++0x [temp.explicit]p2: // If the explicit instantiation is for a member function, a member class @@ -4537,7 +4816,7 @@ Sema::CheckTypenameType(NestedNameSpecifier *NNS, const IdentifierInfo &II, namespace { // See Sema::RebuildTypeInCurrentInstantiation - class VISIBILITY_HIDDEN CurrentInstantiationRebuilder + class CurrentInstantiationRebuilder : public TreeTransform<CurrentInstantiationRebuilder> { SourceLocation Loc; DeclarationName Entity; |