Skip to content

[clang] Reland: Instantiate alias templates with sugar #101858

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang-tools-extra/clangd/unittests/HoverTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@ class Foo final {})cpp";
HI.LocalScope = "";
HI.Kind = index::SymbolKind::TypeAlias;
HI.Definition = "template <typename T> using AA = A<T>";
HI.Type = {"A<T>", "type-parameter-0-0"}; // FIXME: should be 'T'
HI.Type = {"A<T>", "T"};
HI.TemplateParameters = {
{{"typename"}, std::string("T"), std::nullopt}};
}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ T qux(T Generic) {
async::Future<T> TemplateType;
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unused local variable 'TemplateType' of type 'async::Future<T>' [bugprone-unused-local-non-trivial-variable]
a::Future<T> AliasTemplateType;
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future<T>' (aka 'Future<type-parameter-0-0>') [bugprone-unused-local-non-trivial-variable]
// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unused local variable 'AliasTemplateType' of type 'a::Future<T>' (aka 'Future<T>') [bugprone-unused-local-non-trivial-variable]
[[maybe_unused]] async::Future<Units> MaybeUnused;
return Generic;
}
Expand Down
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ Improvements to Clang's diagnostics

- -Wdangling-assignment-gsl is enabled by default.
- Clang now does a better job preserving the template arguments as written when specializing concepts.
- Clang now always preserves the template arguments as written used
to specialize template type aliases.

Improvements to Clang's time-trace
----------------------------------
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3334,8 +3334,8 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,

// Only substitute for the innermost template argument list.
MultiLevelTemplateArgumentList TemplateArgLists;
TemplateArgLists.addOuterTemplateArguments(Template, CanonicalConverted,
/*Final=*/false);
TemplateArgLists.addOuterTemplateArguments(Template, SugaredConverted,
/*Final=*/true);
TemplateArgLists.addOuterRetainedLevels(
AliasTemplate->getTemplateParameters()->getDepth());

Expand Down
35 changes: 8 additions & 27 deletions clang/test/AST/ast-dump-template-decls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,48 +123,31 @@ using type2 = typename C<int>::type1<void>;
// CHECK-NEXT: TemplateArgument type 'void'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: FunctionProtoType 0x{{[^ ]*}} 'void (int)' cdecl
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'void' sugar class depth 0 index 0 U
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'type1'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'void'
// CHECK-NEXT: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 0 T
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'C'
// CHECK-NEXT: BuiltinType 0x{{[^ ]*}} 'int'
} // namespace PR55886

namespace PR56099 {
template <typename... As> struct Y;
template <typename... Bs> using Z = Y<Bs...>;
template <typename... Cs> struct foo {
template <typename... Ds> using bind = Z<Ds..., Cs...>;
};
using t1 = foo<int, short>::bind<char, float>;
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'Y<char, float, int, short>' sugar
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... Bs pack_index 3
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... Bs pack_index 2
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... Bs pack_index 1
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... Bs pack_index 0
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'Z'

template <typename... T> struct D {
template <typename... U> using B = int(int (*...p)(T, U));
template <typename... U> struct bind {
using bound_type = int(int (*...p)(T, U));
};
};
using t2 = D<float, char>::B<int, short>;
// CHECK: TemplateSpecializationType 0x{{[^ ]*}} 'B<int, short>' sugar alias{{$}}
// CHECK-NEXT: name: 'D<float, char>::B':'PR56099::D<float, char>::B' qualified
template struct D<float, char>::bind<int, short>;
// CHECK: TypeAliasDecl 0x{{[^ ]*}} <line:{{[1-9]+}}:5, col:45> col:11 bound_type 'int (int (*)(float, int), int (*)(char, short))'
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (int (*)(float, int), int (*)(char, short))' cdecl
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (float, int)' cdecl
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'float' sugar typename depth 0 index 0 ... T pack_index 1
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar typename depth 0 index 0 ... U pack_index 1
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'B'
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'bind'
// CHECK: FunctionProtoType 0x{{[^ ]*}} 'int (char, short)' cdecl
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'char' sugar typename depth 0 index 0 ... T pack_index 0
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'D'
// CHECK: SubstTemplateTypeParmType 0x{{[^ ]*}} 'short' sugar typename depth 0 index 0 ... U pack_index 0
// CHECK-NEXT: TypeAliasTemplate 0x{{[^ ]*}} 'B'
// CHECK-NEXT: ClassTemplateSpecialization 0x{{[^ ]*}} 'bind'
} // namespace PR56099

namespace subst_default_argument {
Expand All @@ -178,9 +161,7 @@ using test1 = D<E, int>;
// CHECK-NEXT: |-name: 'A':'subst_default_argument::A' qualified
// CHECK-NEXT: | `-ClassTemplateDecl {{.+}} A
// CHECK-NEXT: |-TemplateArgument type 'int'
// CHECK-NEXT: | `-SubstTemplateTypeParmType 0x{{[^ ]*}} 'int' sugar class depth 0 index 1 D2
// CHECK-NEXT: | |-TypeAliasTemplate 0x{{[^ ]*}} 'D'
// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
// CHECK-NEXT: | `-BuiltinType 0x{{[^ ]*}} 'int'
// CHECK-NEXT: `-RecordType 0x{{[^ ]*}} 'subst_default_argument::A<int>'
// CHECK-NEXT: `-ClassTemplateSpecialization 0x{{[^ ]*}} 'A'
} // namespace subst_default_argument
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/temp/temp.deduct.guide/p3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ template<template<typename> typename TT> struct E { // expected-note 2{{template
};

A(int) -> int; // expected-error {{deduced type 'int' of deduction guide is not a specialization of template 'A'}}
template<typename T> A(T) -> B<T>; // expected-error {{deduced type 'B<T>' (aka 'A<type-parameter-0-0>') of deduction guide is not written as a specialization of template 'A'}}
template <typename T> A(T)->B<T>; // expected-error {{deduced type 'B<T>' (aka 'A<T>') of deduction guide is not written as a specialization of template 'A'}}
template<typename T> A(T*) -> const A<T>; // expected-error {{deduced type 'const A<T>' of deduction guide is not a specialization of template 'A'}}

// A deduction-guide shall be declared in the same scope as the corresponding
Expand Down
21 changes: 9 additions & 12 deletions clang/test/Misc/diag-template-diffing-cxx11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,25 +257,22 @@ int f9(S9<int, char, U9<const double>>);
int k9 = f9(V9<double>());

// CHECK-ELIDE-NOTREE: no matching function for call to 'f9'
// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<[2 * ...], S9<[2 * ...], double>>' to 'S9<[2 * ...], S9<[2 * ...], const double>>' for 1st argument
// CHECK-ELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<[2 * ...], U9<double>>' to 'S9<[2 * ...], U9<const double>>' for 1st argument
// CHECK-NOELIDE-NOTREE: no matching function for call to 'f9'
// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<int, char, S9<int, char, double>>' to 'S9<int, char, S9<int, char, const double>>' for 1st argument
// CHECK-NOELIDE-NOTREE: candidate function not viable: no known conversion from 'S9<int, char, U9<double>>' to 'S9<int, char, U9<const double>>' for 1st argument
// CHECK-ELIDE-TREE: no matching function for call to 'f9'
// CHECK-ELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-ELIDE-TREE: S9<
// CHECK-ELIDE-TREE: [2 * ...],
// CHECK-ELIDE-TREE: S9<
// CHECK-ELIDE-TREE: [2 * ...],
// CHECK-ELIDE-TREE: [double != const double]>>
// CHECK-ELIDE-TREE: [2 * ...],
// CHECK-ELIDE-TREE: U9<
// CHECK-ELIDE-TREE: [(no qualifiers) != const] double>>
// CHECK-NOELIDE-TREE: no matching function for call to 'f9'
// CHECK-NOELIDE-TREE: candidate function not viable: no known conversion from argument type to parameter type for 1st argument
// CHECK-NOELIDE-TREE: S9<
// CHECK-NOELIDE-TREE: int,
// CHECK-NOELIDE-TREE: char,
// CHECK-NOELIDE-TREE: S9<
// CHECK-NOELIDE-TREE: int,
// CHECK-NOELIDE-TREE: char,
// CHECK-NOELIDE-TREE: [double != const double]>>
// CHECK-NOELIDE-TREE: int,
// CHECK-NOELIDE-TREE: char,
// CHECK-NOELIDE-TREE: U9<
// CHECK-NOELIDE-TREE: [(no qualifiers) != const] double>>

template<typename ...A> class class_types {};
void set10(class_types<int, int>) {}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/SemaCXX/nullability.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ void test_accepts_nonnull_null_pointer_literal(X *x) {
accepts_nonnull_6(nullptr); // expected-warning{{null passed to a callee that requires a non-null argument}}
}

template<void FP(_Nonnull int*)>
template<void FP(_Nonnull int*)>
void test_accepts_nonnull_null_pointer_literal_template() {
FP(0); // expected-warning{{null passed to a callee that requires a non-null argument}}
}
Expand Down Expand Up @@ -197,6 +197,6 @@ void testNullabilityCompletenessWithTemplate() {

namespace GH60344 {
class a;
template <typename b> using c = b _Nullable; // expected-error {{'_Nullable' cannot be applied to non-pointer type 'GH60344::a'}}
template <typename b> using c = b _Nullable; // expected-error {{'_Nullable' cannot be applied to non-pointer type 'a'}}
c<a>; // expected-note {{in instantiation of template type alias 'c' requested here}}
}
2 changes: 1 addition & 1 deletion clang/test/SemaCXX/sizeless-1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ void template_fn_rvalue_ref(T &&) {}

#if __cplusplus >= 201103L
template <typename T>
using array_alias = T[1]; // expected-error {{array has sizeless element type '__SVInt8_t'}}
using array_alias = T[1]; // expected-error {{array has sizeless element type 'svint8_t' (aka '__SVInt8_t')}}
extern array_alias<int> *array_alias_int_ptr;
extern array_alias<svint8_t> *array_alias_int8_ptr; // expected-note {{in instantiation of template type alias 'array_alias' requested here}}
#endif
Expand Down
10 changes: 5 additions & 5 deletions clang/test/SemaHLSL/VectorOverloadResolution.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ void Fn2(int16_t2 S);
// CHECK: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(int64_t2)' <FunctionToPointerDecay>
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (int64_t2)' lvalue Function {{.*}} 'Fn2' 'void (int64_t2)'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<long, 2>' <IntegralCast>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int64_t, 2>' <IntegralCast>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int2':'vector<int, 2>' <LValueToRValue>
// CHECK-NEXT: DeclRefExpr {{.*}} 'int2':'vector<int, 2>' lvalue ParmVar {{.*}} 'I' 'int2':'vector<int, 2>'

Expand All @@ -36,7 +36,7 @@ void Fn3( int64_t2 p0);
// CHECK: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(int64_t2)' <FunctionToPointerDecay>
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (int64_t2)' lvalue Function {{.*}} 'Fn3' 'void (int64_t2)'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<long, 2>' <FloatingToIntegral>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int64_t, 2>' <FloatingToIntegral>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'half2':'vector<half, 2>' <LValueToRValue>
// CHECK-NEXT: DeclRefExpr {{.*}} 'half2':'vector<half, 2>' lvalue ParmVar {{.*}} 'p0' 'half2':'vector<half, 2>'
// CHECKIR-LABEL: Call3
Expand All @@ -49,7 +49,7 @@ void Call3(half2 p0) {
// CHECK: CallExpr {{.*}} 'void'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(int64_t2)' <FunctionToPointerDecay>
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (int64_t2)' lvalue Function {{.*}} 'Fn3' 'void (int64_t2)'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<long, 2>' <FloatingToIntegral>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int64_t, 2>' <FloatingToIntegral>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float2':'vector<float, 2>' <LValueToRValue>
// CHECK-NEXT: DeclRefExpr {{.*}} 'float2':'vector<float, 2>' lvalue ParmVar {{.*}} 'p0' 'float2':'vector<float, 2>'
// CHECKIR-LABEL: Call4
Expand All @@ -65,8 +65,8 @@ void Fn4( float2 p0);
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'void (*)(float2)' <FunctionToPointerDecay>
// CHECK-NEXT: DeclRefExpr {{.*}} 'void (float2)' lvalue Function {{.*}} 'Fn4' 'void (float2)'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>' <IntegralToFloating>
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t2':'vector<long, 2>' <LValueToRValue>
// CHECK-NEXT: DeclRefExpr {{.*}} 'int64_t2':'vector<long, 2>' lvalue ParmVar {{.*}} 'p0' 'int64_t2':'vector<long, 2>'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'int64_t2':'vector<int64_t, 2>' <LValueToRValue>
// CHECK-NEXT: DeclRefExpr {{.*}} 'int64_t2':'vector<int64_t, 2>' lvalue ParmVar {{.*}} 'p0' 'int64_t2':'vector<int64_t, 2>'
// CHECKIR-LABEL: Call5
// CHECKIR: {{.*}} = sitofp <2 x i64> {{.*}} to <2 x float>
void Call5(int64_t2 p0) {
Expand Down
Loading
Loading