Repository: llvm/llvm-project
File: clang/lib/Sema/SemaTemplate.cpp (C++)

Code before:
      if (Literal)
        return SpirvOperand::createLiteral(Value);
      return SpirvOperand::createConstant(ConstantType, Value);
    } else if (Literal) {
      SemaRef.Diag(LiteralLoc, diag::err_hlsl_vk_literal_must_contain_constant);
      return SpirvOperand();
    }
  }
  if (SemaRef.RequireCompleteType(Loc, OperandArg,
                                  diag::err_call_incomplete_argument))
    return SpirvOperand();
  return SpirvOperand::createType(OperandArg);
}

static QualType checkBuiltinTemplateIdType(
    Sema &SemaRef, ElaboratedTypeKeyword Keyword, BuiltinTemplateDecl *BTD,
    ArrayRef<TemplateArgument> Converted, SourceLocation TemplateLoc,
    TemplateArgumentListInfo &TemplateArgs) {
  if (Converted.size() < BTD->getTemplateParameters()->size())
    return QualType();

  ASTContext &Context = SemaRef.getASTContext();

  switch (BTD->getBuiltinTemplateKind()) {
  case BTK__make_integer_seq: {
    assert(Converted.size() == 3);
    if (Converted[2].isDependent())
      return QualType();
    // Specializations of __make_integer_seq<S, T, N> are treated like
    // S<T, 0, ..., N-1>.

    QualType OrigType = Converted[1].getAsType();
    // C++14 [inteseq.intseq]p1:
    //   T shall be an integer type.
    if (!OrigType->isDependentType() && !OrigType->isIntegralType(Context)) {
      SemaRef.Diag(TemplateArgs[1].getLocation(),
                   diag::err_integer_sequence_integral_element_type);
      return QualType();
    }

    TemplateArgument NumArgsArg = Converted[2];

    TemplateArgumentListInfo SyntheticTemplateArgs;
    // The type argument, wrapped in substitution sugar, gets reused as the
    // first template argument in the synthetic template argument list.
    SyntheticTemplateArgs.addArgument(
        TemplateArgumentLoc(TemplateArgument(OrigType),
                            SemaRef.Context.getTrivialTypeSourceInfo(
                                OrigType, TemplateArgs[1].getLocation())));

    if (llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); NumArgs >= 0) {

Review comment (suggestion):
I think this assertion will fire if you do `__make_integer_seq<a,b,c,d,e>` or similar. It's possible the above size check should be `Converted.size() == BTD->getTemplateParameters()->size()` unless the last parameter is variadic, in which case it should permit more parameters.

Code after:
      if (Literal)
        return SpirvOperand::createLiteral(Value);
      return SpirvOperand::createConstant(ConstantType, Value);
    } else if (Literal) {
      SemaRef.Diag(LiteralLoc, diag::err_hlsl_vk_literal_must_contain_constant);
      return SpirvOperand();
    }
  }
  if (SemaRef.RequireCompleteType(Loc, OperandArg,
                                  diag::err_call_incomplete_argument))
    return SpirvOperand();
  return SpirvOperand::createType(OperandArg);
}

static QualType checkBuiltinTemplateIdType(
    Sema &SemaRef, ElaboratedTypeKeyword Keyword, BuiltinTemplateDecl *BTD,
    ArrayRef<TemplateArgument> Converted, SourceLocation TemplateLoc,
    TemplateArgumentListInfo &TemplateArgs) {
  ASTContext &Context = SemaRef.getASTContext();

  assert(Converted.size() == BTD->getTemplateParameters()->size() &&
         "Builtin template arguments do not match its parameters");

  switch (BTD->getBuiltinTemplateKind()) {
  case BTK__make_integer_seq: {
    // Specializations of __make_integer_seq<S, T, N> are treated like
    // S<T, 0, ..., N-1>.

    QualType OrigType = Converted[1].getAsType();
    // C++14 [inteseq.intseq]p1:
    //   T shall be an integer type.
    if (!OrigType->isDependentType() && !OrigType->isIntegralType(Context)) {
      SemaRef.Diag(TemplateArgs[1].getLocation(),
                   diag::err_integer_sequence_integral_element_type);
      return QualType();
    }

    TemplateArgument NumArgsArg = Converted[2];
    if (NumArgsArg.isDependent())
      return QualType();

    TemplateArgumentListInfo SyntheticTemplateArgs;
    // The type argument, wrapped in substitution sugar, gets reused as the
    // first template argument in the synthetic template argument list.
    SyntheticTemplateArgs.addArgument(
        TemplateArgumentLoc(TemplateArgument(OrigType),
                            SemaRef.Context.getTrivialTypeSourceInfo(
                                OrigType, TemplateArgs[1].getLocation())));

    if (llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); NumArgs >= 0) {
      // Expand N into 0 ... N-1.