mirror of https://github.com/microsoft/clang.git
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@252036 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0c29653a59
commit
6bb02a27b9
|
@ -70,6 +70,7 @@ namespace clang {
|
||||||
class VTableContextBase;
|
class VTableContextBase;
|
||||||
|
|
||||||
namespace Builtin { class Context; }
|
namespace Builtin { class Context; }
|
||||||
|
enum BuiltinTemplateKind : int;
|
||||||
|
|
||||||
namespace comments {
|
namespace comments {
|
||||||
class FullComment;
|
class FullComment;
|
||||||
|
@ -246,6 +247,9 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||||
/// The identifier 'NSCopying'.
|
/// The identifier 'NSCopying'.
|
||||||
IdentifierInfo *NSCopyingName = nullptr;
|
IdentifierInfo *NSCopyingName = nullptr;
|
||||||
|
|
||||||
|
/// The identifier '__make_integer_seq'.
|
||||||
|
mutable IdentifierInfo *MakeIntegerSeqName = nullptr;
|
||||||
|
|
||||||
QualType ObjCConstantStringType;
|
QualType ObjCConstantStringType;
|
||||||
mutable RecordDecl *CFConstantStringTypeDecl;
|
mutable RecordDecl *CFConstantStringTypeDecl;
|
||||||
|
|
||||||
|
@ -399,6 +403,7 @@ private:
|
||||||
|
|
||||||
TranslationUnitDecl *TUDecl;
|
TranslationUnitDecl *TUDecl;
|
||||||
mutable ExternCContextDecl *ExternCContext;
|
mutable ExternCContextDecl *ExternCContext;
|
||||||
|
mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
|
||||||
|
|
||||||
/// \brief The associated SourceManager object.a
|
/// \brief The associated SourceManager object.a
|
||||||
SourceManager &SourceMgr;
|
SourceManager &SourceMgr;
|
||||||
|
@ -868,6 +873,7 @@ public:
|
||||||
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
|
TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
|
||||||
|
|
||||||
ExternCContextDecl *getExternCContextDecl() const;
|
ExternCContextDecl *getExternCContextDecl() const;
|
||||||
|
BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
|
||||||
|
|
||||||
// Builtin Types.
|
// Builtin Types.
|
||||||
CanQualType VoidTy;
|
CanQualType VoidTy;
|
||||||
|
@ -941,6 +947,9 @@ public:
|
||||||
void PrintStats() const;
|
void PrintStats() const;
|
||||||
const SmallVectorImpl<Type *>& getTypes() const { return Types; }
|
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
|
/// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl
|
||||||
/// declaration.
|
/// declaration.
|
||||||
RecordDecl *buildImplicitRecord(StringRef Name,
|
RecordDecl *buildImplicitRecord(StringRef Name,
|
||||||
|
@ -1444,6 +1453,12 @@ public:
|
||||||
return NSCopyingName;
|
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;
|
/// \brief Retrieve the Objective-C "instancetype" type, if already known;
|
||||||
/// otherwise, returns a NULL type;
|
/// otherwise, returns a NULL type;
|
||||||
QualType getObjCInstanceType() {
|
QualType getObjCInstanceType() {
|
||||||
|
|
|
@ -1551,6 +1551,10 @@ DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
|
||||||
TRY_TO(TraverseFunctionInstantiations(D));
|
TRY_TO(TraverseFunctionInstantiations(D));
|
||||||
})
|
})
|
||||||
|
|
||||||
|
DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
|
||||||
|
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
||||||
|
})
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
|
DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
|
||||||
// D is the "T" in something like
|
// D is the "T" in something like
|
||||||
// template <template <typename> class T> class container { };
|
// template <template <typename> class T> class container { };
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
|
enum BuiltinTemplateKind : int;
|
||||||
class TemplateParameterList;
|
class TemplateParameterList;
|
||||||
class TemplateDecl;
|
class TemplateDecl;
|
||||||
class RedeclarableTemplateDecl;
|
class RedeclarableTemplateDecl;
|
||||||
|
@ -1490,6 +1491,35 @@ public:
|
||||||
friend TrailingObjects;
|
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
|
/// \brief Represents a class template specialization, which refers to
|
||||||
/// a class template with a given set of template arguments.
|
/// a class template with a given set of template arguments.
|
||||||
///
|
///
|
||||||
|
|
|
@ -1603,6 +1603,10 @@ DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
|
||||||
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
||||||
})
|
})
|
||||||
|
|
||||||
|
DEF_TRAVERSE_DECL(BuiltinTemplateDecl, {
|
||||||
|
TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
|
||||||
|
})
|
||||||
|
|
||||||
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
|
DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
|
||||||
// D is the "T" in something like "template<typename T> class vector;"
|
// D is the "T" in something like "template<typename T> class vector;"
|
||||||
if (D->getTypeForDecl())
|
if (D->getTypeForDecl())
|
||||||
|
|
|
@ -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
|
} // end namespace clang
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,6 +59,7 @@ def Named : Decl<1>;
|
||||||
def VarTemplate : DDecl<RedeclarableTemplate>;
|
def VarTemplate : DDecl<RedeclarableTemplate>;
|
||||||
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
|
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;
|
||||||
def TemplateTemplateParm : DDecl<Template>;
|
def TemplateTemplateParm : DDecl<Template>;
|
||||||
|
def BuiltinTemplate : DDecl<Template>;
|
||||||
def Using : DDecl<Named>;
|
def Using : DDecl<Named>;
|
||||||
def UsingShadow : DDecl<Named>;
|
def UsingShadow : DDecl<Named>;
|
||||||
def ObjCMethod : DDecl<Named>, DeclContext;
|
def ObjCMethod : DDecl<Named>, DeclContext;
|
||||||
|
|
|
@ -1996,6 +1996,12 @@ def warn_cxx98_compat_unicode_type : Warning<
|
||||||
"'%0' type specifier is incompatible with C++98">,
|
"'%0' type specifier is incompatible with C++98">,
|
||||||
InGroup<CXX98Compat>, DefaultIgnore;
|
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++
|
// Objective-C++
|
||||||
def err_objc_decls_may_only_appear_in_global_scope : Error<
|
def err_objc_decls_may_only_appear_in_global_scope : Error<
|
||||||
"Objective-C declarations may only appear in global scope">;
|
"Objective-C declarations may only appear in global scope">;
|
||||||
|
|
|
@ -982,13 +982,16 @@ namespace clang {
|
||||||
|
|
||||||
/// \brief The extern "C" context.
|
/// \brief The extern "C" context.
|
||||||
PREDEF_DECL_EXTERN_C_CONTEXT_ID = 12,
|
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.
|
/// \brief The number of declaration IDs that are predefined.
|
||||||
///
|
///
|
||||||
/// For more information about predefined declarations, see the
|
/// For more information about predefined declarations, see the
|
||||||
/// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants.
|
/// \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.
|
/// \brief Record code for a list of local redeclarations of a declaration.
|
||||||
const unsigned int LOCAL_REDECLARATIONS = 50;
|
const unsigned int LOCAL_REDECLARATIONS = 50;
|
||||||
|
|
|
@ -744,7 +744,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM,
|
||||||
ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
|
ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
|
||||||
BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
|
BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
|
||||||
FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
|
FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
|
||||||
SourceMgr(SM), LangOpts(LOpts),
|
MakeIntegerSeqDecl(nullptr), SourceMgr(SM), LangOpts(LOpts),
|
||||||
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
|
SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
|
||||||
AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
|
AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
|
||||||
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
|
PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
|
||||||
|
@ -913,6 +913,24 @@ ExternCContextDecl *ASTContext::getExternCContextDecl() const {
|
||||||
return ExternCContext;
|
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 *ASTContext::buildImplicitRecord(StringRef Name,
|
||||||
RecordDecl::TagKind TK) const {
|
RecordDecl::TagKind TK) const {
|
||||||
SourceLocation Loc;
|
SourceLocation Loc;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "clang/AST/DeclVisitor.h"
|
#include "clang/AST/DeclVisitor.h"
|
||||||
#include "clang/AST/StmtVisitor.h"
|
#include "clang/AST/StmtVisitor.h"
|
||||||
#include "clang/AST/TypeVisitor.h"
|
#include "clang/AST/TypeVisitor.h"
|
||||||
|
#include "clang/Basic/Builtins.h"
|
||||||
#include "clang/Basic/Module.h"
|
#include "clang/Basic/Module.h"
|
||||||
#include "clang/Basic/SourceManager.h"
|
#include "clang/Basic/SourceManager.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
@ -447,6 +448,7 @@ namespace {
|
||||||
const ClassTemplatePartialSpecializationDecl *D);
|
const ClassTemplatePartialSpecializationDecl *D);
|
||||||
void VisitClassScopeFunctionSpecializationDecl(
|
void VisitClassScopeFunctionSpecializationDecl(
|
||||||
const ClassScopeFunctionSpecializationDecl *D);
|
const ClassScopeFunctionSpecializationDecl *D);
|
||||||
|
void VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D);
|
||||||
void VisitVarTemplateDecl(const VarTemplateDecl *D);
|
void VisitVarTemplateDecl(const VarTemplateDecl *D);
|
||||||
void VisitVarTemplateSpecializationDecl(
|
void VisitVarTemplateSpecializationDecl(
|
||||||
const VarTemplateSpecializationDecl *D);
|
const VarTemplateSpecializationDecl *D);
|
||||||
|
@ -1333,6 +1335,11 @@ void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
|
||||||
VisitTemplateDecl(D, false);
|
VisitTemplateDecl(D, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
|
||||||
|
dumpName(D);
|
||||||
|
dumpTemplateParameters(D->getTemplateParameters());
|
||||||
|
}
|
||||||
|
|
||||||
void ASTDumper::VisitVarTemplateSpecializationDecl(
|
void ASTDumper::VisitVarTemplateSpecializationDecl(
|
||||||
const VarTemplateSpecializationDecl *D) {
|
const VarTemplateSpecializationDecl *D) {
|
||||||
dumpTemplateArgumentList(D->getTemplateArgs());
|
dumpTemplateArgumentList(D->getTemplateArgs());
|
||||||
|
|
|
@ -639,6 +639,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) {
|
||||||
case ExternCContext:
|
case ExternCContext:
|
||||||
|
|
||||||
case UsingDirective:
|
case UsingDirective:
|
||||||
|
case BuiltinTemplate:
|
||||||
case ClassTemplateSpecialization:
|
case ClassTemplateSpecialization:
|
||||||
case ClassTemplatePartialSpecialization:
|
case ClassTemplatePartialSpecialization:
|
||||||
case ClassScopeFunctionSpecialization:
|
case ClassScopeFunctionSpecialization:
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "clang/AST/Expr.h"
|
#include "clang/AST/Expr.h"
|
||||||
#include "clang/AST/ExprCXX.h"
|
#include "clang/AST/ExprCXX.h"
|
||||||
#include "clang/AST/TypeLoc.h"
|
#include "clang/AST/TypeLoc.h"
|
||||||
|
#include "clang/Basic/Builtins.h"
|
||||||
#include "clang/Basic/IdentifierTable.h"
|
#include "clang/Basic/IdentifierTable.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -1191,3 +1192,69 @@ VarTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
|
||||||
unsigned ID) {
|
unsigned ID) {
|
||||||
return new (C, ID) VarTemplatePartialSpecializationDecl(C);
|
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) {}
|
||||||
|
|
|
@ -35,6 +35,7 @@ using namespace CodeGen;
|
||||||
|
|
||||||
void CodeGenFunction::EmitDecl(const Decl &D) {
|
void CodeGenFunction::EmitDecl(const Decl &D) {
|
||||||
switch (D.getKind()) {
|
switch (D.getKind()) {
|
||||||
|
case Decl::BuiltinTemplate:
|
||||||
case Decl::TranslationUnit:
|
case Decl::TranslationUnit:
|
||||||
case Decl::ExternCContext:
|
case Decl::ExternCContext:
|
||||||
case Decl::Namespace:
|
case Decl::Namespace:
|
||||||
|
|
|
@ -627,6 +627,11 @@ static bool LookupBuiltin(Sema &S, LookupResult &R) {
|
||||||
R.addDecl(S.getASTContext().getFloat128StubType());
|
R.addDecl(S.getASTContext().getFloat128StubType());
|
||||||
return true;
|
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 this is a builtin on this (or all) targets, create the decl.
|
||||||
if (unsigned BuiltinID = II->getBuiltinID()) {
|
if (unsigned BuiltinID = II->getBuiltinID()) {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "clang/AST/ExprCXX.h"
|
#include "clang/AST/ExprCXX.h"
|
||||||
#include "clang/AST/RecursiveASTVisitor.h"
|
#include "clang/AST/RecursiveASTVisitor.h"
|
||||||
#include "clang/AST/TypeVisitor.h"
|
#include "clang/AST/TypeVisitor.h"
|
||||||
|
#include "clang/Basic/Builtins.h"
|
||||||
#include "clang/Basic/LangOptions.h"
|
#include "clang/Basic/LangOptions.h"
|
||||||
#include "clang/Basic/PartialDiagnostic.h"
|
#include "clang/Basic/PartialDiagnostic.h"
|
||||||
#include "clang/Basic/TargetInfo.h"
|
#include "clang/Basic/TargetInfo.h"
|
||||||
|
@ -208,7 +209,8 @@ TemplateNameKind Sema::isTemplateName(Scope *S,
|
||||||
R.suppressDiagnostics();
|
R.suppressDiagnostics();
|
||||||
} else {
|
} else {
|
||||||
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
|
assert(isa<ClassTemplateDecl>(TD) || isa<TemplateTemplateParmDecl>(TD) ||
|
||||||
isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD));
|
isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) ||
|
||||||
|
isa<BuiltinTemplateDecl>(TD));
|
||||||
TemplateKind =
|
TemplateKind =
|
||||||
isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
|
isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;
|
||||||
}
|
}
|
||||||
|
@ -2017,6 +2019,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,
|
QualType Sema::CheckTemplateIdType(TemplateName Name,
|
||||||
SourceLocation TemplateLoc,
|
SourceLocation TemplateLoc,
|
||||||
TemplateArgumentListInfo &TemplateArgs) {
|
TemplateArgumentListInfo &TemplateArgs) {
|
||||||
|
@ -2171,6 +2225,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
|
||||||
CanonType = Context.getTypeDeclType(Decl);
|
CanonType = Context.getTypeDeclType(Decl);
|
||||||
assert(isa<RecordType>(CanonType) &&
|
assert(isa<RecordType>(CanonType) &&
|
||||||
"type of non-dependent specialization is not a RecordType");
|
"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
|
// Build the fully-sugared type for this class template
|
||||||
|
|
|
@ -922,6 +922,11 @@ Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) {
|
||||||
llvm_unreachable("EnumConstantDecls can only occur within EnumDecls.");
|
llvm_unreachable("EnumConstantDecls can only occur within EnumDecls.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Decl *
|
||||||
|
TemplateDeclInstantiator::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
|
||||||
|
llvm_unreachable("BuiltinTemplateDecls cannot be instantiated.");
|
||||||
|
}
|
||||||
|
|
||||||
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||||
bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
|
bool isFriend = (D->getFriendObjectKind() != Decl::FOK_None);
|
||||||
|
|
||||||
|
|
|
@ -329,6 +329,7 @@ bool serialization::isRedeclarableDeclKind(unsigned Kind) {
|
||||||
case Decl::ClassScopeFunctionSpecialization:
|
case Decl::ClassScopeFunctionSpecialization:
|
||||||
case Decl::Import:
|
case Decl::Import:
|
||||||
case Decl::OMPThreadPrivate:
|
case Decl::OMPThreadPrivate:
|
||||||
|
case Decl::BuiltinTemplate:
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// These indirectly derive from Redeclarable<T> but are not actually
|
// These indirectly derive from Redeclarable<T> but are not actually
|
||||||
|
|
|
@ -6412,6 +6412,9 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {
|
||||||
|
|
||||||
case PREDEF_DECL_EXTERN_C_CONTEXT_ID:
|
case PREDEF_DECL_EXTERN_C_CONTEXT_ID:
|
||||||
return Context.getExternCContextDecl();
|
return Context.getExternCContextDecl();
|
||||||
|
|
||||||
|
case PREDEF_DECL_MAKE_INTEGER_SEQ_ID:
|
||||||
|
return Context.getMakeIntegerSeqDecl();
|
||||||
}
|
}
|
||||||
llvm_unreachable("PredefinedDeclIDs unknown enum value");
|
llvm_unreachable("PredefinedDeclIDs unknown enum value");
|
||||||
}
|
}
|
||||||
|
|
|
@ -293,6 +293,7 @@ namespace clang {
|
||||||
DeclID VisitTemplateDecl(TemplateDecl *D);
|
DeclID VisitTemplateDecl(TemplateDecl *D);
|
||||||
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
|
RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
|
||||||
void VisitClassTemplateDecl(ClassTemplateDecl *D);
|
void VisitClassTemplateDecl(ClassTemplateDecl *D);
|
||||||
|
void VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D);
|
||||||
void VisitVarTemplateDecl(VarTemplateDecl *D);
|
void VisitVarTemplateDecl(VarTemplateDecl *D);
|
||||||
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
|
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
|
||||||
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
|
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
|
||||||
|
@ -1856,6 +1857,10 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
|
||||||
|
llvm_unreachable("BuiltinTemplates are not serialized");
|
||||||
|
}
|
||||||
|
|
||||||
/// TODO: Unify with ClassTemplateDecl version?
|
/// TODO: Unify with ClassTemplateDecl version?
|
||||||
/// May require unifying ClassTemplateDecl and
|
/// May require unifying ClassTemplateDecl and
|
||||||
/// VarTemplateDecl beyond TemplateDecl...
|
/// VarTemplateDecl beyond TemplateDecl...
|
||||||
|
|
|
@ -4136,6 +4136,8 @@ uint64_t ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot,
|
||||||
RegisterPredefDecl(Context.BuiltinMSVaListDecl,
|
RegisterPredefDecl(Context.BuiltinMSVaListDecl,
|
||||||
PREDEF_DECL_BUILTIN_MS_VA_LIST_ID);
|
PREDEF_DECL_BUILTIN_MS_VA_LIST_ID);
|
||||||
RegisterPredefDecl(Context.ExternCContext, PREDEF_DECL_EXTERN_C_CONTEXT_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
|
// Build a record containing all of the tentative definitions in this file, in
|
||||||
// TentativeDefinitions order. Generally, this record will be empty for
|
// TentativeDefinitions order. Generally, this record will be empty for
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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}}
|
|
@ -5110,6 +5110,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) {
|
||||||
case Decl::Import:
|
case Decl::Import:
|
||||||
case Decl::OMPThreadPrivate:
|
case Decl::OMPThreadPrivate:
|
||||||
case Decl::ObjCTypeParam:
|
case Decl::ObjCTypeParam:
|
||||||
|
case Decl::BuiltinTemplate:
|
||||||
return C;
|
return C;
|
||||||
|
|
||||||
// Declaration kinds that don't make any sense here, but are
|
// Declaration kinds that don't make any sense here, but are
|
||||||
|
|
Loading…
Reference in New Issue