majnemer created this revision.
majnemer added a reviewer: rsmith.
majnemer added a subscriber: cfe-commits.

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.

http://reviews.llvm.org/D13786

Files:
  include/clang/AST/ASTContext.h
  include/clang/AST/DataRecursiveASTVisitor.h
  include/clang/AST/DeclTemplate.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/AST/TemplateName.h
  include/clang/Basic/DeclNodes.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Basic/TokenKinds.def
  include/clang/Sema/Sema.h
  lib/AST/ASTContext.cpp
  lib/AST/ASTDumper.cpp
  lib/AST/ASTImporter.cpp
  lib/AST/DeclBase.cpp
  lib/AST/DeclTemplate.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/TemplateName.cpp
  lib/AST/Type.cpp
  lib/CodeGen/CGDecl.cpp
  lib/Parse/ParseDecl.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaTemplate.cpp
  lib/Sema/SemaTemplateInstantiateDecl.cpp
  lib/Sema/TreeTransform.h
  lib/Serialization/ASTCommon.cpp
  lib/Serialization/ASTReader.cpp
  lib/Serialization/ASTReaderDecl.cpp
  lib/Serialization/ASTWriter.cpp
  tools/libclang/CIndex.cpp

Index: tools/libclang/CIndex.cpp
===================================================================
--- tools/libclang/CIndex.cpp
+++ tools/libclang/CIndex.cpp
@@ -1392,6 +1392,9 @@
     return Visit(MakeCursorTemplateRef(
                   Name.getAsSubstTemplateTemplateParmPack()->getParameterPack(),
                                        Loc, TU));
+
+  case TemplateName::BuiltinTemplate:
+    return false;
   }
 
   llvm_unreachable("Invalid TemplateName::Kind!");
@@ -5110,6 +5113,7 @@
   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
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -5246,6 +5246,9 @@
     AddTemplateArgument(SubstPack->getArgumentPack(), Record);
     break;
   }
+  case TemplateName::BuiltinTemplate: {
+    break;
+  }
   }
 }
 
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -293,6 +293,7 @@
     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::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) {
+  //
+}
+
 /// TODO: Unify with ClassTemplateDecl version?
 ///       May require unifying ClassTemplateDecl and
 ///        VarTemplateDecl beyond TemplateDecl...
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -7619,6 +7619,9 @@
     
     return Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
   }
+  case TemplateName::BuiltinTemplate: {
+    return Context.getBuiltinTemplateName();
+  }
   }
 
   llvm_unreachable("Unhandled template name kind!");
Index: lib/Serialization/ASTCommon.cpp
===================================================================
--- lib/Serialization/ASTCommon.cpp
+++ lib/Serialization/ASTCommon.cpp
@@ -329,6 +329,7 @@
   case Decl::ClassScopeFunctionSpecialization:
   case Decl::Import:
   case Decl::OMPThreadPrivate:
+  case Decl::BuiltinTemplate:
     return false;
 
   // These indirectly derive from Redeclarable<T> but are not actually
Index: lib/Sema/TreeTransform.h
===================================================================
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -3454,6 +3454,9 @@
                                             SubstPack->getArgumentPack());
   }
 
+  if (Name.getKind() == TemplateName::BuiltinTemplate)
+    return Name;
+
   // These should be getting filtered out before they reach the AST.
   llvm_unreachable("overloaded function decl survived to here");
 }
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -922,6 +922,11 @@
   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);
 
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -2017,9 +2017,9 @@
   }
 }
 
-QualType Sema::CheckTemplateIdType(TemplateName Name,
-                                   SourceLocation TemplateLoc,
-                                   TemplateArgumentListInfo &TemplateArgs) {
+QualType
+Sema::CheckTemplateIdType(TemplateName Name, SourceLocation TemplateLoc,
+                          TemplateArgumentListInfo &UnderlyingTemplateArgs) {
   DependentTemplateName *DTN
     = Name.getUnderlying().getAsDependentTemplateName();
   if (DTN && DTN->isIdentifier())
@@ -2030,15 +2030,19 @@
     return Context.getDependentTemplateSpecializationType(ETK_None,
                                                           DTN->getQualifier(),
                                                           DTN->getIdentifier(),
-                                                          TemplateArgs);
+                                                          UnderlyingTemplateArgs);
+
+  bool IsBuiltinTemplate = Name.getKind() == TemplateName::BuiltinTemplate;
+  TemplateDecl *Template = IsBuiltinTemplate ? Context.getBuiltinTemplateDecl()
+                                             : Name.getAsTemplateDecl();
 
-  TemplateDecl *Template = Name.getAsTemplateDecl();
   if (!Template || isa<FunctionTemplateDecl>(Template) ||
       isa<VarTemplateDecl>(Template)) {
     // We might have a substituted template template parameter pack. If so,
     // build a template specialization type for it.
     if (Name.getAsSubstTemplateTemplateParmPack())
-      return Context.getTemplateSpecializationType(Name, TemplateArgs);
+      return Context.getTemplateSpecializationType(Name,
+                                                   UnderlyingTemplateArgs);
 
     Diag(TemplateLoc, diag::err_template_id_not_a_type)
       << Name;
@@ -2049,10 +2053,57 @@
   // Check that the template argument list is well-formed for this
   // template.
   SmallVector<TemplateArgument, 4> Converted;
-  if (CheckTemplateArgumentList(Template, TemplateLoc, TemplateArgs,
+  if (CheckTemplateArgumentList(Template, TemplateLoc, UnderlyingTemplateArgs,
                                 false, Converted))
     return QualType();
 
+  // Instantiations involving __make_integer_seq<S, T, N> are treated like
+  // S<T, 0, ..., N-1>.
+  TemplateArgumentListInfo SyntheticTemplateArgs;
+  TemplateName UnderlyingName = Name;
+  bool UseSyntheticTemplateArgs = false;
+  if (IsBuiltinTemplate) {
+    assert(Converted.size() == 3 && "Unexpected BuiltinTemplate!");
+
+    // Switch our template from __make_integer_seq to S.
+    Name = Converted[0].getAsTemplate();
+    Template = Name.getAsTemplateDecl();
+    TemplateArgument NumArgsArg = Converted[2];
+    if (!NumArgsArg.isDependent()) {
+      // The first template argument will be reused as the template decl that
+      // our synthetic template arguments will be applied to while the last
+      // template argument will be replaced with a pack.
+      TemplateArgument SequenceType = Converted[1];
+      Converted.clear();
+      Converted.push_back(SequenceType);
+      UseSyntheticTemplateArgs = true;
+
+      // Diagnose attempts to create integer sequences with a negative length.
+      llvm::APSInt NumArgs = NumArgsArg.getAsIntegral();
+      if (NumArgs < 0)
+        Diag(UnderlyingTemplateArgs[2].getLocation(),
+             diag::err_integer_sequence_negative_length);
+
+      QualType Ty = NumArgsArg.getIntegralType();
+      SmallVector<TemplateArgument, 2> ArgumentPack;
+      for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
+           I < NumArgs; ++I) {
+        TemplateArgument TA(Context, I, Ty);
+        Expr *E =
+            BuildExpressionFromIntegralTemplateArgument(TA, SourceLocation())
+                .getAs<Expr>();
+        ArgumentPack.push_back(TA);
+        SyntheticTemplateArgs.addArgument(
+            TemplateArgumentLoc(TemplateArgument(E), E));
+      }
+      Converted.push_back(
+          TemplateArgument::CreatePackCopy(Context, ArgumentPack));
+    }
+  }
+
+  TemplateArgumentListInfo &TemplateArgs =
+      UseSyntheticTemplateArgs ? SyntheticTemplateArgs : UnderlyingTemplateArgs;
+
   QualType CanonType;
 
   bool InstantiationDependent = false;
@@ -2085,15 +2136,15 @@
       return QualType();
   } else if (Name.isDependent() ||
              TemplateSpecializationType::anyDependentTemplateArguments(
-               TemplateArgs, InstantiationDependent)) {
+                 TemplateArgs, InstantiationDependent)) {
     // This class template specialization is a dependent
     // type. Therefore, its canonical type is another class template
     // specialization type that contains all of the converted
     // arguments in canonical form. This ensures that, e.g., A<T> and
     // A<T, T> have identical types when A is declared as:
     //
     //   template<typename T, typename U = T> struct A;
-    TemplateName CanonName = Context.getCanonicalTemplateName(Name);
+    TemplateName CanonName = Context.getCanonicalTemplateName(UnderlyingName);
     CanonType = Context.getTemplateSpecializationType(CanonName,
                                                       Converted.data(),
                                                       Converted.size());
@@ -2176,7 +2227,8 @@
   // Build the fully-sugared type for this class template
   // specialization, which refers back to the class template
   // specialization we created or found.
-  return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
+  return Context.getTemplateSpecializationType(
+      UnderlyingName, UnderlyingTemplateArgs, CanonType);
 }
 
 TypeResult
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -727,6 +727,10 @@
   return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
 }
 
+void Sema::actOnBuiltinTemplateName(TemplateTy &TemplateResult) {
+  TemplateResult = TemplateTy::make(Context.getBuiltinTemplateName());
+}
+
 Sema::NameClassification
 Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name,
                    SourceLocation NameLoc, const Token &NextToken,
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -2895,6 +2895,63 @@
       continue;
     }
 
+    case tok::kw___make_integer_seq: {
+      assert(getLangOpts().CPlusPlus &&
+             "Can only annotate template-ids in C++");
+      TemplateTy Template;
+      Actions.actOnBuiltinTemplateName(Template);
+
+      if (!NextToken().is(tok::less)) {
+        DS.SetTypeSpecError();
+        break;
+      }
+
+      // Consume the template-name.
+      SourceLocation TemplateNameLoc = ConsumeToken();
+
+      assert(Template && Tok.is(tok::less) &&
+             "Parser isn't at the beginning of a template-id");
+
+      // Parse the enclosed template argument list.
+      SourceLocation LAngleLoc, RAngleLoc, TemplateKWLoc;
+      TemplateArgList TemplateArgs;
+      CXXScopeSpec SS;
+      bool IsInvalid =
+          ParseTemplateIdAfterTemplateName(Template, TemplateNameLoc, SS, false,
+                                           LAngleLoc, TemplateArgs, RAngleLoc);
+
+      if (IsInvalid) {
+        // If we failed to parse the template ID but skipped ahead to a >,
+        // we're not going to be able to form a token annotation.
+        // Eat the '>' if present.
+        TryConsumeToken(tok::greater);
+        DS.SetTypeSpecError();
+        break;
+      }
+
+      ASTTemplateArgsPtr TemplateArgsPtr(TemplateArgs);
+      TypeResult Type = Actions.ActOnTemplateIdType(SS, TemplateKWLoc, Template,
+                                                    TemplateNameLoc, LAngleLoc,
+                                                    TemplateArgsPtr, RAngleLoc);
+      if (Type.isInvalid()) {
+        // If we failed to parse the template ID but skipped ahead to a >, we're
+        // not
+        // going to be able to form a token annotation.  Eat the '>' if present.
+        TryConsumeToken(tok::greater);
+        DS.SetTypeSpecError();
+        break;
+      }
+
+      Tok.setKind(tok::annot_typename);
+      setTypeAnnotation(Tok, Type.get());
+      Tok.setLocation(TemplateNameLoc);
+      Tok.setAnnotationEndLoc(RAngleLoc);
+      // In case the tokens were cached, have Preprocessor replace them with the
+      // annotation token.
+      PP.AnnotateCachedTokens(Tok);
+      continue;
+    }
+
     case tok::kw___is_signed:
       // GNU libstdc++ 4.4 uses __is_signed as an identifier, but Clang
       // typically treats it as a trait. If we see __is_signed as it appears
Index: lib/CodeGen/CGDecl.cpp
===================================================================
--- lib/CodeGen/CGDecl.cpp
+++ lib/CodeGen/CGDecl.cpp
@@ -35,6 +35,7 @@
 
 void CodeGenFunction::EmitDecl(const Decl &D) {
   switch (D.getKind()) {
+  case Decl::BuiltinTemplate:
   case Decl::TranslationUnit:
   case Decl::ExternCContext:
   case Decl::Namespace:
Index: lib/AST/Type.cpp
===================================================================
--- lib/AST/Type.cpp
+++ lib/AST/Type.cpp
@@ -3105,7 +3105,8 @@
          "Use DependentTemplateSpecializationType for dependent template-name");
   assert((T.getKind() == TemplateName::Template ||
           T.getKind() == TemplateName::SubstTemplateTemplateParm ||
-          T.getKind() == TemplateName::SubstTemplateTemplateParmPack) &&
+          T.getKind() == TemplateName::SubstTemplateTemplateParmPack ||
+          T.getKind() == TemplateName::BuiltinTemplate) &&
          "Unexpected template name for TemplateSpecializationType");
 
   TemplateArgument *TemplateArgs
Index: lib/AST/TemplateName.cpp
===================================================================
--- lib/AST/TemplateName.cpp
+++ lib/AST/TemplateName.cpp
@@ -61,6 +61,8 @@
 
   UncommonTemplateNameStorage *uncommon
     = Storage.get<UncommonTemplateNameStorage*>();
+  if (uncommon->isBuiltin())
+    return BuiltinTemplate;
   if (uncommon->getAsOverloadedStorage())
     return OverloadedTemplate;
   if (uncommon->getAsSubstTemplateTemplateParm())
@@ -147,12 +149,13 @@
   } else if (SubstTemplateTemplateParmStorage *subst
                = getAsSubstTemplateTemplateParm()) {
     subst->getReplacement().print(OS, Policy, SuppressNNS);
-  } else if (SubstTemplateTemplateParmPackStorage *SubstPack
-                                        = getAsSubstTemplateTemplateParmPack())
+  } else if (SubstTemplateTemplateParmPackStorage *SubstPack =
+                 getAsSubstTemplateTemplateParmPack()) {
     OS << *SubstPack->getParameterPack();
-  else {
-    OverloadedTemplateStorage *OTS = getAsOverloadedTemplate();
+  } else if (OverloadedTemplateStorage *OTS = getAsOverloadedTemplate()) {
     (*OTS->begin())->printName(OS);
+  } else if (getKind() == BuiltinTemplate) {
+    OS << "__make_integer_seq";
   }
 }
 
Index: lib/AST/ItaniumMangle.cpp
===================================================================
--- lib/AST/ItaniumMangle.cpp
+++ lib/AST/ItaniumMangle.cpp
@@ -1442,6 +1442,14 @@
   case TemplateName::OverloadedTemplate:
     llvm_unreachable("can't mangle an overloaded template name as a <type>");
 
+  case TemplateName::BuiltinTemplate: {
+    DiagnosticsEngine &Diags = Context.getDiags();
+    unsigned DiagID =
+        Diags.getCustomDiagID(DiagnosticsEngine::Error,
+                              "mangling __make_integer_seq is not supported");
+    Diags.Report(DiagID);
+  }
+
   case TemplateName::DependentTemplate: {
     const DependentTemplateName *Dependent = TN.getAsDependentTemplateName();
     assert(Dependent->isIdentifier());
@@ -1572,6 +1580,7 @@
       break;
     }
 
+    case TemplateName::BuiltinTemplate:
     case TemplateName::OverloadedTemplate:
     case TemplateName::DependentTemplate:
       llvm_unreachable("invalid base for a template specialization type");
Index: lib/AST/DeclTemplate.cpp
===================================================================
--- lib/AST/DeclTemplate.cpp
+++ lib/AST/DeclTemplate.cpp
@@ -1191,3 +1191,52 @@
                                                          unsigned ID) {
   return new (C, ID) VarTemplatePartialSpecializationDecl(C);
 }
+
+static TemplateParameterList *
+createBuiltinTemplateParameterList(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);
+
+  // 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);
+
+  // <typename 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);
+
+  // typename T
+  auto *TemplateTypeParm = TemplateTypeParmDecl::Create(
+      C, DC, SourceLocation(), SourceLocation(), /*Depth=*/0, /*Position=*/1,
+      /*Id=*/nullptr, /*Typename=*/true, /*ParameterPack=*/false);
+
+  // Ints...
+  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, Ints...> class IntSeq, typename T, Ints...>
+  return TemplateParameterList::Create(C, SourceLocation(), SourceLocation(),
+                                       Params, 3, SourceLocation());
+}
+
+void BuiltinTemplateDecl::anchor() {}
+
+BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C, DeclContext *DC)
+    : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), DeclarationName(),
+                   createBuiltinTemplateParameterList(C, DC)) {}
Index: lib/AST/DeclBase.cpp
===================================================================
--- lib/AST/DeclBase.cpp
+++ lib/AST/DeclBase.cpp
@@ -639,6 +639,7 @@
     case ExternCContext:
 
     case UsingDirective:
+    case BuiltinTemplate:
     case ClassTemplateSpecialization:
     case ClassTemplatePartialSpecialization:
     case ClassScopeFunctionSpecialization:
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -5666,6 +5666,9 @@
     
     return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack);
   }
+  case TemplateName::BuiltinTemplate: {
+    return ToContext.getBuiltinTemplateName();
+  }
   }
   
   llvm_unreachable("Invalid template name kind");
Index: lib/AST/ASTDumper.cpp
===================================================================
--- lib/AST/ASTDumper.cpp
+++ lib/AST/ASTDumper.cpp
@@ -447,6 +447,7 @@
         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 +1334,11 @@
   VisitTemplateDecl(D, false);
 }
 
+void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
+  dumpName(D);
+  dumpTemplateParameters(D->getTemplateParameters());
+}
+
 void ASTDumper::VisitVarTemplateSpecializationDecl(
     const VarTemplateSpecializationDecl *D) {
   dumpTemplateArgumentList(D->getTemplateArgs());
Index: lib/AST/ASTContext.cpp
===================================================================
--- lib/AST/ASTContext.cpp
+++ lib/AST/ASTContext.cpp
@@ -741,7 +741,7 @@
       ucontext_tDecl(nullptr), BlockDescriptorType(nullptr),
       BlockDescriptorExtendedType(nullptr), cudaConfigureCallDecl(nullptr),
       FirstLocalImport(), LastLocalImport(), ExternCContext(nullptr),
-      SourceMgr(SM), LangOpts(LOpts),
+      BuiltinTemplate(nullptr), SourceMgr(SM), LangOpts(LOpts),
       SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)),
       AddrSpaceMap(nullptr), Target(nullptr), AuxTarget(nullptr),
       PrintingPolicy(LOpts), Idents(idents), Selectors(sels),
@@ -904,6 +904,16 @@
   return ExternCContext;
 }
 
+BuiltinTemplateDecl *ASTContext::getBuiltinTemplateDecl() const {
+  if (!BuiltinTemplate) {
+    BuiltinTemplate =
+        BuiltinTemplateDecl::Create(*this, getTranslationUnitDecl());
+    BuiltinTemplate->setImplicit();
+  }
+
+  return BuiltinTemplate;
+}
+
 RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
                                             RecordDecl::TagKind TK) const {
   SourceLocation Loc;
@@ -4215,6 +4225,8 @@
 ASTContext::getNameForTemplate(TemplateName Name,
                                SourceLocation NameLoc) const {
   switch (Name.getKind()) {
+  case TemplateName::BuiltinTemplate:
+    return DeclarationNameInfo();
   case TemplateName::QualifiedTemplate:
   case TemplateName::Template:
     // DNInfo work in progress: CHECKME: what about DNLoc?
@@ -4263,6 +4275,8 @@
 
 TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const {
   switch (Name.getKind()) {
+  case TemplateName::BuiltinTemplate:
+    return Name;
   case TemplateName::QualifiedTemplate:
   case TemplateName::Template: {
     TemplateDecl *Template = Name.getAsTemplateDecl();
@@ -6414,6 +6428,13 @@
   ObjCConstantStringType = getObjCInterfaceType(Decl);
 }
 
+/// \brief Retrieve the template name that corresponds to a __make_integer_seq.
+TemplateName ASTContext::getBuiltinTemplateName() const {
+  void *Memory = Allocate(sizeof(BuiltinTemplateStorage));
+  auto *BTS = new (Memory) BuiltinTemplateStorage();
+  return TemplateName(BTS);
+}
+
 /// \brief Retrieve the template name that corresponds to a non-empty
 /// lookup.
 TemplateName
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5498,6 +5498,8 @@
                           QualType ObjectType, bool EnteringContext,
                           bool &MemberOfUnknownSpecialization);
 
+  void actOnBuiltinTemplateName(TemplateTy &TemplateResult);
+
   TemplateNameKind isTemplateName(Scope *S,
                                   CXXScopeSpec &SS,
                                   bool hasTemplateKeyword,
Index: include/clang/Basic/TokenKinds.def
===================================================================
--- include/clang/Basic/TokenKinds.def
+++ include/clang/Basic/TokenKinds.def
@@ -479,6 +479,7 @@
 KEYWORD(__fastcall                  , KEYALL)
 KEYWORD(__thiscall                  , KEYALL)
 KEYWORD(__vectorcall                , KEYALL)
+KEYWORD(__make_integer_seq          , KEYCXX)
 KEYWORD(__forceinline               , KEYMS)
 KEYWORD(__unaligned                 , KEYMS)
 KEYWORD(__super                     , KEYMS)
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1992,7 +1992,11 @@
 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 cannot have a negative sequence length">;
+
 // Objective-C++
 def err_objc_decls_may_only_appear_in_global_scope : Error<
   "Objective-C declarations may only appear in global scope">;
Index: include/clang/Basic/DeclNodes.td
===================================================================
--- include/clang/Basic/DeclNodes.td
+++ include/clang/Basic/DeclNodes.td
@@ -59,6 +59,7 @@
       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;
Index: include/clang/AST/TemplateName.h
===================================================================
--- include/clang/AST/TemplateName.h
+++ include/clang/AST/TemplateName.h
@@ -41,6 +41,7 @@
 class UncommonTemplateNameStorage {
 protected:
   enum Kind {
+    Builtin,
     Overloaded,
     SubstTemplateTemplateParm,
     SubstTemplateTemplateParmPack
@@ -67,7 +68,9 @@
   
 public:
   unsigned size() const { return Bits.Size; }
-  
+
+  bool isBuiltin() { return Bits.Kind == Builtin; }
+
   OverloadedTemplateStorage *getAsOverloadedStorage()  {
     return Bits.Kind == Overloaded
              ? reinterpret_cast<OverloadedTemplateStorage *>(this) 
@@ -86,7 +89,16 @@
              : nullptr;
   }
 };
-  
+
+/// \brief A structure for storing the information associated with an
+/// builtin template name.
+class BuiltinTemplateStorage : public UncommonTemplateNameStorage {
+  friend class ASTContext;
+
+public:
+  BuiltinTemplateStorage() : UncommonTemplateNameStorage(Builtin, 0) {}
+};
+
 /// \brief A structure for storing the information associated with an
 /// overloaded template name.
 class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
@@ -189,25 +201,28 @@
   enum NameKind {
     /// \brief A single template declaration.
     Template,
+    /// \brief An instance of __make_integer_seq.
+    BuiltinTemplate,
     /// \brief A set of overloaded template declarations.
     OverloadedTemplate,
-    /// \brief A qualified template name, where the qualification is kept 
+    /// \brief A qualified template name, where the qualification is kept
     /// to describe the source code as written.
     QualifiedTemplate,
-    /// \brief A dependent template name that has not been resolved to a 
+    /// \brief A dependent template name that has not been resolved to a
     /// template (or set of templates).
     DependentTemplate,
     /// \brief A template template parameter that has been substituted
     /// for some other template name.
     SubstTemplateTemplateParm,
-    /// \brief A template template parameter pack that has been substituted for 
+    /// \brief A template template parameter pack that has been substituted for
     /// a template template argument pack, but has not yet been expanded into
     /// individual arguments.
     SubstTemplateTemplateParmPack
   };
 
   TemplateName() : Storage() { }
   explicit TemplateName(TemplateDecl *Template) : Storage(Template) { }
+  explicit TemplateName(BuiltinTemplateStorage *Storage) : Storage(Storage) {}
   explicit TemplateName(OverloadedTemplateStorage *Storage)
     : Storage(Storage) { }
   explicit TemplateName(SubstTemplateTemplateParmStorage *Storage);
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -1603,6 +1603,10 @@
   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())
Index: include/clang/AST/DeclTemplate.h
===================================================================
--- include/clang/AST/DeclTemplate.h
+++ include/clang/AST/DeclTemplate.h
@@ -1490,6 +1490,28 @@
   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);
+
+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) {
+    return new (C, DC) BuiltinTemplateDecl(C, DC);
+  }
+
+  SourceRange getSourceRange() const override LLVM_READONLY {
+    return SourceRange();
+  }
+};
+
 /// \brief Represents a class template specialization, which refers to
 /// a class template with a given set of template arguments.
 ///
Index: include/clang/AST/DataRecursiveASTVisitor.h
===================================================================
--- include/clang/AST/DataRecursiveASTVisitor.h
+++ include/clang/AST/DataRecursiveASTVisitor.h
@@ -1551,6 +1551,10 @@
     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 { };
Index: include/clang/AST/ASTContext.h
===================================================================
--- include/clang/AST/ASTContext.h
+++ include/clang/AST/ASTContext.h
@@ -399,6 +399,7 @@
   
   TranslationUnitDecl *TUDecl;
   mutable ExternCContextDecl *ExternCContext;
+  mutable BuiltinTemplateDecl *BuiltinTemplate;
 
   /// \brief The associated SourceManager object.a
   SourceManager &SourceMgr;
@@ -821,6 +822,7 @@
   TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
 
   ExternCContextDecl *getExternCContextDecl() const;
+  BuiltinTemplateDecl *getBuiltinTemplateDecl() const;
 
   // Builtin Types.
   CanQualType VoidTy;
@@ -1650,6 +1652,8 @@
   DeclarationNameInfo getNameForTemplate(TemplateName Name,
                                          SourceLocation NameLoc) const;
 
+  TemplateName getBuiltinTemplateName() const;
+
   TemplateName getOverloadedTemplateName(UnresolvedSetIterator Begin,
                                          UnresolvedSetIterator End) const;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to