majnemer updated this revision to Diff 37558.
majnemer marked 2 inline comments as done.
majnemer added a comment.

- Address Richard's review comments.


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/Builtins.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,12 @@
     AddTemplateArgument(SubstPack->getArgumentPack(), Record);
     break;
   }
+  case TemplateName::BuiltinTemplate: {
+    BuiltinTemplateStorage *BTS = Name.getAsBuiltinTemplate();
+    BuiltinTemplateNameKind BTNK = BTS->getKind();
+    Record.push_back(BTNK);
+    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) {
+  llvm_unreachable("BuiltinTemplates are not serialized");
+}
+
 /// 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,10 @@
     
     return Context.getSubstTemplateTemplateParmPack(Param, ArgPack);
   }
+  case TemplateName::BuiltinTemplate: {
+    BuiltinTemplateNameKind BTNK = (BuiltinTemplateNameKind)Record[Idx++];
+    return Context.getBuiltinTemplateName(BTNK);
+  }
   }
 
   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
@@ -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"
@@ -2032,7 +2033,18 @@
                                                           DTN->getIdentifier(),
                                                           TemplateArgs);
 
-  TemplateDecl *Template = Name.getAsTemplateDecl();
+  BuiltinTemplateStorage *BTS = Name.getAsBuiltinTemplate();
+  TemplateDecl *Template;
+  if (BTS) {
+    switch (BTS->getKind()) {
+    case BTNK__make_integer_seq:
+      Template = Context.getMakeIntegerSeqDecl();
+      break;
+    }
+  } else {
+    Template = Name.getAsTemplateDecl();
+  }
+
   if (!Template || isa<FunctionTemplateDecl>(Template) ||
       isa<VarTemplateDecl>(Template)) {
     // We might have a substituted template template parameter pack. If so,
@@ -2171,6 +2183,42 @@
     CanonType = Context.getTypeDeclType(Decl);
     assert(isa<RecordType>(CanonType) &&
            "type of non-dependent specialization is not a RecordType");
+  } else if (BTS) {
+    switch (BTS->getKind()) {
+    case BTNK__make_integer_seq:
+      // Instantiations involving __make_integer_seq<S, T, N> are treated like
+      // S<T, 0, ..., N-1>.
+      TemplateArgument NumArgsArg = Converted[2];
+      llvm::APSInt NumArgs = NumArgsArg.getAsIntegral();
+
+      // Diagnose attempts to create integer sequences with a negative length.
+      if (NumArgs < 0) {
+        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 =
+            BuildExpressionFromIntegralTemplateArgument(TA, SourceLocation())
+                .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.
+      CanonType = CheckTemplateIdType(Converted[0].getAsTemplate(), TemplateLoc,
+                                      SyntheticTemplateArgs);
+      break;
+    }
   }
 
   // Build the fully-sugared type for this class template
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -727,6 +727,11 @@
   return S.CreateParsedType(T, Builder.getTypeSourceInfo(Context, T));
 }
 
+void Sema::actOnBuiltinTemplateName(TemplateTy &TemplateResult,
+                                    BuiltinTemplateNameKind BTNK) {
+  TemplateResult = TemplateTy::make(Context.getBuiltinTemplateName(BTNK));
+}
+
 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, BTNK__make_integer_seq);
+
+      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
@@ -16,6 +16,7 @@
 #include "clang/AST/NestedNameSpecifier.h"
 #include "clang/AST/PrettyPrinter.h"
 #include "clang/AST/TemplateBase.h"
+#include "clang/Basic/Builtins.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/LangOptions.h"
 #include "llvm/Support/raw_ostream.h"
@@ -61,6 +62,8 @@
 
   UncommonTemplateNameStorage *uncommon
     = Storage.get<UncommonTemplateNameStorage*>();
+  if (uncommon->getAsBuiltinTemplate())
+    return BuiltinTemplate;
   if (uncommon->getAsOverloadedStorage())
     return OverloadedTemplate;
   if (uncommon->getAsSubstTemplateTemplateParm())
@@ -92,6 +95,12 @@
     return Template->getDeclContext() &&
            Template->getDeclContext()->isDependentContext();
   }
+  if (BuiltinTemplateStorage *BTS = getAsBuiltinTemplate()) {
+    switch (BTS->getKind()) {
+    case BTNK__make_integer_seq:
+      return false;
+    }
+  }
 
   assert(!getAsOverloadedTemplate() &&
          "overloaded templates shouldn't survive to here");
@@ -147,12 +156,17 @@
   } 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 (BuiltinTemplateStorage *BTS = getAsBuiltinTemplate()) {
+    switch (BTS->getKind()) {
+    case BTNK__make_integer_seq:
+      OS << "__make_integer_seq";
+      break;
+    }
   }
 }
 
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 builtin templates 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
@@ -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,65 @@
                                                          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);
+
+  // 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());
+}
+
+static TemplateParameterList *createBuiltinTemplateParameterList(
+    const ASTContext &C, BuiltinTemplateNameKind BTNK, DeclContext *DC) {
+  switch (BTNK) {
+  case BTNK__make_integer_seq:
+    return createMakeIntegerSeqParameterList(C, DC);
+  }
+
+  llvm_unreachable("unhandled BuiltinTemplateNameKind!");
+}
+
+void BuiltinTemplateDecl::anchor() {}
+
+BuiltinTemplateDecl::BuiltinTemplateDecl(const ASTContext &C,
+                                         BuiltinTemplateNameKind BTNK,
+                                         DeclContext *DC)
+    : TemplateDecl(BuiltinTemplate, DC, SourceLocation(), DeclarationName(),
+                   createBuiltinTemplateParameterList(C, BTNK, DC)),
+      BTNK(BTNK) {}
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,10 @@
     
     return ToContext.getSubstTemplateTemplateParmPack(Param, ArgPack);
   }
+  case TemplateName::BuiltinTemplate: {
+    return ToContext.getBuiltinTemplateName(
+        From.getAsBuiltinTemplate()->getKind());
+  }
   }
   
   llvm_unreachable("Invalid template name kind");
Index: lib/AST/ASTDumper.cpp
===================================================================
--- lib/AST/ASTDumper.cpp
+++ lib/AST/ASTDumper.cpp
@@ -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 @@
         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,16 @@
   VisitTemplateDecl(D, false);
 }
 
+void ASTDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
+  dumpName(D);
+  switch (D->getBuiltinTemplateNameKind()) {
+  case BTNK__make_integer_seq:
+    OS << " __make_integer_seq";
+    break;
+  }
+  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),
+      MakeIntegerSeqDecl(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,22 @@
   return ExternCContext;
 }
 
+BuiltinTemplateDecl *
+ASTContext::buildBuiltinTemplateDecl(BuiltinTemplateNameKind BTNK) const {
+  auto *BuiltinTemplate =
+      BuiltinTemplateDecl::Create(*this, BTNK, getTranslationUnitDecl());
+  BuiltinTemplate->setImplicit();
+
+  return BuiltinTemplate;
+}
+
+BuiltinTemplateDecl *
+ASTContext::getMakeIntegerSeqDecl() const {
+  if (!MakeIntegerSeqDecl)
+    MakeIntegerSeqDecl = buildBuiltinTemplateDecl(BTNK__make_integer_seq);
+  return MakeIntegerSeqDecl;
+}
+
 RecordDecl *ASTContext::buildImplicitRecord(StringRef Name,
                                             RecordDecl::TagKind TK) const {
   SourceLocation Loc;
@@ -4215,6 +4231,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 +4281,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 +6434,14 @@
   ObjCConstantStringType = getObjCInterfaceType(Decl);
 }
 
+/// \brief Retrieve the template name that corresponds to a __make_integer_seq.
+TemplateName
+ASTContext::getBuiltinTemplateName(BuiltinTemplateNameKind BTNK) const {
+  void *Memory = Allocate(sizeof(BuiltinTemplateStorage));
+  auto *BTS = new (Memory) BuiltinTemplateStorage(BTNK);
+  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,9 @@
                           QualType ObjectType, bool EnteringContext,
                           bool &MemberOfUnknownSpecialization);
 
+  void actOnBuiltinTemplateName(TemplateTy &TemplateResult,
+                                BuiltinTemplateNameKind BTNK);
+
   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/Basic/Builtins.h
===================================================================
--- include/clang/Basic/Builtins.h
+++ include/clang/Basic/Builtins.h
@@ -206,5 +206,12 @@
 };
 
 }
+
+/// \brief Kinds of BuiltinTemplate TemplateNames.
+enum BuiltinTemplateNameKind : int {
+  /// \brief This names the __make_integer_seq BuiltinTemplateDecl.
+  BTNK__make_integer_seq
+};
+
 } // end namespace clang
 #endif
Index: include/clang/AST/TemplateName.h
===================================================================
--- include/clang/AST/TemplateName.h
+++ include/clang/AST/TemplateName.h
@@ -21,6 +21,8 @@
 namespace clang {
   
 class ASTContext;
+class BuiltinTemplateStorage;
+enum BuiltinTemplateNameKind : int;
 class DependentTemplateName;
 class DiagnosticBuilder;
 class IdentifierInfo;
@@ -41,6 +43,7 @@
 class UncommonTemplateNameStorage {
 protected:
   enum Kind {
+    Builtin,
     Overloaded,
     SubstTemplateTemplateParm,
     SubstTemplateTemplateParmPack
@@ -67,7 +70,13 @@
   
 public:
   unsigned size() const { return Bits.Size; }
-  
+
+  BuiltinTemplateStorage *getAsBuiltinTemplate() {
+    return Bits.Kind == Builtin
+               ? reinterpret_cast<BuiltinTemplateStorage *>(this)
+               : nullptr;
+  }
+
   OverloadedTemplateStorage *getAsOverloadedStorage()  {
     return Bits.Kind == Overloaded
              ? reinterpret_cast<OverloadedTemplateStorage *>(this) 
@@ -86,7 +95,20 @@
              : nullptr;
   }
 };
-  
+
+/// \brief A structure for storing the information associated with an
+/// builtin template name.
+class BuiltinTemplateStorage : public UncommonTemplateNameStorage {
+  friend class ASTContext;
+  BuiltinTemplateNameKind BTNK;
+
+public:
+  BuiltinTemplateStorage(BuiltinTemplateNameKind BTNK)
+      : UncommonTemplateNameStorage(Builtin, 0), BTNK(BTNK) {}
+
+  BuiltinTemplateNameKind getKind() const { return BTNK; }
+};
+
 /// \brief A structure for storing the information associated with an
 /// overloaded template name.
 class OverloadedTemplateStorage : public UncommonTemplateNameStorage {
@@ -189,25 +211,28 @@
   enum NameKind {
     /// \brief A single template declaration.
     Template,
+    /// \brief A builtin, compiler defined template.
+    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);
@@ -285,6 +310,13 @@
     return Storage.dyn_cast<DependentTemplateName *>();
   }
 
+  /// \brief Retrieve the underlying builtin template name structure, if any.
+  BuiltinTemplateStorage *getAsBuiltinTemplate() const {
+    if (auto *Uncommon = Storage.dyn_cast<UncommonTemplateNameStorage *>())
+      return Uncommon->getAsBuiltinTemplate();
+    return nullptr;
+  }
+
   TemplateName getUnderlying() const;
 
   /// \brief Determines whether this is a dependent template name.
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
@@ -25,6 +25,7 @@
 
 namespace clang {
 
+enum BuiltinTemplateNameKind : int;
 class TemplateParameterList;
 class TemplateDecl;
 class RedeclarableTemplateDecl;
@@ -1490,6 +1491,34 @@
   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, BuiltinTemplateNameKind BTNK,
+                      DeclContext *DC);
+
+  BuiltinTemplateNameKind BTNK;
+
+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, BuiltinTemplateNameKind BTNK, DeclContext *DC) {
+    return new (C, DC) BuiltinTemplateDecl(C, BTNK, DC);
+  }
+
+  SourceRange getSourceRange() const override LLVM_READONLY {
+    return SourceRange();
+  }
+
+  BuiltinTemplateNameKind getBuiltinTemplateNameKind() const { return BTNK; }
+};
+
 /// \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
@@ -70,6 +70,7 @@
   class VTableContextBase;
 
   namespace Builtin { class Context; }
+  enum BuiltinTemplateNameKind : int;
 
   namespace comments {
     class FullComment;
@@ -399,6 +400,7 @@
   
   TranslationUnitDecl *TUDecl;
   mutable ExternCContextDecl *ExternCContext;
+  mutable BuiltinTemplateDecl *MakeIntegerSeqDecl;
 
   /// \brief The associated SourceManager object.a
   SourceManager &SourceMgr;
@@ -821,6 +823,7 @@
   TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; }
 
   ExternCContextDecl *getExternCContextDecl() const;
+  BuiltinTemplateDecl *getMakeIntegerSeqDecl() const;
 
   // Builtin Types.
   CanQualType VoidTy;
@@ -894,6 +897,9 @@
   void PrintStats() const;
   const SmallVectorImpl<Type *>& getTypes() const { return Types; }
 
+  BuiltinTemplateDecl *
+  buildBuiltinTemplateDecl(BuiltinTemplateNameKind BTNK) const;
+
   /// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl
   /// declaration.
   RecordDecl *buildImplicitRecord(StringRef Name,
@@ -1650,6 +1656,8 @@
   DeclarationNameInfo getNameForTemplate(TemplateName Name,
                                          SourceLocation NameLoc) const;
 
+  TemplateName getBuiltinTemplateName(BuiltinTemplateNameKind BTNK) 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