From 6bb02a27b9161e772ec3fd64c8ee9955787d583e Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 4 Nov 2015 03:40:30 +0000 Subject: [PATCH] [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 takes 0.25 seconds. std::make_integer_sequence 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 --- include/clang/AST/ASTContext.h | 15 +++++ include/clang/AST/DataRecursiveASTVisitor.h | 4 ++ include/clang/AST/DeclTemplate.h | 30 +++++++++ include/clang/AST/RecursiveASTVisitor.h | 4 ++ include/clang/Basic/Builtins.h | 7 +++ include/clang/Basic/DeclNodes.td | 1 + include/clang/Basic/DiagnosticSemaKinds.td | 8 ++- include/clang/Serialization/ASTBitCodes.h | 5 +- lib/AST/ASTContext.cpp | 20 +++++- lib/AST/ASTDumper.cpp | 7 +++ lib/AST/DeclBase.cpp | 1 + lib/AST/DeclTemplate.cpp | 67 +++++++++++++++++++++ lib/CodeGen/CGDecl.cpp | 1 + lib/Sema/SemaLookup.cpp | 5 ++ lib/Sema/SemaTemplate.cpp | 59 +++++++++++++++++- lib/Sema/SemaTemplateInstantiateDecl.cpp | 5 ++ lib/Serialization/ASTCommon.cpp | 1 + lib/Serialization/ASTReader.cpp | 3 + lib/Serialization/ASTReaderDecl.cpp | 5 ++ lib/Serialization/ASTWriter.cpp | 2 + test/PCH/make-integer-seq.cpp | 14 +++++ test/SemaCXX/make_integer_seq.cpp | 47 +++++++++++++++ tools/libclang/CIndex.cpp | 1 + 23 files changed, 308 insertions(+), 4 deletions(-) create mode 100644 test/PCH/make-integer-seq.cpp create mode 100644 test/SemaCXX/make_integer_seq.cpp diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index a16c74ed51..72bbb606df 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -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& 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() { diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index 25e2c069ba..cc80a68436 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -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