@@ -3501,45 +3501,70 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
3501
3501
SourceLocation TemplateLoc,
3502
3502
TemplateArgumentListInfo &TemplateArgs) {
3503
3503
ASTContext &Context = SemaRef.getASTContext();
3504
+
3505
+ TemplateParameterList *TPL = BTD->getTemplateParameters();
3506
+
3507
+ // Wrap the type in substitution sugar.
3508
+ auto getSubstType = [&](unsigned IndexReplaced, QualType Replacement) {
3509
+ QualType TTP = SemaRef.Context.getTemplateTypeParmType(
3510
+ 0, IndexReplaced, false,
3511
+ cast<TemplateTypeParmDecl>(TPL->getParam(IndexReplaced)));
3512
+ return SemaRef.Context.getSubstTemplateTypeParmType(
3513
+ cast<TemplateTypeParmType>(TTP), Replacement.getCanonicalType());
3514
+ };
3515
+
3504
3516
switch (BTD->getBuiltinTemplateKind()) {
3505
3517
case BTK__make_integer_seq: {
3506
3518
// Specializations of __make_integer_seq<S, T, N> are treated like
3507
3519
// S<T, 0, ..., N-1>.
3508
3520
3521
+ QualType OrigType = Converted[1].getAsType();
3509
3522
// C++14 [inteseq.intseq]p1:
3510
3523
// T shall be an integer type.
3511
- if (!Converted[1].getAsType() ->isIntegralType(Context)) {
3524
+ if (!OrigType->isDependentType() && !OrigType ->isIntegralType(Context)) {
3512
3525
SemaRef.Diag(TemplateArgs[1].getLocation(),
3513
3526
diag::err_integer_sequence_integral_element_type);
3514
3527
return QualType();
3515
3528
}
3516
3529
3517
- // C++14 [inteseq.make]p1:
3518
- // If N is negative the program is ill-formed.
3519
3530
TemplateArgument NumArgsArg = Converted[2];
3520
- llvm::APSInt NumArgs = NumArgsArg.getAsIntegral();
3521
- if (NumArgs < 0) {
3531
+ if (NumArgsArg.isDependent())
3532
+ return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
3533
+ Converted);
3534
+
3535
+ TemplateArgumentListInfo SyntheticTemplateArgs;
3536
+ // The type argument, wrapped in substitution sugar, gets reused as the
3537
+ // first template argument in the synthetic template argument list.
3538
+ QualType SyntheticType = getSubstType(1, OrigType);
3539
+ SyntheticTemplateArgs.addArgument(
3540
+ TemplateArgumentLoc(TemplateArgument(SyntheticType),
3541
+ SemaRef.Context.getTrivialTypeSourceInfo(
3542
+ SyntheticType, TemplateArgs[1].getLocation())));
3543
+
3544
+ if (llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); NumArgs >= 0) {
3545
+ // Expand N into 0 ... N-1.
3546
+ for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
3547
+ I < NumArgs; ++I) {
3548
+ TemplateArgument TA(Context, I, SyntheticType);
3549
+ SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc(
3550
+ TA, SyntheticType, TemplateArgs[2].getLocation()));
3551
+ }
3552
+ } else {
3553
+ // C++14 [inteseq.make]p1:
3554
+ // If N is negative the program is ill-formed.
3522
3555
SemaRef.Diag(TemplateArgs[2].getLocation(),
3523
3556
diag::err_integer_sequence_negative_length);
3524
3557
return QualType();
3525
3558
}
3526
3559
3527
- QualType ArgTy = NumArgsArg.getIntegralType();
3528
- TemplateArgumentListInfo SyntheticTemplateArgs;
3529
- // The type argument gets reused as the first template argument in the
3530
- // synthetic template argument list.
3531
- SyntheticTemplateArgs.addArgument(TemplateArgs[1]);
3532
- // Expand N into 0 ... N-1.
3533
- for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
3534
- I < NumArgs; ++I) {
3535
- TemplateArgument TA(Context, I, ArgTy);
3536
- SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc(
3537
- TA, ArgTy, TemplateArgs[2].getLocation()));
3538
- }
3560
+ // Wrap the template in substitution sugar.
3561
+ TemplateName TN = SemaRef.Context.getSubstTemplateTemplateParm(
3562
+ cast<TemplateTemplateParmDecl>(TPL->getParam(0)),
3563
+ Converted[0].getAsTemplate());
3564
+
3539
3565
// The first template argument will be reused as the template decl that
3540
3566
// our synthetic template arguments will be applied to.
3541
- return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(),
3542
- TemplateLoc, SyntheticTemplateArgs);
3567
+ return SemaRef.CheckTemplateIdType(TN, TemplateLoc, SyntheticTemplateArgs);
3543
3568
}
3544
3569
3545
3570
case BTK__type_pack_element:
@@ -3549,11 +3574,15 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
3549
3574
assert(Converted.size() == 2 &&
3550
3575
"__type_pack_element should be given an index and a parameter pack");
3551
3576
3552
- // If the Index is out of bounds, the program is ill-formed.
3553
3577
TemplateArgument IndexArg = Converted[0], Ts = Converted[1];
3578
+ if (IndexArg.isDependent() || Ts.isDependent())
3579
+ return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
3580
+ Converted);
3581
+
3554
3582
llvm::APSInt Index = IndexArg.getAsIntegral();
3555
3583
assert(Index >= 0 && "the index used with __type_pack_element should be of "
3556
3584
"type std::size_t, and hence be non-negative");
3585
+ // If the Index is out of bounds, the program is ill-formed.
3557
3586
if (Index >= Ts.pack_size()) {
3558
3587
SemaRef.Diag(TemplateArgs[0].getLocation(),
3559
3588
diag::err_type_pack_element_out_of_bounds);
@@ -3562,7 +3591,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
3562
3591
3563
3592
// We simply return the type at index `Index`.
3564
3593
auto Nth = std::next(Ts.pack_begin(), Index.getExtValue());
3565
- return Nth->getAsType();
3594
+ return getSubstType(1, Nth->getAsType() );
3566
3595
}
3567
3596
llvm_unreachable("unexpected BuiltinTemplateDecl!");
3568
3597
}
@@ -3730,7 +3759,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
3730
3759
// We might have a substituted template template parameter pack. If so,
3731
3760
// build a template specialization type for it.
3732
3761
if (Name.getAsSubstTemplateTemplateParmPack())
3733
- return Context.getTemplateSpecializationType(Name, TemplateArgs);
3762
+ return Context.getTemplateSpecializationType(Name,
3763
+ TemplateArgs.arguments());
3734
3764
3735
3765
Diag(TemplateLoc, diag::err_template_id_not_a_type)
3736
3766
<< Name;
@@ -3808,6 +3838,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
3808
3838
3809
3839
return QualType();
3810
3840
}
3841
+ } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
3842
+ CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc,
3843
+ TemplateArgs);
3811
3844
} else if (Name.isDependent() ||
3812
3845
TemplateSpecializationType::anyDependentTemplateArguments(
3813
3846
TemplateArgs, Converted)) {
@@ -3857,8 +3890,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
3857
3890
break;
3858
3891
}
3859
3892
}
3860
- } else if (ClassTemplateDecl *ClassTemplate
3861
- = dyn_cast<ClassTemplateDecl>(Template)) {
3893
+ } else if (ClassTemplateDecl *ClassTemplate =
3894
+ dyn_cast<ClassTemplateDecl>(Template)) {
3862
3895
// Find the class template specialization declaration that
3863
3896
// corresponds to these arguments.
3864
3897
void *InsertPos = nullptr;
@@ -3895,15 +3928,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
3895
3928
CanonType = Context.getTypeDeclType(Decl);
3896
3929
assert(isa<RecordType>(CanonType) &&
3897
3930
"type of non-dependent specialization is not a RecordType");
3898
- } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
3899
- CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc,
3900
- TemplateArgs);
3931
+ } else {
3932
+ llvm_unreachable("Unhandled template kind");
3901
3933
}
3902
3934
3903
3935
// Build the fully-sugared type for this class template
3904
3936
// specialization, which refers back to the class template
3905
3937
// specialization we created or found.
3906
- return Context.getTemplateSpecializationType(Name, TemplateArgs, CanonType);
3938
+ return Context.getTemplateSpecializationType(Name, TemplateArgs.arguments(),
3939
+ CanonType);
3907
3940
}
3908
3941
3909
3942
void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName,
0 commit comments