diff options
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 200 |
1 files changed, 122 insertions, 78 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 035c37cfe6e9..6cc85883345d 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -18,6 +18,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeVisitor.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/TargetInfo.h" @@ -208,7 +209,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S, R.suppressDiagnostics(); } else { assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) || - isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD)); + isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) || + isa<BuiltinTemplateDecl>(TD)); TemplateKind = isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template; } @@ -327,8 +329,8 @@ void Sema::LookupTemplateName(LookupResult &Found, Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) { Found.setLookupName(Corrected.getCorrection()); - if (Corrected.getCorrectionDecl()) - Found.addDecl(Corrected.getCorrectionDecl()); + if (auto *ND = Corrected.getFoundDecl()) + Found.addDecl(ND); FilterAcceptableTemplateNames(Found); if (!Found.empty()) { if (LookupCtx) { @@ -812,14 +814,15 @@ Sema::ActOnTemplateParameterList(unsigned Depth, SourceLocation ExportLoc, SourceLocation TemplateLoc, SourceLocation LAngleLoc, - Decl **Params, unsigned NumParams, + ArrayRef<Decl *> Params, SourceLocation RAngleLoc) { if (ExportLoc.isValid()) Diag(ExportLoc, diag::warn_template_export_unsupported); - return TemplateParameterList::Create(Context, TemplateLoc, LAngleLoc, - (NamedDecl**)Params, NumParams, - RAngleLoc); + return TemplateParameterList::Create( + Context, TemplateLoc, LAngleLoc, + llvm::makeArrayRef((NamedDecl *const *)Params.data(), Params.size()), + RAngleLoc); } static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { @@ -1089,9 +1092,9 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, /*DelayTypeCreation=*/true); SetNestedNameSpecifier(NewClass, SS); if (NumOuterTemplateParamLists > 0) - NewClass->setTemplateParameterListsInfo(Context, - NumOuterTemplateParamLists, - OuterTemplateParamLists); + NewClass->setTemplateParameterListsInfo( + Context, llvm::makeArrayRef(OuterTemplateParamLists, + NumOuterTemplateParamLists)); // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. @@ -1936,7 +1939,7 @@ TemplateParameterList *Sema::MatchTemplateParametersToScopeSpecifier( // Fabricate an empty template parameter list for the invented header. return TemplateParameterList::Create(Context, SourceLocation(), - SourceLocation(), nullptr, 0, + SourceLocation(), None, SourceLocation()); } @@ -2017,6 +2020,58 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) { } } +static QualType +checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD, + const SmallVectorImpl<TemplateArgument> &Converted, + SourceLocation TemplateLoc, + TemplateArgumentListInfo &TemplateArgs) { + ASTContext &Context = SemaRef.getASTContext(); + switch (BTD->getBuiltinTemplateKind()) { + case BTK__make_integer_seq: + // Specializations of __make_integer_seq<S, T, N> are treated like + // S<T, 0, ..., N-1>. + + // C++14 [inteseq.intseq]p1: + // T shall be an integer type. + if (!Converted[1].getAsType()->isIntegralType(Context)) { + SemaRef.Diag(TemplateArgs[1].getLocation(), + diag::err_integer_sequence_integral_element_type); + return QualType(); + } + + // C++14 [inteseq.make]p1: + // If N is negative the program is ill-formed. + TemplateArgument NumArgsArg = Converted[2]; + llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); + if (NumArgs < 0) { + SemaRef.Diag(TemplateArgs[2].getLocation(), + diag::err_integer_sequence_negative_length); + return QualType(); + } + + QualType ArgTy = NumArgsArg.getIntegralType(); + TemplateArgumentListInfo SyntheticTemplateArgs; + // The type argument gets reused as the first template argument in the + // synthetic template argument list. + SyntheticTemplateArgs.addArgument(TemplateArgs[1]); + // Expand N into 0 ... N-1. + for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned()); + I < NumArgs; ++I) { + TemplateArgument TA(Context, I, ArgTy); + Expr *E = SemaRef.BuildExpressionFromIntegralTemplateArgument( + TA, TemplateArgs[2].getLocation()) + .getAs<Expr>(); + SyntheticTemplateArgs.addArgument( + TemplateArgumentLoc(TemplateArgument(E), E)); + } + // The first template argument will be reused as the template decl that + // our synthetic template arguments will be applied to. + return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(), + TemplateLoc, SyntheticTemplateArgs); + } + llvm_unreachable("unexpected BuiltinTemplateDecl!"); +} + QualType Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs) { @@ -2171,6 +2226,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, CanonType = Context.getTypeDeclType(Decl); assert(isa<RecordType>(CanonType) && "type of non-dependent specialization is not a RecordType"); + } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) { + CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc, + TemplateArgs); } // Build the fully-sugared type for this class template @@ -2469,25 +2527,6 @@ DeclResult Sema::ActOnVarTemplateSpecialization( false, Converted)) return true; - // Check that the type of this variable template specialization - // matches the expected type. - TypeSourceInfo *ExpectedDI; - { - // Do substitution on the type of the declaration - TemplateArgumentList TemplateArgList(TemplateArgumentList::OnStack, - Converted.data(), Converted.size()); - InstantiatingTemplate Inst(*this, TemplateKWLoc, VarTemplate); - if (Inst.isInvalid()) - return true; - VarDecl *Templated = VarTemplate->getTemplatedDecl(); - ExpectedDI = - SubstType(Templated->getTypeSourceInfo(), - MultiLevelTemplateArgumentList(TemplateArgList), - Templated->getTypeSpecStartLoc(), Templated->getDeclName()); - } - if (!ExpectedDI) - return true; - // Find the variable template (partial) specialization declaration that // corresponds to these arguments. if (IsPartialSpecialization) { @@ -2710,7 +2749,8 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc, typedef PartialSpecMatchResult MatchResult; SmallVector<MatchResult, 4> Matched; SourceLocation PointOfInstantiation = TemplateNameLoc; - TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation); + TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation, + /*ForTakingAddress=*/false); // 1. Attempt to find the closest partial specialization that this // specializes, if any. @@ -3242,7 +3282,8 @@ SubstDefaultTemplateArgument(Sema &SemaRef, TemplateArgLists.addOuterTemplateArguments(None); Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); - EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated); + EnterExpressionEvaluationContext ConstantEvaluated(SemaRef, + Sema::ConstantEvaluated); return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists); } @@ -3733,9 +3774,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // We're done with this parameter pack. Pack up its arguments and add // them to the list. Converted.push_back( - TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); + TemplateArgument::CreatePackCopy(Context, ArgumentPack)); ArgumentPack.clear(); // This argument is assigned to the next parameter. @@ -3816,10 +3855,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // If we're checking a partial template argument list, we're done. if (PartialTemplateArgs) { if ((*Param)->isTemplateParameterPack() && !ArgumentPack.empty()) - Converted.push_back(TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); - + Converted.push_back( + TemplateArgument::CreatePackCopy(Context, ArgumentPack)); + return false; } @@ -3835,9 +3873,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, if (Param + 1 != ParamEnd) return true; - Converted.push_back(TemplateArgument::CreatePackCopy(Context, - ArgumentPack.data(), - ArgumentPack.size())); + Converted.push_back( + TemplateArgument::CreatePackCopy(Context, ArgumentPack)); ArgumentPack.clear(); ++Param; @@ -3946,7 +3983,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, // No problems found with the new argument list, propagate changes back // to caller. - TemplateArgs = NewArgs; + TemplateArgs = std::move(NewArgs); return false; } @@ -4245,7 +4282,11 @@ isNullPointerValueTemplateArgument(Sema &S, NonTypeTemplateParmDecl *Param, QualType ParamType, Expr *Arg) { if (Arg->isValueDependent() || Arg->isTypeDependent()) return NPV_NotNullPointer; - + + if (!S.isCompleteType(Arg->getExprLoc(), ParamType)) + llvm_unreachable( + "Incomplete parameter type in isNullPointerValueTemplateArgument!"); + if (!S.getLangOpts().CPlusPlus11) return NPV_NotNullPointer; @@ -4693,8 +4734,6 @@ static bool CheckTemplateArgumentPointerToMember(Sema &S, S.Diag(Arg->getExprLoc(), diag::warn_cxx98_compat_template_arg_null); Converted = TemplateArgument(S.Context.getCanonicalType(ParamType), /*isNullPtr*/true); - if (S.Context.getTargetInfo().getCXXABI().isMicrosoft()) - S.RequireCompleteType(Arg->getExprLoc(), ParamType, 0); return false; case NPV_NotNullPointer: break; @@ -6311,9 +6350,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, PrevPartial); SetNestedNameSpecifier(Partial, SS); if (TemplateParameterLists.size() > 1 && SS.isSet()) { - Partial->setTemplateParameterListsInfo(Context, - TemplateParameterLists.size() - 1, - TemplateParameterLists.data()); + Partial->setTemplateParameterListsInfo( + Context, TemplateParameterLists.drop_back(1)); } if (!PrevPartial) @@ -6367,14 +6405,23 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, SetNestedNameSpecifier(Specialization, SS); if (TemplateParameterLists.size() > 0) { Specialization->setTemplateParameterListsInfo(Context, - TemplateParameterLists.size(), - TemplateParameterLists.data()); + TemplateParameterLists); } if (!PrevDecl) ClassTemplate->AddSpecialization(Specialization, InsertPos); - CanonType = Context.getTypeDeclType(Specialization); + if (CurContext->isDependentContext()) { + // -fms-extensions permits specialization of nested classes without + // fully specializing the outer class(es). + assert(getLangOpts().MicrosoftExt && + "Only possible with -fms-extensions!"); + TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name); + CanonType = Context.getTemplateSpecializationType( + CanonTemplate, Converted.data(), Converted.size()); + } else { + CanonType = Context.getTypeDeclType(Specialization); + } } // C++ [temp.expl.spec]p6: @@ -6497,24 +6544,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S, return NewDecl; } -Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope, - MultiTemplateParamsArg TemplateParameterLists, - Declarator &D) { - assert(getCurFunctionDecl() == nullptr && "Function parsing confused"); - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - - if (FTI.hasPrototype) { - // FIXME: Diagnose arguments without names in C. - } - - Scope *ParentScope = FnBodyScope->getParent(); - - D.setFunctionDefinitionKind(FDK_Definition); - Decl *DP = HandleDeclarator(ParentScope, D, - TemplateParameterLists); - return ActOnStartOfFunctionDef(FnBodyScope, DP); -} - /// \brief Strips various properties off an implicit instantiation /// that has just been explicitly specialized. static void StripImplicitInstantiation(NamedDecl *D) { @@ -6795,7 +6824,11 @@ bool Sema::CheckFunctionTemplateSpecialization( // The set of function template specializations that could match this // explicit function template specialization. UnresolvedSet<8> Candidates; - TemplateSpecCandidateSet FailedCandidates(FD->getLocation()); + TemplateSpecCandidateSet FailedCandidates(FD->getLocation(), + /*ForTakingAddress=*/false); + + llvm::SmallDenseMap<FunctionDecl *, TemplateArgumentListInfo, 8> + ConvertedTemplateArgs; DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); @@ -6826,6 +6859,10 @@ bool Sema::CheckFunctionTemplateSpecialization( } } + TemplateArgumentListInfo Args; + if (ExplicitTemplateArgs) + Args = *ExplicitTemplateArgs; + // C++ [temp.expl.spec]p11: // A trailing template-argument can be left unspecified in the // template-id naming an explicit function template specialization @@ -6837,7 +6874,7 @@ bool Sema::CheckFunctionTemplateSpecialization( FunctionDecl *Specialization = nullptr; if (TemplateDeductionResult TDK = DeduceTemplateArguments( cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()), - ExplicitTemplateArgs, FT, Specialization, Info)) { + ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info)) { // Template argument deduction failed; record why it failed, so // that we can provide nifty diagnostics. FailedCandidates.addCandidate() @@ -6848,6 +6885,8 @@ bool Sema::CheckFunctionTemplateSpecialization( } // Record this candidate. + if (ExplicitTemplateArgs) + ConvertedTemplateArgs[Specialization] = std::move(Args); Candidates.addDecl(Specialization, I.getAccess()); } } @@ -6926,10 +6965,10 @@ bool Sema::CheckFunctionTemplateSpecialization( // Take copies of (semantic and syntactic) template argument lists. const TemplateArgumentList* TemplArgs = new (Context) TemplateArgumentList(Specialization->getTemplateSpecializationArgs()); - FD->setFunctionTemplateSpecialization(Specialization->getPrimaryTemplate(), - TemplArgs, /*InsertPos=*/nullptr, - SpecInfo->getTemplateSpecializationKind(), - ExplicitTemplateArgs); + FD->setFunctionTemplateSpecialization( + Specialization->getPrimaryTemplate(), TemplArgs, /*InsertPos=*/nullptr, + SpecInfo->getTemplateSpecializationKind(), + ExplicitTemplateArgs ? &ConvertedTemplateArgs[Specialization] : nullptr); // The "previous declaration" for this function template specialization is // the prior function template specialization. @@ -7429,11 +7468,16 @@ Sema::ActOnExplicitInstantiation(Scope *S, } } + // Set the template specialization kind. Make sure it is set before + // instantiating the members which will trigger ASTConsumer callbacks. + Specialization->setTemplateSpecializationKind(TSK); InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK); + } else { + + // Set the template specialization kind. + Specialization->setTemplateSpecializationKind(TSK); } - // Set the template specialization kind. - Specialization->setTemplateSpecializationKind(TSK); return Specialization; } |