[clang] f4ea3bd - [clang] Fixes how we represent / emulate builtin templates
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 16 08:45:45 PDT 2022
Author: Matheus Izvekov
Date: 2022-09-16T17:44:12+02:00
New Revision: f4ea3bd4b2086e6de10131b197aaf7d066a24df8
URL: https://github.com/llvm/llvm-project/commit/f4ea3bd4b2086e6de10131b197aaf7d066a24df8
DIFF: https://github.com/llvm/llvm-project/commit/f4ea3bd4b2086e6de10131b197aaf7d066a24df8.diff
LOG: [clang] Fixes how we represent / emulate builtin templates
We change the template specialization of builtin templates to
behave like aliases.
Though unlike real alias templates, these might still produce a canonical
TemplateSpecializationType when some important argument is dependent.
For example, we can't do anything about make_integer_seq when the
count is dependent, or a type_pack_element when the index is dependent.
We change type deduction to not try to deduce canonical TSTs of
builtin templates.
We also change those buitin templates to produce substitution sugar,
just like a real instantiation would, making the resulting type correctly
represent the template arguments used to specialize the underlying template.
And make_integer_seq will now produce a TST for the specialization
of it's first argument, which we use as the underlying type of
the builtin alias.
When performing member access on the resulting type, it's now
possible to map from a Subst* node to the template argument
as-written used in a regular fashion, without special casing.
And this fixes a bunch of bugs with relation to these builtin
templates factoring into deduction.
Fixes GH42102 and GH51928.
Depends on D133261
Signed-off-by: Matheus Izvekov <mizvekov at gmail.com>
Differential Revision: https://reviews.llvm.org/D133262
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/DeclTemplate.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/DeclTemplate.cpp
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/test/SemaTemplate/make_integer_seq.cpp
clang/test/SemaTemplate/type_pack_element.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e4648cd3b2879..1ec21a7b3acec 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -122,6 +122,9 @@ Bug Fixes
- Clang will now no longer treat a C 'overloadable' function without a prototype as
a variadic function with the attribute. This should make further diagnostics more
clear.
+- Fixes to builtin template emulation of regular templates.
+ `Issue 42102 <https://github.com/llvm/llvm-project/issues/42102>`_
+ `Issue 51928 <https://github.com/llvm/llvm-project/issues/51928>`_
Improvements to Clang's diagnostics
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index c0228465322ee..14661ecc0c09c 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1636,7 +1636,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
ArrayRef<TemplateArgument> Args) const;
QualType getTemplateSpecializationType(TemplateName T,
- const TemplateArgumentListInfo &Args,
+ ArrayRef<TemplateArgumentLoc> Args,
QualType Canon = QualType()) const;
TypeSourceInfo *
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index baed5ca22fa75..dbea107f368fb 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -440,6 +440,9 @@ class TemplateDecl : public NamedDecl {
/// Get the underlying, templated declaration.
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
+ // Should a specialization behave like an alias for another type.
+ bool isTypeAlias() const;
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index c326435ba5f5f..5bf03d8f3c3aa 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -4848,7 +4848,8 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
QualType Underlying) const {
assert(!Name.getAsDependentTemplateName() &&
"No dependent template names here!");
- QualType TST = getTemplateSpecializationType(Name, Args, Underlying);
+ QualType TST =
+ getTemplateSpecializationType(Name, Args.arguments(), Underlying);
TypeSourceInfo *DI = CreateTypeSourceInfo(TST);
TemplateSpecializationTypeLoc TL =
@@ -4864,14 +4865,14 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name,
QualType
ASTContext::getTemplateSpecializationType(TemplateName Template,
- const TemplateArgumentListInfo &Args,
+ ArrayRef<TemplateArgumentLoc> Args,
QualType Underlying) const {
assert(!Template.getAsDependentTemplateName() &&
"No dependent template names here!");
SmallVector<TemplateArgument, 4> ArgVec;
ArgVec.reserve(Args.size());
- for (const TemplateArgumentLoc &Arg : Args.arguments())
+ for (const TemplateArgumentLoc &Arg : Args)
ArgVec.push_back(Arg.getArgument());
return getTemplateSpecializationType(Template, ArgVec, Underlying);
@@ -4897,8 +4898,8 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
Template = QTN->getUnderlyingTemplate();
- bool IsTypeAlias =
- isa_and_nonnull<TypeAliasTemplateDecl>(Template.getAsTemplateDecl());
+ const auto *TD = Template.getAsTemplateDecl();
+ bool IsTypeAlias = TD && TD->isTypeAlias();
QualType CanonType;
if (!Underlying.isNull())
CanonType = getCanonicalType(Underlying);
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index e3dd7804c99ba..6bb5a493485ef 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -250,6 +250,16 @@ bool TemplateDecl::hasAssociatedConstraints() const {
return false;
}
+bool TemplateDecl::isTypeAlias() const {
+ switch (getKind()) {
+ case TemplateDecl::TypeAliasTemplate:
+ case TemplateDecl::BuiltinTemplate:
+ return true;
+ default:
+ return false;
+ };
+}
+
//===----------------------------------------------------------------------===//
// RedeclarableTemplateDecl Implementation
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 49dcf7781d03a..73cb80816fae7 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -1263,10 +1263,11 @@ llvm::DIType *CGDebugInfo::CreateType(const TemplateSpecializationType *Ty,
assert(Ty->isTypeAlias());
llvm::DIType *Src = getOrCreateType(Ty->getAliasedType(), Unit);
- auto *AliasDecl =
- cast<TypeAliasTemplateDecl>(Ty->getTemplateName().getAsTemplateDecl())
- ->getTemplatedDecl();
+ const TemplateDecl *TD = Ty->getTemplateName().getAsTemplateDecl();
+ if (isa<BuiltinTemplateDecl>(TD))
+ return Src;
+ const auto *AliasDecl = cast<TypeAliasTemplateDecl>(TD)->getTemplatedDecl();
if (AliasDecl->hasAttr<NoDebugAttr>())
return Src;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index ed507fd329a57..b8cf69f7764ff 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3501,45 +3501,70 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
SourceLocation TemplateLoc,
TemplateArgumentListInfo &TemplateArgs) {
ASTContext &Context = SemaRef.getASTContext();
+
+ TemplateParameterList *TPL = BTD->getTemplateParameters();
+
+ // Wrap the type in substitution sugar.
+ auto getSubstType = [&](unsigned IndexReplaced, QualType Replacement) {
+ QualType TTP = SemaRef.Context.getTemplateTypeParmType(
+ 0, IndexReplaced, false,
+ cast<TemplateTypeParmDecl>(TPL->getParam(IndexReplaced)));
+ return SemaRef.Context.getSubstTemplateTypeParmType(
+ cast<TemplateTypeParmType>(TTP), Replacement.getCanonicalType());
+ };
+
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 (!Converted[1].getAsType()->isIntegralType(Context)) {
+ if (!OrigType->isDependentType() && !OrigType->isIntegralType(Context)) {
SemaRef.Diag(TemplateArgs[1].getLocation(),
diag::err_integer_sequence_integral_element_type);
return QualType();
}
- // C++14 [inteseq.make]p1:
- // If N is negative the program is ill-formed.
TemplateArgument NumArgsArg = Converted[2];
- llvm::APSInt NumArgs = NumArgsArg.getAsIntegral();
- if (NumArgs < 0) {
+ if (NumArgsArg.isDependent())
+ return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
+ Converted);
+
+ TemplateArgumentListInfo SyntheticTemplateArgs;
+ // The type argument, wrapped in substitution sugar, gets reused as the
+ // first template argument in the synthetic template argument list.
+ QualType SyntheticType = getSubstType(1, OrigType);
+ SyntheticTemplateArgs.addArgument(
+ TemplateArgumentLoc(TemplateArgument(SyntheticType),
+ SemaRef.Context.getTrivialTypeSourceInfo(
+ SyntheticType, TemplateArgs[1].getLocation())));
+
+ if (llvm::APSInt NumArgs = NumArgsArg.getAsIntegral(); NumArgs >= 0) {
+ // Expand N into 0 ... N-1.
+ for (llvm::APSInt I(NumArgs.getBitWidth(), NumArgs.isUnsigned());
+ I < NumArgs; ++I) {
+ TemplateArgument TA(Context, I, SyntheticType);
+ SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc(
+ TA, SyntheticType, TemplateArgs[2].getLocation()));
+ }
+ } else {
+ // C++14 [inteseq.make]p1:
+ // If N is negative the program is ill-formed.
SemaRef.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);
- SyntheticTemplateArgs.addArgument(SemaRef.getTrivialTemplateArgumentLoc(
- TA, ArgTy, TemplateArgs[2].getLocation()));
- }
+ // Wrap the template in substitution sugar.
+ TemplateName TN = SemaRef.Context.getSubstTemplateTemplateParm(
+ cast<TemplateTemplateParmDecl>(TPL->getParam(0)),
+ Converted[0].getAsTemplate());
+
// The first template argument will be reused as the template decl that
// our synthetic template arguments will be applied to.
- return SemaRef.CheckTemplateIdType(Converted[0].getAsTemplate(),
- TemplateLoc, SyntheticTemplateArgs);
+ return SemaRef.CheckTemplateIdType(TN, TemplateLoc, SyntheticTemplateArgs);
}
case BTK__type_pack_element:
@@ -3549,11 +3574,15 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
assert(Converted.size() == 2 &&
"__type_pack_element should be given an index and a parameter pack");
- // If the Index is out of bounds, the program is ill-formed.
TemplateArgument IndexArg = Converted[0], Ts = Converted[1];
+ if (IndexArg.isDependent() || Ts.isDependent())
+ return Context.getCanonicalTemplateSpecializationType(TemplateName(BTD),
+ Converted);
+
llvm::APSInt Index = IndexArg.getAsIntegral();
assert(Index >= 0 && "the index used with __type_pack_element should be of "
"type std::size_t, and hence be non-negative");
+ // If the Index is out of bounds, the program is ill-formed.
if (Index >= Ts.pack_size()) {
SemaRef.Diag(TemplateArgs[0].getLocation(),
diag::err_type_pack_element_out_of_bounds);
@@ -3562,7 +3591,7 @@ checkBuiltinTemplateIdType(Sema &SemaRef, BuiltinTemplateDecl *BTD,
// We simply return the type at index `Index`.
auto Nth = std::next(Ts.pack_begin(), Index.getExtValue());
- return Nth->getAsType();
+ return getSubstType(1, Nth->getAsType());
}
llvm_unreachable("unexpected BuiltinTemplateDecl!");
}
@@ -3730,7 +3759,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// 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,
+ TemplateArgs.arguments());
Diag(TemplateLoc, diag::err_template_id_not_a_type)
<< Name;
@@ -3808,6 +3838,9 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
return QualType();
}
+ } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
+ CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc,
+ TemplateArgs);
} else if (Name.isDependent() ||
TemplateSpecializationType::anyDependentTemplateArguments(
TemplateArgs, Converted)) {
@@ -3857,8 +3890,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
break;
}
}
- } else if (ClassTemplateDecl *ClassTemplate
- = dyn_cast<ClassTemplateDecl>(Template)) {
+ } else if (ClassTemplateDecl *ClassTemplate =
+ dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
void *InsertPos = nullptr;
@@ -3895,15 +3928,15 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
CanonType = Context.getTypeDeclType(Decl);
assert(isa<RecordType>(CanonType) &&
"type of non-dependent specialization is not a RecordType");
- } else if (auto *BTD = dyn_cast<BuiltinTemplateDecl>(Template)) {
- CanonType = checkBuiltinTemplateIdType(*this, BTD, Converted, TemplateLoc,
- TemplateArgs);
+ } else {
+ llvm_unreachable("Unhandled template kind");
}
// 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(Name, TemplateArgs.arguments(),
+ CanonType);
}
void Sema::ActOnUndeclaredTypeTemplateName(Scope *S, TemplateTy &ParsedName,
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 82f6d9458dada..5e0f5f22a13b9 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -563,6 +563,12 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
// FIXME: Try to preserve type sugar here, which is hard
// because of the unresolved template arguments.
const auto *TP = UP.getCanonicalType()->castAs<TemplateSpecializationType>();
+ TemplateName TNP = TP->getTemplateName();
+
+ // If the parameter is an alias template, there is nothing to deduce.
+ if (const auto *TD = TNP.getAsTemplateDecl(); TD && TD->isTypeAlias())
+ return Sema::TDK_Success;
+
ArrayRef<TemplateArgument> PResolved = TP->template_arguments();
QualType UA = A;
@@ -574,10 +580,15 @@ DeduceTemplateSpecArguments(Sema &S, TemplateParameterList *TemplateParams,
// FIXME: Should not lose sugar here.
if (const auto *SA =
dyn_cast<TemplateSpecializationType>(UA.getCanonicalType())) {
+ TemplateName TNA = SA->getTemplateName();
+
+ // If the argument is an alias template, there is nothing to deduce.
+ if (const auto *TD = TNA.getAsTemplateDecl(); TD && TD->isTypeAlias())
+ return Sema::TDK_Success;
+
// Perform template argument deduction for the template name.
if (auto Result =
- DeduceTemplateArguments(S, TemplateParams, TP->getTemplateName(),
- SA->getTemplateName(), Info, Deduced))
+ DeduceTemplateArguments(S, TemplateParams, TNP, TNA, Info, Deduced))
return Result;
// Perform template argument deduction on each template
// argument. Ignore any missing/extra arguments, since they could be
diff --git a/clang/test/SemaTemplate/make_integer_seq.cpp b/clang/test/SemaTemplate/make_integer_seq.cpp
index 78d66c702c038..dfdb65c196604 100644
--- a/clang/test/SemaTemplate/make_integer_seq.cpp
+++ b/clang/test/SemaTemplate/make_integer_seq.cpp
@@ -4,21 +4,31 @@ template <class A1, A1... A2> struct A {};
using test1 = __make_integer_seq<A, int, 1>;
// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:5:1, col:43> col:7 test1 '__make_integer_seq<A, int, 1>':'A<int, 0>'
-// CHECK-NEXT: | `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar
-// CHECK-NEXT: | `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar __make_integer_seq
-// CHECK-NEXT: | |-TemplateArgument template A
-// CHECK-NEXT: | |-TemplateArgument type 'int'
-// CHECK-NEXT: | | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
-// CHECK-NEXT: | |-TemplateArgument expr
-// CHECK-NEXT: | | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int'
-// CHECK-NEXT: | | |-value: Int 1
-// CHECK-NEXT: | | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
-// CHECK-NEXT: | `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>'
-// CHECK-NEXT: | `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A'
+// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar alias __make_integer_seq
+// CHECK-NEXT: |-TemplateArgument template A
+// CHECK-NEXT: |-TemplateArgument type 'int'
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: |-TemplateArgument expr
+// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int'
+// CHECK-NEXT: | |-value: Int 1
+// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A
+// CHECK-NEXT: |-TemplateArgument type 'int':'int'
+// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar
+// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1
+// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: |-TemplateArgument expr
+// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int'
+// CHECK-NEXT: | |-value: Int 0
+// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int':'int' 0
+// CHECK-NEXT: `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>'
+// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A'
template <class B1, B1 B2> using B = __make_integer_seq<A, B1, B2>;
using test2 = B<int, 1>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:20:1, col:23> col:7 test2 'B<int, 1>':'A<int, 0>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:30:1, col:23> col:7 test2 'B<int, 1>':'A<int, 0>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar
// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'B<int, 1>' sugar alias B
// CHECK-NEXT: |-TemplateArgument type 'int'
@@ -28,7 +38,7 @@ using test2 = B<int, 1>;
// CHECK-NEXT: | |-value: Int 1
// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:22> 'int' 1
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar __make_integer_seq
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, 1>' sugar alias __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template A
// CHECK-NEXT: |-TemplateArgument type 'int':'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar
@@ -36,61 +46,93 @@ using test2 = B<int, 1>;
// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'B1'
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
// CHECK-NEXT: |-TemplateArgument expr
-// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:19:64> 'int'
+// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <line:29:64> 'int'
// CHECK-NEXT: | |-value: Int 1
// CHECK-NEXT: | `-SubstNonTypeTemplateParmExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int'
// CHECK-NEXT: | |-NonTypeTemplateParmDecl 0x{{[0-9A-Fa-f]+}} <col:21, col:24> col:24 referenced 'B1' depth 0 index 1 B2
// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:64> 'int' 1
-// CHECK-NEXT: `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>'
-// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>' sugar A
+// CHECK-NEXT: |-TemplateArgument type 'int':'int'
+// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar
+// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1
+// CHECK-NEXT: | | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: |-TemplateArgument expr
+// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:64> 'int'
+// CHECK-NEXT: | |-value: Int 0
+// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:64> 'int':'int' 0
+// CHECK-NEXT: `-RecordType 0x{{[0-9A-Fa-f]+}} 'A<int, 0>'
+// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[0-9A-Fa-f]+}} 'A'
template <template <class T, T...> class S, class T, int N> struct C {
using test3 = __make_integer_seq<S, T, N>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:48:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<S, T, N>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:68:3, col:43> col:9 test3 '__make_integer_seq<S, T, N>':'__make_integer_seq<type-parameter-0-1, N>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' dependent __make_integer_seq
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<S, T, N>' sugar dependent alias __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template S
// CHECK-NEXT: |-TemplateArgument type 'T'
// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'T' dependent depth 0 index 1
// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'T'
-// CHECK-NEXT: `-TemplateArgument expr
-// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent>
-// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: |-TemplateArgument expr
+// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent>
+// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<type-parameter-0-1, N>' dependent __make_integer_seq
+// CHECK-NEXT: |-TemplateArgument template
+// CHECK-NEXT: |-TemplateArgument type 'type-parameter-0-1'
+// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent depth 0 index 1
+// CHECK-NEXT: `-TemplateArgument expr
+// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent>
+// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
using test4 = __make_integer_seq<A, T, 1>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:60:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, T, 1>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:87:3, col:43> col:9 test4 '__make_integer_seq<A, T, 1>':'__make_integer_seq<A, type-parameter-0-1, 1>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' dependent __make_integer_seq
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, T, 1>' sugar dependent alias __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template A
// CHECK-NEXT: |-TemplateArgument type 'T'
// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'T' dependent depth 0 index 1
// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'T'
-// CHECK-NEXT: `-TemplateArgument expr
-// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent>
-// CHECK-NEXT: `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
+// CHECK-NEXT: |-TemplateArgument expr
+// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent>
+// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, type-parameter-0-1, 1>' dependent __make_integer_seq
+// CHECK-NEXT: |-TemplateArgument template A
+// CHECK-NEXT: |-TemplateArgument type 'type-parameter-0-1'
+// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent depth 0 index 1
+// CHECK-NEXT: `-TemplateArgument expr
+// CHECK-NEXT: `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:42> 'type-parameter-0-1':'type-parameter-0-1' <Dependent>
+// CHECK-NEXT: `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:42> 'int' 1
using test5 = __make_integer_seq<A, int, N>;
-// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:72:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>':'__make_integer_seq<A, int, N>'
+// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:106:3, col:45> col:9 test5 '__make_integer_seq<A, int, N>':'__make_integer_seq<A, int, N>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' dependent __make_integer_seq
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' sugar dependent alias __make_integer_seq
// CHECK-NEXT: |-TemplateArgument template A
// CHECK-NEXT: |-TemplateArgument type 'int'
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
-// CHECK-NEXT: `-TemplateArgument expr
-// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: |-TemplateArgument expr
+// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__make_integer_seq<A, int, N>' dependent __make_integer_seq
+// CHECK-NEXT: |-TemplateArgument template A
+// CHECK-NEXT: |-TemplateArgument type 'int'
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: `-TemplateArgument expr
+// CHECK-NEXT: `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:44> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
};
-template <class T, class S> struct D; // expected-note {{template is declared here}}
+// expected-no-diagnostics
+
+template <class T, class S> struct D;
template <class T> struct D<T, __make_integer_seq<A, int, sizeof(T)>> {};
-template struct D<char, A<int, 0>>; // expected-error {{explicit instantiation of undefined template}}
+template struct D<char, A<int, 0>>;
-template <class T, class S> struct E; // expected-note {{template is declared here}}
+template <class T, class S> struct E;
template <class T> struct E<T, __make_integer_seq<A, T, 2>> {};
-template struct E<short, A<short, 0, 1>>; // expected-error {{explicit instantiation of undefined template}}
+template struct E<short, A<short, 0, 1>>;
-template <template <class A1, A1... A2> class T, class S> struct F; // expected-note {{template is declared here}}
+template <template <class A1, A1... A2> class T, class S> struct F;
template <template <class A1, A1... A2> class T> struct F<T, __make_integer_seq<T, long, 3>> {};
-template struct F<A, A<long, 0, 1, 2>>; // expected-error {{explicit instantiation of undefined template}}
+template struct F<A, A<long, 0, 1, 2>>;
template <class T> struct G;
template <class T> struct G<__make_integer_seq<A, T, 1>> {};
@@ -99,5 +141,5 @@ template <class T> struct G<__make_integer_seq<A, T, 1U>> {};
template <int S, class = __make_integer_seq<A, int, S>> struct H;
template <int S, int... Is> struct H<S, A<int, Is...>> { };
-template <int S> void h(H<S>); // expected-note {{could not match '__make_integer_seq' against 'A'}}
-void test_h() { h(H<5>{}); } // expected-error {{no matching function for call to 'h'}}
+template <int S> void h(H<S>);
+void test_h() { h(H<5>{}); }
diff --git a/clang/test/SemaTemplate/type_pack_element.cpp b/clang/test/SemaTemplate/type_pack_element.cpp
index 443b72bc2e557..028bf177f4084 100644
--- a/clang/test/SemaTemplate/type_pack_element.cpp
+++ b/clang/test/SemaTemplate/type_pack_element.cpp
@@ -3,7 +3,7 @@
using test1 = __type_pack_element<0, int>;
// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <<stdin>:3:1, col:41> col:7 test1 '__type_pack_element<0, int>':'int'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, int>' sugar
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, int>' sugar __type_pack_element
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, int>' sugar alias __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:35> 'unsigned long'
// CHECK-NEXT: | |-value: Int 0
@@ -11,53 +11,79 @@ using test1 = __type_pack_element<0, int>;
// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:35> 'int' 0
// CHECK-NEXT: |-TemplateArgument type 'int'
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
-// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: `-SubstTemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'int' sugar
+// CHECK-NEXT: |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'auto' dependent depth 0 index 1
+// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} ''
+// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
template<int N, class ...Ts> struct A {
using test2 = __type_pack_element<N, Ts...>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:17:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, Ts...>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:20:3, col:45> col:9 test2 '__type_pack_element<N, Ts...>':'__type_pack_element<N, type-parameter-0-1...>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' dependent __type_pack_element
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, Ts...>' sugar dependent alias __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr
// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT: `-TemplateArgument type 'Ts...'
-// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
-// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
-// CHECK-NEXT: `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
+// CHECK-NEXT: |-TemplateArgument type 'Ts...'
+// CHECK-NEXT: | `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
+// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, type-parameter-0-1...>' dependent __type_pack_element
+// CHECK-NEXT: |-TemplateArgument expr
+// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
+// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: `-TemplateArgument pack
+// CHECK-NEXT: `-TemplateArgument type 'type-parameter-0-1...'
+// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1...' dependent
+// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
using test3 = __type_pack_element<0, Ts...>;
-// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:29:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, Ts...>'
+// CHECK: |-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:40:3, col:45> col:9 test3 '__type_pack_element<0, Ts...>':'__type_pack_element<0, type-parameter-0-1...>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' dependent __type_pack_element
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, Ts...>' sugar dependent alias __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long'
// CHECK-NEXT: | |-value: Int 0
// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
// CHECK-NEXT: | `-IntegerLiteral 0x{{[0-9A-Fa-f]+}} <col:37> 'int' 0
-// CHECK-NEXT: `-TemplateArgument type 'Ts...'
-// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
-// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
-// CHECK-NEXT: `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
+// CHECK-NEXT: |-TemplateArgument type 'Ts...'
+// CHECK-NEXT: | `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'Ts...' dependent
+// CHECK-NEXT: | `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'Ts' dependent contains_unexpanded_pack depth 0 index 1 pack
+// CHECK-NEXT: | `-TemplateTypeParm 0x{{[0-9A-Fa-f]+}} 'Ts'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<0, type-parameter-0-1...>' dependent __type_pack_element
+// CHECK-NEXT: |-TemplateArgument integral 0
+// CHECK-NEXT: `-TemplateArgument pack
+// CHECK-NEXT: `-TemplateArgument type 'type-parameter-0-1...'
+// CHECK-NEXT: `-PackExpansionType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1...' dependent
+// CHECK-NEXT: `-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'type-parameter-0-1' dependent contains_unexpanded_pack depth 0 index 1 pack
using test4 = __type_pack_element<N, int>;
-// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:43:3, col:43> col:9 test4 '__type_pack_element<N, int>':'__type_pack_element<N, int>'
+// CHECK: `-TypeAliasDecl 0x{{[0-9A-Fa-f]+}} <line:60:3, col:43> col:9 test4 '__type_pack_element<N, int>':'__type_pack_element<N, int>'
// CHECK-NEXT: `-ElaboratedType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent
-// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' dependent __type_pack_element
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' sugar dependent alias __type_pack_element
// CHECK-NEXT: |-TemplateArgument expr
// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
-// CHECK-NEXT: `-TemplateArgument type 'int'
-// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: |-TemplateArgument type 'int'
+// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
+// CHECK-NEXT: `-TemplateSpecializationType 0x{{[0-9A-Fa-f]+}} '__type_pack_element<N, int>' dependent __type_pack_element
+// CHECK-NEXT: |-TemplateArgument expr
+// CHECK-NEXT: | `-ImplicitCastExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'unsigned long' <IntegralCast>
+// CHECK-NEXT: | `-DeclRefExpr 0x{{[0-9A-Fa-f]+}} <col:37> 'int' NonTypeTemplateParm 0x{{[0-9A-Fa-f]+}} 'N' 'int'
+// CHECK-NEXT: `-TemplateArgument pack
+// CHECK-NEXT: `-TemplateArgument type 'int'
+// CHECK-NEXT: `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
};
-template <class T, class S> struct B; // expected-note {{template is declared here}}
+// expected-no-diagnostics
+
+template <class T, class S> struct B;
template <class T> struct B<T, __type_pack_element<sizeof(T), void, long>> {};
-template struct B<char, long>; // expected-error {{explicit instantiation of undefined template}}
+template struct B<char, long>;
-template <class T, class S> struct C; // expected-note {{template is declared here}}
+template <class T, class S> struct C;
template <class T> struct C<T, __type_pack_element<0, T, short>> {};
-template struct C<int, int>; // expected-error {{explicit instantiation of undefined template}}
+template struct C<int, int>;
template <class T> struct D;
template <class T, class U> struct D<__type_pack_element<0, T, U>> {};
More information about the cfe-commits
mailing list