mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 11:26:42 +00:00

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@gmail.com> Differential Revision: https://reviews.llvm.org/D133262
146 lines
9.8 KiB
C++
146 lines
9.8 KiB
C++
// RUN: %clang_cc1 -std=c++2b -fsyntax-only -triple x86_64-linux-gnu -ast-dump -verify -xc++ < %s | FileCheck %s
|
|
|
|
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 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: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'
|
|
// CHECK-NEXT: | `-BuiltinType 0x{{[0-9A-Fa-f]+}} 'int'
|
|
// CHECK-NEXT: |-TemplateArgument expr
|
|
// CHECK-NEXT: | `-ConstantExpr 0x{{[0-9A-Fa-f]+}} <col:22> 'int'
|
|
// 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 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
|
|
// CHECK-NEXT: | |-TemplateTypeParmType 0x{{[0-9A-Fa-f]+}} 'B1' dependent depth 0 index 0
|
|
// 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: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: `-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: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>' 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: `-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: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>' 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: `-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: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>' 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: `-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'
|
|
};
|
|
|
|
// 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>>;
|
|
|
|
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>>;
|
|
|
|
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>>;
|
|
|
|
template <class T> struct G;
|
|
template <class T> struct G<__make_integer_seq<A, T, 1>> {};
|
|
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>);
|
|
void test_h() { h(H<5>{}); }
|