Author: majnemer Date: Tue Nov 3 21:40:30 2015 New Revision: 252036 URL: http://llvm.org/viewvc/llvm-project?rev=252036&view=rev Log: [Sema] Implement __make_integer_seq
This new builtin template allows for incredibly fast instantiations of templates like std::integer_sequence. Performance numbers follow: My work station has 64 GB of ram + 20 Xeon Cores at 2.8 GHz. __make_integer_seq<std::integer_sequence, int, 90000> takes 0.25 seconds. std::make_integer_sequence<int, 90000> takes unbound time, it is still running. Clang is consuming gigabytes of memory. Differential Revision: http://reviews.llvm.org/D13786 Added: cfe/trunk/test/PCH/make-integer-seq.cpp cfe/trunk/test/SemaCXX/make_integer_seq.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h cfe/trunk/include/clang/AST/DeclTemplate.h cfe/trunk/include/clang/AST/RecursiveASTVisitor.h cfe/trunk/include/clang/Basic/Builtins.h cfe/trunk/include/clang/Basic/DeclNodes.td cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td cfe/trunk/include/clang/Serialization/ASTBitCodes.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/lib/AST/ASTDumper.cpp cfe/trunk/lib/AST/DeclBase.cpp cfe/trunk/lib/AST/DeclTemplate.cpp cfe/trunk/lib/CodeGen/CGDecl.cpp cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp cfe/trunk/lib/Serialization/ASTCommon.cpp cfe/trunk/lib/Serialization/ASTReader.cpp cfe/trunk/lib/Serialization/ASTReaderDecl.cpp cfe/trunk/lib/Serialization/ASTWriter.cpp cfe/trunk/tools/libclang/CIndex.cpp Modified: cfe/trunk/include/clang/AST/ASTContext.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTContext.h (original) +++ cfe/trunk/include/clang/AST/ASTContext.h Tue Nov 3 21:40:30 2015 @@ -70,6 +70,7 @@ namespace clang { class VTableContextBase; namespace Builtin { class Context; } + enum BuiltinTemplateKind : int; namespace comments { class FullComment; @@ -246,6 +247,9 @@ class ASTContext : public RefCountedBase /// The identifier 'NSCopying'. IdentifierInfo *NSCopyingName = nullptr; + /// The identifier '__make_integer_seq'. + mutable IdentifierInfo *MakeIntegerSeqName = nullptr; + QualType ObjCConstantStringType; mutable RecordDecl *CFConstantStringTypeDecl; @@ -399,6 +403,7 @@ private: TranslationUnitDecl *TUDecl; mutable ExternCContextDecl *ExternCContext; + mutable BuiltinTemplateDecl *MakeIntegerSeqDecl; /// \brief The associated SourceManager object.a SourceManager &SourceMgr; @@ -868,6 +873,7 @@ public: TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } ExternCContextDecl *getExternCContextDecl() const; + BuiltinTemplateDecl *getMakeIntegerSeqDecl() const; // Builtin Types. CanQualType VoidTy; @@ -941,6 +947,9 @@ public: void PrintStats() const; const SmallVectorImpl<Type *>& getTypes() const { return Types; } + BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK, + const IdentifierInfo *II) const; + /// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl /// declaration. RecordDecl *buildImplicitRecord(StringRef Name, @@ -1444,6 +1453,12 @@ public: return NSCopyingName; } + IdentifierInfo *getMakeIntegerSeqName() const { + if (!MakeIntegerSeqName) + MakeIntegerSeqName = &Idents.get("__make_integer_seq"); + return MakeIntegerSeqName; + } + /// \brief Retrieve the Objective-C "instancetype" type, if already known; /// otherwise, returns a NULL type; QualType getObjCInstanceType() { Modified: cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/DataRecursiveASTVisitor.h Tue Nov 3 21:40:30 2015 @@ -1551,6 +1551,10 @@ DEF_TRAVERSE_DECL(FunctionTemplateDecl, TRY_TO(TraverseFunctionInstantiations(D)); }) +DEF_TRAVERSE_DECL(BuiltinTemplateDecl, { + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); +}) + DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { // D is the "T" in something like // template <template <typename> class T> class container { }; Modified: cfe/trunk/include/clang/AST/DeclTemplate.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclTemplate.h (original) +++ cfe/trunk/include/clang/AST/DeclTemplate.h Tue Nov 3 21:40:30 2015 @@ -25,6 +25,7 @@ namespace clang { +enum BuiltinTemplateKind : int; class TemplateParameterList; class TemplateDecl; class RedeclarableTemplateDecl; @@ -1490,6 +1491,35 @@ public: friend TrailingObjects; }; +/// \brief Represents the builtin template declaration which is used to +/// implement __make_integer_seq. It serves no real purpose beyond existing as +/// a place to hold template parameters. +class BuiltinTemplateDecl : public TemplateDecl { + void anchor() override; + + BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC, + DeclarationName Name, BuiltinTemplateKind BTK); + + BuiltinTemplateKind BTK; + +public: + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == BuiltinTemplate; } + + static BuiltinTemplateDecl *Create(const ASTContext &C, DeclContext *DC, + DeclarationName Name, + BuiltinTemplateKind BTK) { + return new (C, DC) BuiltinTemplateDecl(C, DC, Name, BTK); + } + + SourceRange getSourceRange() const override LLVM_READONLY { + return SourceRange(); + } + + BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; } +}; + /// \brief Represents a class template specialization, which refers to /// a class template with a given set of template arguments. /// Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original) +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Nov 3 21:40:30 2015 @@ -1603,6 +1603,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDe TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); }) +DEF_TRAVERSE_DECL(BuiltinTemplateDecl, { + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); +}) + DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { // D is the "T" in something like "template<typename T> class vector;" if (D->getTypeForDecl()) Modified: cfe/trunk/include/clang/Basic/Builtins.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.h?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/Builtins.h (original) +++ cfe/trunk/include/clang/Basic/Builtins.h Tue Nov 3 21:40:30 2015 @@ -205,5 +205,12 @@ private: }; } + +/// \brief Kinds of BuiltinTemplateDecl. +enum BuiltinTemplateKind : int { + /// \brief This names the __make_integer_seq BuiltinTemplateDecl. + BTK__make_integer_seq +}; + } // end namespace clang #endif Modified: cfe/trunk/include/clang/Basic/DeclNodes.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DeclNodes.td (original) +++ cfe/trunk/include/clang/Basic/DeclNodes.td Tue Nov 3 21:40:30 2015 @@ -59,6 +59,7 @@ def Named : Decl<1>; def VarTemplate : DDecl<RedeclarableTemplate>; def TypeAliasTemplate : DDecl<RedeclarableTemplate>; def TemplateTemplateParm : DDecl<Template>; + def BuiltinTemplate : DDecl<Template>; def Using : DDecl<Named>; def UsingShadow : DDecl<Named>; def ObjCMethod : DDecl<Named>, DeclContext; Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Nov 3 21:40:30 2015 @@ -1995,7 +1995,13 @@ def err_concept_decl_invalid_specifiers def warn_cxx98_compat_unicode_type : Warning< "'%0' type specifier is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; - + +// __make_integer_seq +def err_integer_sequence_negative_length : Error< + "integer sequences must have non-negative sequence length">; +def err_integer_sequence_integral_element_type : Error< + "integer sequences must have integral element type">; + // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< "Objective-C declarations may only appear in global scope">; Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original) +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Nov 3 21:40:30 2015 @@ -982,13 +982,16 @@ namespace clang { /// \brief The extern "C" context. PREDEF_DECL_EXTERN_C_CONTEXT_ID = 12, + + /// \brief The internal '__make_integer_seq' template. + PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13, }; /// \brief The number of declaration IDs that are predefined. /// /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. - const unsigned int NUM_PREDEF_DECL_IDS = 13; + const unsigned int NUM_PREDEF_DECL_IDS = 14; /// \brief Record code for a list of local redeclarations of a declaration. const unsigned int LOCAL_REDECLARATIONS = 50; Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Tue Nov 3 21:40:30 2015 @@ -744,7 +744,7 @@ ASTContext::ASTContext(LangOptions &LOpt ucontext_tDecl(nullptr), BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr), FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr), - SourceMgr(SM), LangOpts(LOpts), + MakeIntegerSeqDecl(nullptr), SourceMgr(SM), LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), @@ -913,6 +913,24 @@ ExternCContextDecl *ASTContext::getExter return ExternCContext; } +BuiltinTemplateDecl * +ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateKind BTK, + const IdentifierInfo *II) const { + auto *BuiltinTemplate = BuiltinTemplateDecl::Create(*this, TUDecl, II, BTK); + BuiltinTemplate->setImplicit(); + TUDecl->addDecl(BuiltinTemplate); + + return BuiltinTemplate; +} + +BuiltinTemplateDecl * +ASTContext::getMakeIntegerSeqDecl() const { + if (!MakeIntegerSeqDecl) + MakeIntegerSeqDecl = buildBuiltinTemplateDecl(BTK__make_integer_seq, + getMakeIntegerSeqName()); + return MakeIntegerSeqDecl; +} + RecordDecl *ASTContext::buildImplicitRecord(StringRef Name, RecordDecl::TagKind TK) const { SourceLocation Loc; Modified: cfe/trunk/lib/AST/ASTDumper.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTDumper.cpp (original) +++ cfe/trunk/lib/AST/ASTDumper.cpp Tue Nov 3 21:40:30 2015 @@ -21,6 +21,7 @@ #include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" #include "clang/AST/TypeVisitor.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/raw_ostream.h" @@ -447,6 +448,7 @@ namespace { const ClassTemplatePartialSpecializationDecl *D); void VisitClassScopeFunctionSpecializationDecl( const ClassScopeFunctionSpecializationDecl *D); + void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D); void VisitVarTemplateDecl(const VarTemplateDecl *D); void VisitVarTemplateSpecializationDecl( const VarTemplateSpecializationDecl *D); @@ -1333,6 +1335,11 @@ void ASTDumper::VisitVarTemplateDecl(con VisitTemplateDecl(D, false); } +void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); +} + void ASTDumper::VisitVarTemplateSpecializationDecl( const VarTemplateSpecializationDecl *D) { dumpTemplateArgumentList(D->getTemplateArgs()); Modified: cfe/trunk/lib/AST/DeclBase.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclBase.cpp (original) +++ cfe/trunk/lib/AST/DeclBase.cpp Tue Nov 3 21:40:30 2015 @@ -639,6 +639,7 @@ unsigned Decl::getIdentifierNamespaceFor case ExternCContext: case UsingDirective: + case BuiltinTemplate: case ClassTemplateSpecialization: case ClassTemplatePartialSpecialization: case ClassScopeFunctionSpecialization: Modified: cfe/trunk/lib/AST/DeclTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/AST/DeclTemplate.cpp (original) +++ cfe/trunk/lib/AST/DeclTemplate.cpp Tue Nov 3 21:40:30 2015 @@ -18,6 +18,7 @@ #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/Builtins.h" #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/STLExtras.h" #include <memory> @@ -1191,3 +1192,69 @@ VarTemplatePartialSpecializationDecl::Cr unsigned ID) { return new (C, ID) VarTemplatePartialSpecializationDecl(C); } + +static TemplateParameterList * +createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) { + // typename T + auto *T = TemplateTypeParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/1, /*Position=*/0, + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); + T->setImplicit(true); + + // T ...Ints + TypeSourceInfo *TI = + C.getTrivialTypeSourceInfo(QualType(T->getTypeForDecl(), 0)); + auto *N = NonTypeTemplateParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, + /*Id=*/nullptr, TI->getType(), /*ParameterPack=*/true, TI); + N->setImplicit(true); + + // <typename T, T ...Ints> + NamedDecl *P[2] = {T, N}; + auto *TPL = TemplateParameterList::Create( + C, SourceLocation(), SourceLocation(), P, 2, SourceLocation()); + + // template <typename T, ...Ints> class IntSeq + auto *TemplateTemplateParm = TemplateTemplateParmDecl::Create( + C, DC, SourceLocation(), /*Depth=*/0, /*Position=*/0, + /*ParameterPack=*/false, /*Id=*/nullptr, TPL); + TemplateTemplateParm->setImplicit(true); + + // typename T + auto *TemplateTypeParm = TemplateTypeParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1, + /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false); + TemplateTypeParm->setImplicit(true); + + // T N + TypeSourceInfo *TInfo = C.getTrivialTypeSourceInfo( + QualType(TemplateTypeParm->getTypeForDecl(), 0)); + auto *NonTypeTemplateParm = NonTypeTemplateParmDecl::Create( + C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/2, + /*Id=*/nullptr, TInfo->getType(), /*ParameterPack=*/false, TInfo); + NamedDecl *Params[] = {TemplateTemplateParm, TemplateTypeParm, + NonTypeTemplateParm}; + + // template <template <typename T, T ...Ints> class IntSeq, typename T, T N> + return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(), + Params, 3, SourceLocation()); +} + +static TemplateParameterList *createBuiltinTemplateParameterList( + const ASTContext &C, DeclContext *DC, BuiltinTemplateKind BTK) { + switch (BTK) { + case BTK__make_integer_seq: + return createMakeIntegerSeqParameterList(C, DC); + } + + llvm_unreachable("unhandled BuiltinTemplateKind!"); +} + +void BuiltinTemplateDecl::anchor() {} + +BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC, + DeclarationName Name, + BuiltinTemplateKind BTK) + : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), Name, + createBuiltinTemplateParameterList(C, DC, BTK)), + BTK(BTK) {} Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Nov 3 21:40:30 2015 @@ -35,6 +35,7 @@ using namespace CodeGen; void CodeGenFunction::EmitDecl(const Decl &D) { switch (D.getKind()) { + case Decl::BuiltinTemplate: case Decl::TranslationUnit: case Decl::ExternCContext: case Decl::Namespace: Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Nov 3 21:40:30 2015 @@ -627,6 +627,11 @@ static bool LookupBuiltin(Sema &S, Looku R.addDecl(S.getASTContext().getFloat128StubType()); return true; } + if (S.getLangOpts().CPlusPlus && NameKind == Sema::LookupOrdinaryName && + II == S.getASTContext().getMakeIntegerSeqName()) { + R.addDecl(S.getASTContext().getMakeIntegerSeqDecl()); + return true; + } // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) { Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Nov 3 21:40:30 2015 @@ -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(Sc 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; } @@ -2017,6 +2019,58 @@ void Sema::NoteAllFoundTemplates(Templat } } +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 +2225,9 @@ QualType Sema::CheckTemplateIdType(Templ 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 Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Nov 3 21:40:30 2015 @@ -922,6 +922,11 @@ Decl *TemplateDeclInstantiator::VisitEnu llvm_unreachable("EnumConstantDecls can only occur within EnumDecls."); } +Decl * +TemplateDeclInstantiator::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { + llvm_unreachable("BuiltinTemplateDecls cannot be instantiated."); +} + Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None); Modified: cfe/trunk/lib/Serialization/ASTCommon.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTCommon.cpp (original) +++ cfe/trunk/lib/Serialization/ASTCommon.cpp Tue Nov 3 21:40:30 2015 @@ -329,6 +329,7 @@ bool serialization::isRedeclarableDeclKi case Decl::ClassScopeFunctionSpecialization: case Decl::Import: case Decl::OMPThreadPrivate: + case Decl::BuiltinTemplate: return false; // These indirectly derive from Redeclarable<T> but are not actually Modified: cfe/trunk/lib/Serialization/ASTReader.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReader.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Nov 3 21:40:30 2015 @@ -6412,6 +6412,9 @@ static Decl *getPredefinedDecl(ASTContex case PREDEF_DECL_EXTERN_C_CONTEXT_ID: return Context.getExternCContextDecl(); + + case PREDEF_DECL_MAKE_INTEGER_SEQ_ID: + return Context.getMakeIntegerSeqDecl(); } llvm_unreachable("PredefinedDeclIDs unknown enum value"); } Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original) +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Nov 3 21:40:30 2015 @@ -293,6 +293,7 @@ namespace clang { DeclID VisitTemplateDecl(TemplateDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); + void VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D); void VisitVarTemplateDecl(VarTemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); @@ -1856,6 +1857,10 @@ void ASTDeclReader::VisitClassTemplateDe } } +void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { + llvm_unreachable("BuiltinTemplates are not serialized"); +} + /// TODO: Unify with ClassTemplateDecl version? /// May require unifying ClassTemplateDecl and /// VarTemplateDecl beyond TemplateDecl... Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original) +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Nov 3 21:40:30 2015 @@ -4136,6 +4136,8 @@ uint64_t ASTWriter::WriteASTCore(Sema &S RegisterPredefDecl(Context.BuiltinMSVaListDecl, PREDEF_DECL_BUILTIN_MS_VA_LIST_ID); RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_ID); + RegisterPredefDecl(Context.MakeIntegerSeqDecl, + PREDEF_DECL_MAKE_INTEGER_SEQ_ID); // Build a record containing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for Added: cfe/trunk/test/PCH/make-integer-seq.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/make-integer-seq.cpp?rev=252036&view=auto ============================================================================== --- cfe/trunk/test/PCH/make-integer-seq.cpp (added) +++ cfe/trunk/test/PCH/make-integer-seq.cpp Tue Nov 3 21:40:30 2015 @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -std=c++14 -x c++-header %s -emit-pch -o %t.pch +// RUN: %clang_cc1 -std=c++14 -x c++ /dev/null -include-pch %t.pch + +template <class T, T... I> +struct Seq { + static constexpr T PackSize = sizeof...(I); +}; + +template <typename T, T N> +using MakeSeq = __make_integer_seq<Seq, T, N>; + +void fn1() { + MakeSeq<int, 3> x; +} Added: cfe/trunk/test/SemaCXX/make_integer_seq.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/make_integer_seq.cpp?rev=252036&view=auto ============================================================================== --- cfe/trunk/test/SemaCXX/make_integer_seq.cpp (added) +++ cfe/trunk/test/SemaCXX/make_integer_seq.cpp Tue Nov 3 21:40:30 2015 @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s + +template <class T, T... I> +struct Seq { + static constexpr T PackSize = sizeof...(I); +}; + +template <typename T, T N> +using MakeSeq = __make_integer_seq<Seq, T, N>; + +static_assert(__is_same(MakeSeq<int, 0>, Seq<int>), ""); +static_assert(__is_same(MakeSeq<int, 1>, Seq<int, 0>), ""); +static_assert(__is_same(MakeSeq<int, 2>, Seq<int, 0, 1>), ""); +static_assert(__is_same(MakeSeq<int, 3>, Seq<int, 0, 1, 2>), ""); +static_assert(__is_same(MakeSeq<int, 4>, Seq<int, 0, 1, 2, 3>), ""); + +static_assert(__is_same(MakeSeq<unsigned int, 0U>, Seq<unsigned int>), ""); +static_assert(__is_same(MakeSeq<unsigned int, 1U>, Seq<unsigned int, 0U>), ""); +static_assert(__is_same(MakeSeq<unsigned int, 2U>, Seq<unsigned int, 0U, 1U>), ""); +static_assert(__is_same(MakeSeq<unsigned int, 3U>, Seq<unsigned int, 0U, 1U, 2U>), ""); +static_assert(__is_same(MakeSeq<unsigned int, 4U>, Seq<unsigned int, 0U, 1U, 2U, 3U>), ""); + +static_assert(__is_same(MakeSeq<long long, 0LL>, Seq<long long>), ""); +static_assert(__is_same(MakeSeq<long long, 1LL>, Seq<long long, 0LL>), ""); +static_assert(__is_same(MakeSeq<long long, 2LL>, Seq<long long, 0LL, 1LL>), ""); +static_assert(__is_same(MakeSeq<long long, 3LL>, Seq<long long, 0LL, 1LL, 2LL>), ""); +static_assert(__is_same(MakeSeq<long long, 4LL>, Seq<long long, 0LL, 1LL, 2LL, 3LL>), ""); + +static_assert(__is_same(MakeSeq<unsigned long long, 0ULL>, Seq<unsigned long long>), ""); +static_assert(__is_same(MakeSeq<unsigned long long, 1ULL>, Seq<unsigned long long, 0ULL>), ""); +static_assert(__is_same(MakeSeq<unsigned long long, 2ULL>, Seq<unsigned long long, 0ULL, 1ULL>), ""); +static_assert(__is_same(MakeSeq<unsigned long long, 3ULL>, Seq<unsigned long long, 0ULL, 1ULL, 2ULL>), ""); +static_assert(__is_same(MakeSeq<unsigned long long, 4ULL>, Seq<unsigned long long, 0ULL, 1ULL, 2ULL, 3ULL>), ""); + +template <typename T, T N> +using ErrorSeq = __make_integer_seq<Seq, T, N>; // expected-error{{must have non-negative sequence length}} \ + expected-error{{must have integral element type}} + +enum Color : int { Red, + Green, + Blue }; +using illformed1 = ErrorSeq<Color, Blue>; // expected-note{{in instantiation}} + +using illformed2 = ErrorSeq<int, -5>; + +template <typename T, T N> void f() {} +__make_integer_seq<f, int, 0> x; // expected-error{{template template parameter must be a class template or type alias template}} Modified: cfe/trunk/tools/libclang/CIndex.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=252036&r1=252035&r2=252036&view=diff ============================================================================== --- cfe/trunk/tools/libclang/CIndex.cpp (original) +++ cfe/trunk/tools/libclang/CIndex.cpp Tue Nov 3 21:40:30 2015 @@ -5110,6 +5110,7 @@ CXCursor clang_getCursorDefinition(CXCur case Decl::Import: case Decl::OMPThreadPrivate: case Decl::ObjCTypeParam: + case Decl::BuiltinTemplate: return C; // Declaration kinds that don't make any sense here, but are _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits