From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001 From: "Zancanaro; Carlo" Date: Mon, 24 Sep 2012 09:58:17 +1000 Subject: Add the clang library to the repo (with some of my changes, too). --- clang/lib/Sema/SemaTemplate.cpp | 7192 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 7192 insertions(+) create mode 100644 clang/lib/Sema/SemaTemplate.cpp (limited to 'clang/lib/Sema/SemaTemplate.cpp') diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp new file mode 100644 index 0000000..51ce2a1 --- /dev/null +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -0,0 +1,7192 @@ +//===------- 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 "clang/Sema/SemaInternal.h" +#include "clang/Sema/Lookup.h" +#include "clang/Sema/Scope.h" +#include "clang/Sema/Template.h" +#include "clang/Sema/TemplateDeduction.h" +#include "TreeTransform.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/TypeVisitor.h" +#include "clang/Sema/DeclSpec.h" +#include "clang/Sema/ParsedTemplate.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "llvm/ADT/SmallBitVector.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringExtras.h" +using namespace clang; +using namespace sema; + +// Exported for use by Parser. +SourceRange +clang::getTemplateParamsRange(TemplateParameterList const * const *Ps, + unsigned N) { + if (!N) return SourceRange(); + return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc()); +} + +/// \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 *Orig, + bool AllowFunctionTemplates) { + NamedDecl *D = Orig->getUnderlyingDecl(); + + if (isa(D)) { + if (!AllowFunctionTemplates && isa(D)) + return 0; + + return Orig; + } + + if (CXXRecordDecl *Record = dyn_cast(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(Record->getDeclContext()); + if (Record->getDescribedClassTemplate()) + return Record->getDescribedClassTemplate(); + + if (ClassTemplateSpecializationDecl *Spec + = dyn_cast(Record)) + return Spec->getSpecializedTemplate(); + } + + return 0; + } + + return 0; +} + +void Sema::FilterAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates) { + // The set of class templates we've already seen. + llvm::SmallPtrSet ClassTemplates; + LookupResult::Filter filter = R.makeFilter(); + while (filter.hasNext()) { + NamedDecl *Orig = filter.next(); + NamedDecl *Repl = isAcceptableTemplateName(Context, Orig, + AllowFunctionTemplates); + if (!Repl) + filter.erase(); + else if (Repl != Orig) { + + // C++ [temp.local]p3: + // A lookup that finds an injected-class-name (10.2) can result in an + // ambiguity in certain cases (for example, if it is found in more than + // one base class). If all of the injected-class-names that are found + // refer to specializations of the same class template, and if the name + // is used as a template-name, the reference refers to the class + // template itself and not a specialization thereof, and is not + // ambiguous. + if (ClassTemplateDecl *ClassTmpl = dyn_cast(Repl)) + if (!ClassTemplates.insert(ClassTmpl)) { + filter.erase(); + continue; + } + + // FIXME: we promote access to public here as a workaround to + // the fact that LookupResult doesn't let us remember that we + // found this template through a particular injected class name, + // which means we end up doing nasty things to the invariants. + // Pretending that access is public is *much* safer. + filter.replace(Repl, AS_public); + } + } + filter.done(); +} + +bool Sema::hasAnyAcceptableTemplateNames(LookupResult &R, + bool AllowFunctionTemplates) { + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); I != IEnd; ++I) + if (isAcceptableTemplateName(Context, *I, AllowFunctionTemplates)) + return true; + + return false; +} + +TemplateNameKind Sema::isTemplateName(Scope *S, + CXXScopeSpec &SS, + bool hasTemplateKeyword, + UnqualifiedId &Name, + ParsedType ObjectTypePtr, + bool EnteringContext, + TemplateTy &TemplateResult, + bool &MemberOfUnknownSpecialization) { + assert(getLangOpts().CPlusPlus && "No template names in C!"); + + DeclarationName TName; + MemberOfUnknownSpecialization = false; + + switch (Name.getKind()) { + case UnqualifiedId::IK_Identifier: + TName = DeclarationName(Name.Identifier); + break; + + case UnqualifiedId::IK_OperatorFunctionId: + TName = Context.DeclarationNames.getCXXOperatorName( + Name.OperatorFunctionId.Operator); + break; + + case UnqualifiedId::IK_LiteralOperatorId: + TName = Context.DeclarationNames.getCXXLiteralOperatorName(Name.Identifier); + break; + + default: + return TNK_Non_template; + } + + QualType ObjectType = ObjectTypePtr.get(); + + LookupResult R(*this, TName, Name.getLocStart(), LookupOrdinaryName); + LookupTemplateName(R, S, SS, ObjectType, EnteringContext, + MemberOfUnknownSpecialization); + if (R.empty()) return TNK_Non_template; + if (R.isAmbiguous()) { + // Suppress diagnostics; we'll redo this lookup later. + R.suppressDiagnostics(); + + // FIXME: we might have ambiguous templates, in which case we + // should at least parse them properly! + return TNK_Non_template; + } + + TemplateName Template; + TemplateNameKind TemplateKind; + + unsigned ResultCount = R.end() - R.begin(); + if (ResultCount > 1) { + // We assume that we'll preserve the qualifier from a function + // template name in other ways. + Template = Context.getOverloadedTemplateName(R.begin(), R.end()); + TemplateKind = TNK_Function_template; + + // We'll do this lookup again later. + R.suppressDiagnostics(); + } else { + TemplateDecl *TD = cast((*R.begin())->getUnderlyingDecl()); + + if (SS.isSet() && !SS.isInvalid()) { + NestedNameSpecifier *Qualifier + = static_cast(SS.getScopeRep()); + Template = Context.getQualifiedTemplateName(Qualifier, + hasTemplateKeyword, TD); + } else { + Template = TemplateName(TD); + } + + if (isa(TD)) { + TemplateKind = TNK_Function_template; + + // We'll do this lookup again later. + R.suppressDiagnostics(); + } else { + assert(isa(TD) || isa(TD) || + isa(TD)); + TemplateKind = TNK_Type_template; + } + } + + TemplateResult = TemplateTy::make(Template); + return TemplateKind; +} + +bool Sema::DiagnoseUnknownTemplateName(const IdentifierInfo &II, + SourceLocation IILoc, + Scope *S, + const CXXScopeSpec *SS, + TemplateTy &SuggestedTemplate, + TemplateNameKind &SuggestedKind) { + // We can't recover unless there's a dependent scope specifier preceding the + // template name. + // FIXME: Typo correction? + if (!SS || !SS->isSet() || !isDependentScopeSpecifier(*SS) || + computeDeclContext(*SS)) + return false; + + // The code is missing a 'template' keyword prior to the dependent template + // name. + NestedNameSpecifier *Qualifier = (NestedNameSpecifier*)SS->getScopeRep(); + Diag(IILoc, diag::err_template_kw_missing) + << Qualifier << II.getName() + << FixItHint::CreateInsertion(IILoc, "template "); + SuggestedTemplate + = TemplateTy::make(Context.getDependentTemplateName(Qualifier, &II)); + SuggestedKind = TNK_Dependent_template_name; + return true; +} + +void Sema::LookupTemplateName(LookupResult &Found, + Scope *S, CXXScopeSpec &SS, + QualType ObjectType, + bool EnteringContext, + bool &MemberOfUnknownSpecialization) { + // Determine where to perform name lookup + MemberOfUnknownSpecialization = false; + DeclContext *LookupCtx = 0; + bool isDependent = false; + 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"); + LookupCtx = computeDeclContext(ObjectType); + isDependent = ObjectType->isDependentType(); + assert((isDependent || !ObjectType->isIncompleteType()) && + "Caller should have completed object type"); + + // Template names cannot appear inside an Objective-C class or object type. + if (ObjectType->isObjCObjectOrInterfaceType()) { + Found.clear(); + return; + } + } else if (SS.isSet()) { + // This nested-name-specifier occurs after another nested-name-specifier, + // so long into the context associated with the prior nested-name-specifier. + LookupCtx = computeDeclContext(SS, EnteringContext); + isDependent = isDependentScopeSpecifier(SS); + + // The declaration context must be complete. + if (LookupCtx && RequireCompleteDeclContext(SS, LookupCtx)) + return; + } + + bool ObjectTypeSearchedInScope = false; + bool AllowFunctionTemplatesInLookup = true; + 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. + LookupQualifiedName(Found, LookupCtx); + 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 + // 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. + if (S) LookupName(Found, S); + ObjectTypeSearchedInScope = true; + AllowFunctionTemplatesInLookup = false; + } + } else if (isDependent && (!S || ObjectType.isNull())) { + // We cannot look into a dependent object type or nested nme + // specifier. + MemberOfUnknownSpecialization = true; + return; + } else { + // Perform unqualified name lookup in the current scope. + LookupName(Found, S); + + if (!ObjectType.isNull()) + AllowFunctionTemplatesInLookup = false; + } + + if (Found.empty() && !isDependent) { + // If we did not find any names, attempt to correct any typos. + DeclarationName Name = Found.getLookupName(); + Found.clear(); + // Simple filter callback that, for keywords, only accepts the C++ *_cast + CorrectionCandidateCallback FilterCCC; + FilterCCC.WantTypeSpecifiers = false; + FilterCCC.WantExpressionKeywords = false; + FilterCCC.WantRemainingKeywords = false; + FilterCCC.WantCXXNamedCasts = true; + if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(), + Found.getLookupKind(), S, &SS, + FilterCCC, LookupCtx)) { + Found.setLookupName(Corrected.getCorrection()); + if (Corrected.getCorrectionDecl()) + Found.addDecl(Corrected.getCorrectionDecl()); + FilterAcceptableTemplateNames(Found); + if (!Found.empty()) { + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + if (LookupCtx) + Diag(Found.getNameLoc(), diag::err_no_member_template_suggest) + << Name << LookupCtx << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); + else + Diag(Found.getNameLoc(), diag::err_no_template_suggest) + << Name << CorrectedQuotedStr + << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); + if (TemplateDecl *Template = Found.getAsSingle()) + Diag(Template->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + } + } else { + Found.setLookupName(Name); + } + } + + FilterAcceptableTemplateNames(Found, AllowFunctionTemplatesInLookup); + if (Found.empty()) { + if (isDependent) + MemberOfUnknownSpecialization = true; + return; + } + + 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, Found.getLookupName(), Found.getNameLoc(), + LookupOrdinaryName); + LookupName(FoundOuter, S); + FilterAcceptableTemplateNames(FoundOuter, /*AllowFunctionTemplates=*/false); + + if (FoundOuter.empty()) { + // - if the name is not found, the name found in the class of the + // object expression is used, otherwise + } else if (!FoundOuter.getAsSingle() || + FoundOuter.isAmbiguous()) { + // - 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 + FoundOuter.clear(); + } else if (!Found.isSuppressingDiagnostics()) { + // - 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 (!Found.isSingleResult() || + Found.getFoundDecl()->getCanonicalDecl() + != FoundOuter.getFoundDecl()->getCanonicalDecl()) { + Diag(Found.getNameLoc(), + diag::ext_nested_name_member_ref_lookup_ambiguous) + << Found.getLookupName() + << ObjectType; + 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. + } + } + } +} + +/// ActOnDependentIdExpression - Handle a dependent id-expression that +/// was just parsed. This is only possible with an explicit scope +/// specifier naming a dependent type. +ExprResult +Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + bool isAddressOfOperand, + const TemplateArgumentListInfo *TemplateArgs) { + DeclContext *DC = getFunctionLevelDeclContext(); + + if (!isAddressOfOperand && + isa(DC) && + cast(DC)->isInstance()) { + QualType ThisType = cast(DC)->getThisType(Context); + + // 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*/ 0, ThisType, + /*IsArrow*/ true, + /*Op*/ SourceLocation(), + SS.getWithLocInContext(Context), + TemplateKWLoc, + FirstQualifierInScope, + NameInfo, + TemplateArgs)); + } + + return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); +} + +ExprResult +Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, + SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs) { + return Owned(DependentScopeDeclRefExpr::Create(Context, + SS.getWithLocInContext(Context), + TemplateKWLoc, + NameInfo, + TemplateArgs)); +} + +/// DiagnoseTemplateParameterShadow - Produce a diagnostic complaining +/// that the template parameter 'PrevDecl' is being shadowed by a new +/// declaration at location Loc. Returns true to indicate that this is +/// an error, and false otherwise. +void Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) { + assert(PrevDecl->isTemplateParameter() && "Not a template parameter"); + + // Microsoft Visual C++ permits template parameters to be shadowed. + if (getLangOpts().MicrosoftExt) + return; + + // C++ [temp.local]p4: + // A template-parameter shall not be redeclared within its + // scope (including nested scopes). + Diag(Loc, diag::err_template_param_shadow) + << cast(PrevDecl)->getDeclName(); + Diag(PrevDecl->getLocation(), diag::note_template_param_here); + return; +} + +/// AdjustDeclIfTemplate - If the given decl happens to be a template, reset +/// 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(Decl *&D) { + if (TemplateDecl *Temp = dyn_cast_or_null(D)) { + D = Temp->getTemplatedDecl(); + return Temp; + } + return 0; +} + +ParsedTemplateArgument ParsedTemplateArgument::getTemplatePackExpansion( + SourceLocation EllipsisLoc) const { + assert(Kind == Template && + "Only template template arguments can be pack expansions here"); + assert(getAsTemplate().get().containsUnexpandedParameterPack() && + "Template template argument pack expansion without packs"); + ParsedTemplateArgument Result(*this); + Result.EllipsisLoc = EllipsisLoc; + return Result; +} + +static TemplateArgumentLoc translateTemplateArgument(Sema &SemaRef, + const ParsedTemplateArgument &Arg) { + + switch (Arg.getKind()) { + case ParsedTemplateArgument::Type: { + TypeSourceInfo *DI; + QualType T = SemaRef.GetTypeFromParser(Arg.getAsType(), &DI); + if (!DI) + DI = SemaRef.Context.getTrivialTypeSourceInfo(T, Arg.getLocation()); + return TemplateArgumentLoc(TemplateArgument(T), DI); + } + + case ParsedTemplateArgument::NonType: { + Expr *E = static_cast(Arg.getAsExpr()); + return TemplateArgumentLoc(TemplateArgument(E), E); + } + + case ParsedTemplateArgument::Template: { + TemplateName Template = Arg.getAsTemplate().get(); + TemplateArgument TArg; + if (Arg.getEllipsisLoc().isValid()) + TArg = TemplateArgument(Template, llvm::Optional()); + else + TArg = Template; + return TemplateArgumentLoc(TArg, + Arg.getScopeSpec().getWithLocInContext( + SemaRef.Context), + Arg.getLocation(), + Arg.getEllipsisLoc()); + } + } + + llvm_unreachable("Unhandled parsed template argument"); +} + +/// \brief Translates template arguments as provided by the parser +/// into template arguments used by semantic analysis. +void Sema::translateTemplateArguments(const ASTTemplateArgsPtr &TemplateArgsIn, + TemplateArgumentListInfo &TemplateArgs) { + for (unsigned I = 0, Last = TemplateArgsIn.size(); I != Last; ++I) + TemplateArgs.addArgument(translateTemplateArgument(*this, + TemplateArgsIn[I])); +} + +/// ActOnTypeParameter - Called when a C++ template type parameter +/// (e.g., "typename T") has been parsed. Typename specifies whether +/// the keyword "typename" was used to declare the type parameter +/// (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 +/// ParamNameLoc is the location of the parameter name (if any). +/// If the type parameter has a default argument, it will be added +/// later via ActOnTypeParameterDefault. +Decl *Sema::ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, + SourceLocation EllipsisLoc, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, unsigned Position, + SourceLocation EqualLoc, + ParsedType DefaultArg) { + assert(S->isTemplateParamScope() && + "Template type parameter not in template parameter scope!"); + bool Invalid = false; + + if (ParamName) { + NamedDecl *PrevDecl = LookupSingleName(S, ParamName, ParamNameLoc, + LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(ParamNameLoc, PrevDecl); + PrevDecl = 0; + } + } + + SourceLocation Loc = ParamNameLoc; + if (!ParamName) + Loc = KeyLoc; + + TemplateTypeParmDecl *Param + = TemplateTypeParmDecl::Create(Context, Context.getTranslationUnitDecl(), + KeyLoc, Loc, Depth, Position, ParamName, + Typename, Ellipsis); + Param->setAccess(AS_public); + if (Invalid) + Param->setInvalidDecl(); + + if (ParamName) { + // Add the template parameter into the current scope. + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + + // 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. + if (DefaultArg && Ellipsis) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + DefaultArg = ParsedType(); + } + + // Handle the default argument, if provided. + if (DefaultArg) { + TypeSourceInfo *DefaultTInfo; + GetTypeFromParser(DefaultArg, &DefaultTInfo); + + assert(DefaultTInfo && "expected source information for type"); + + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(Loc, DefaultTInfo, + UPPC_DefaultArgument)) + return Param; + + // Check the template argument itself. + if (CheckTemplateArgument(Param, DefaultTInfo)) { + Param->setInvalidDecl(); + return Param; + } + + Param->setDefaultArgument(DefaultTInfo, false); + } + + return Param; +} + +/// \brief Check that the type of a non-type template parameter is +/// well-formed. +/// +/// \returns the (possibly-promoted) parameter type if valid; +/// otherwise, produces a diagnostic and returns a NULL type. +QualType +Sema::CheckNonTypeTemplateParameterType(QualType T, SourceLocation Loc) { + // We don't allow variably-modified types as the type of non-type template + // parameters. + if (T->isVariablyModifiedType()) { + Diag(Loc, diag::err_variably_modified_nontype_template_param) + << T; + return QualType(); + } + + // C++ [temp.param]p4: + // + // A non-type template-parameter shall have one of the following + // (optionally cv-qualified) types: + // + // -- integral or enumeration type, + if (T->isIntegralOrEnumerationType() || + // -- pointer to object or pointer to function, + T->isPointerType() || + // -- reference to object or reference to function, + T->isReferenceType() || + // -- pointer to member, + T->isMemberPointerType() || + // -- std::nullptr_t. + T->isNullPtrType() || + // If T is a dependent type, we can't do the check now, so we + // assume that it is well-formed. + T->isDependentType()) { + // C++ [temp.param]p5: The top-level cv-qualifiers on the template-parameter + // are ignored when determining its type. + return T.getUnqualifiedType(); + } + + // C++ [temp.param]p8: + // + // A non-type template-parameter of type "array of T" or + // "function returning T" is adjusted to be of type "pointer to + // T" or "pointer to function returning T", respectively. + else if (T->isArrayType()) + // FIXME: Keep the type prior to promotion? + return Context.getArrayDecayedType(T); + else if (T->isFunctionType()) + // FIXME: Keep the type prior to promotion? + return Context.getPointerType(T); + + Diag(Loc, diag::err_template_nontype_parm_bad_type) + << T; + + return QualType(); +} + +Decl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, + unsigned Depth, + unsigned Position, + SourceLocation EqualLoc, + Expr *Default) { + TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S); + QualType T = TInfo->getType(); + + assert(S->isTemplateParamScope() && + "Non-type template parameter not in template parameter scope!"); + bool Invalid = false; + + IdentifierInfo *ParamName = D.getIdentifier(); + if (ParamName) { + NamedDecl *PrevDecl = LookupSingleName(S, ParamName, D.getIdentifierLoc(), + LookupOrdinaryName, + ForRedeclaration); + if (PrevDecl && PrevDecl->isTemplateParameter()) { + DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl); + PrevDecl = 0; + } + } + + T = CheckNonTypeTemplateParameterType(T, D.getIdentifierLoc()); + if (T.isNull()) { + T = Context.IntTy; // Recover with an 'int' type. + Invalid = true; + } + + bool IsParameterPack = D.hasEllipsis(); + NonTypeTemplateParmDecl *Param + = NonTypeTemplateParmDecl::Create(Context, Context.getTranslationUnitDecl(), + D.getLocStart(), + D.getIdentifierLoc(), + Depth, Position, ParamName, T, + IsParameterPack, TInfo); + Param->setAccess(AS_public); + + if (Invalid) + Param->setInvalidDecl(); + + if (D.getIdentifier()) { + // Add the template parameter into the current scope. + S->AddDecl(Param); + IdResolver.AddDecl(Param); + } + + // 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. + if (Default && IsParameterPack) { + Diag(EqualLoc, diag::err_template_param_pack_default_arg); + Default = 0; + } + + // Check the well-formedness of the default template argument, if provided. + if (Default) { + // Check for unexpanded parameter packs. + if (DiagnoseUnexpandedParameterPack(Default, UPPC_DefaultArgument)) + return Param; + + TemplateArgument Converted; + ExprResult DefaultRes = CheckTemplateArgument(Param, Param->getType(), Default, Converted); + if (DefaultRes.isInvalid()) { + Param->setInvalidDecl(); + return Param; + } + Default = DefaultRes.take(); + + Param->setDefaultArgument(Default, false); + } + + return Param; +} + +/// ActOnTemplateTemplateParameter - Called when a C++ template template +/// parameter (e.g. T in template