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

Code before:
      const TemplateArgumentList &ConstantArgs = SpecDecl->getTemplateArgs();

      QualType ConstantType = ConstantArgs[0].getAsType();
      llvm::APInt Value = ConstantArgs[1].getAsIntegral();

      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 (llvm::any_of(Converted,
                   [](const TemplateArgument &A) { return A.isDependent(); }))
    return QualType();

  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>.

    QualType OrigType = Converted[1].getAsType();
    // C++14 [inteseq.intseq]p1:
    //   T shall be an integer type.
    if (!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(

Review comment (bug):
Oh huh, I wouldn't have thought of doing it this way. Good call.

Are we able to check that the minimum arg count is reached? e.g 
```cpp
__some_builtin_template<{some template parameter set}>(...)
```
is always invalid if there are insufficient template parameters (assuming no packs), e.g we can error out on incorrect/insufficient template parameters even if they are dependent


Code after:
      const TemplateArgumentList &ConstantArgs = SpecDecl->getTemplateArgs();

      QualType ConstantType = ConstantArgs[0].getAsType();
      llvm::APInt Value = ConstantArgs[1].getAsIntegral();

      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),