Skip to content

Commit 86064d2

Browse files
MaxSagebaumhsutter
andauthored
Bugfix for missing semaphore in typed template parameters. (#918)
* Bugfix for missing semaphore in typed template parameters. * Output of unnamed type param name for typed template arguments. * Name clash for unamed template arguments. * Missing name generation of unamed template types in tempalte parameter list. * Update of test results. * Update for failing tests. --------- Signed-off-by: Herb Sutter <[email protected]> Co-authored-by: Herb Sutter <[email protected]>
1 parent 7637c50 commit 86064d2

File tree

9 files changed

+133
-36
lines changed

9 files changed

+133
-36
lines changed

regression-tests/pure2-variadics.cpp2

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,27 @@ x: <Ts...: type> type = {
66
func: () = {}
77
}
88

9+
// int pack expansion
10+
y: <Ts...: int> type = {
11+
12+
func: () ( 0 + ... + Ts);
13+
}
14+
15+
// Discard type name pack expansion
16+
t0: @struct <_...> type = {
17+
f: <_: int> () -> i32 = 0;
18+
}
19+
20+
// Discard template type pack expansion
21+
t1: @struct <T...: _> type = {
22+
f: <_: int> () -> i32 = 0;
23+
}
24+
25+
// Discard typename and template type pack expansion
26+
t2: @struct <_...: _> type = {
27+
f: <_: int> () -> i32 = 0;
28+
}
29+
930
left_fold_print: <Args...: type> (inout out: std::ostream, args...: Args) = {
1031
// Binary left fold expression
1132
(out << ... << args);
@@ -31,4 +52,6 @@ main: ()
3152

3253
std::cout << "\nfirst all() returned (all(true, true, true, false))$";
3354
std::cout << "\nsecond all() returned " << all(true, true, true, true) as std::string;
55+
56+
std::cout << "\nsum of (1, 2, 3, 100) is: " << y<1,2,3,100>().func() as std::string;
3457
}

regression-tests/test-results/apple-clang-14/pure2-variadics.cpp.execution

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ plu
33
abr
44
3.14word-1500
55
first all() returned false
6-
second all() returned true
6+
second all() returned true
7+
sum of (1, 2, 3, 100) is: 106

regression-tests/test-results/gcc-10/pure2-variadics.cpp.execution

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ plu
33
abr
44
3.14word-1500
55
first all() returned false
6-
second all() returned true
6+
second all() returned true
7+
sum of (1, 2, 3, 100) is: 106

regression-tests/test-results/gcc-13/pure2-variadics.cpp.execution

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ plu
33
abr
44
3.14word-1500
55
first all() returned false
6-
second all() returned true
6+
second all() returned true
7+
sum of (1, 2, 3, 100) is: 106

regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,15 @@ namespace ns {
3434

3535
// Variables.
3636

37-
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> bool inline constexpr v0 = false;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
37+
template<t<CPP2_UFCS_NONLOCAL(f)(o)> UnnamedTypeParam1_13_6> bool inline constexpr v0 = false;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
3838

3939
t<CPP2_UFCS_NONLOCAL(f)(o)> inline constexpr v1 = t<true>();// Fails on Clang 12 (lambda in unevaluated context).
4040

4141
bool inline constexpr v2 = CPP2_UFCS_NONLOCAL(f)(o);
4242

4343
// Functions.
4444

45-
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> auto g() -> void;
45+
template<t<CPP2_UFCS_NONLOCAL(f)(o)> UnnamedTypeParam1_21_5> auto g() -> void;
4646

4747
auto g([[maybe_unused]] cpp2::in<t<CPP2_UFCS_NONLOCAL(f)(o)>> unnamed_param_1) -> void;
4848

@@ -52,9 +52,9 @@ auto g() -> void;
5252

5353
// Aliases.
5454

55-
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> using a = bool;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
55+
template<t<CPP2_UFCS_NONLOCAL(f)(o)> UnnamedTypeParam1_31_5> using a = bool;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
5656

57-
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> auto inline constexpr b = false;// Fails on GCC ([GCC109781][]).
57+
template<t<CPP2_UFCS_NONLOCAL(f)(o)> UnnamedTypeParam1_33_5> auto inline constexpr b = false;// Fails on GCC ([GCC109781][]).
5858

5959
using c = t<CPP2_UFCS_NONLOCAL(f)(o)>;// Fails on Clang 12 (lambda in unevaluated context) and Clang 12 (a lambda expression cannot appear in this context)
6060

@@ -81,7 +81,7 @@ auto main() -> int;
8181
namespace ns {
8282

8383
#line 21 "mixed-bugfix-for-ufcs-non-local.cpp2"
84-
template<t<CPP2_UFCS_NONLOCAL(f)(o)> _> auto g() -> void{}// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
84+
template<t<CPP2_UFCS_NONLOCAL(f)(o)> UnnamedTypeParam1_21_5> auto g() -> void{}// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context)
8585

8686
#line 23 "mixed-bugfix-for-ufcs-non-local.cpp2"
8787
auto g([[maybe_unused]] cpp2::in<t<CPP2_UFCS_NONLOCAL(f)(o)>> unnamed_param_1) -> void{}// Fails on Clang 12 (lambda in unevaluated context).

regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,20 @@ class B;
3535
class t {
3636
public: [[nodiscard]] auto f() & -> cpp2::i32;
3737
public: [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32;
38-
public: template<typename UnnamedTypeParam1> [[nodiscard]] auto f() & -> cpp2::i32;
39-
public: template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32;
40-
public: template<typename UnnamedTypeParam1, typename U> [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) & -> cpp2::i32;
38+
public: template<typename UnnamedTypeParam1_10_7> [[nodiscard]] auto f() & -> cpp2::i32;
39+
public: template<typename UnnamedTypeParam1_11_7> [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32;
40+
public: template<typename UnnamedTypeParam1_12_7, typename U> [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) & -> cpp2::i32;
4141
};
4242

4343
[[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32;
4444
[[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32;
45-
template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32;
46-
template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32;
47-
template<typename UnnamedTypeParam1, typename U> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) -> cpp2::i32;
45+
template<typename UnnamedTypeParam1_17_5> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32;
46+
template<typename UnnamedTypeParam1_18_5> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32;
47+
template<typename UnnamedTypeParam1_19_5, typename U> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) -> cpp2::i32;
4848

4949
extern t m;
5050
extern t const n;
51-
template<typename UnnamedTypeParam1, typename U> auto inline constexpr a = n;
51+
template<typename UnnamedTypeParam1_23_5, typename U> auto inline constexpr a = n;
5252

5353
extern cpp2::i32 auto_1;
5454
extern cpp2::i32 auto_2;
@@ -98,23 +98,17 @@ class B {
9898
[[nodiscard]] auto t::f() & -> cpp2::i32 { return print_res(0); }
9999
#line 9 "pure2-bugfix-for-ufcs-arguments.cpp2"
100100
[[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32 { return print_res(1); }
101-
#line 10 "pure2-bugfix-for-ufcs-arguments.cpp2"
102-
template<typename UnnamedTypeParam1> [[nodiscard]] auto t::f() & -> cpp2::i32 { return print_res(2); }
103-
#line 11 "pure2-bugfix-for-ufcs-arguments.cpp2"
104-
template<typename UnnamedTypeParam1> [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32 { return print_res(3); }
105-
#line 12 "pure2-bugfix-for-ufcs-arguments.cpp2"
106-
template<typename UnnamedTypeParam1, typename U> [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) & -> cpp2::i32 { return print_res(4); }
101+
template<typename UnnamedTypeParam1_10_7> [[nodiscard]] auto t::f() & -> cpp2::i32 { return print_res(2); }
102+
template<typename UnnamedTypeParam1_11_7> [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32 { return print_res(3); }
103+
template<typename UnnamedTypeParam1_12_7, typename U> [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) & -> cpp2::i32 { return print_res(4); }
107104

108105
#line 15 "pure2-bugfix-for-ufcs-arguments.cpp2"
109106
[[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32 { return print_res(5); }
110107
#line 16 "pure2-bugfix-for-ufcs-arguments.cpp2"
111108
[[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32 { return print_res(6); }
112-
#line 17 "pure2-bugfix-for-ufcs-arguments.cpp2"
113-
template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32 { return print_res(7); }
114-
#line 18 "pure2-bugfix-for-ufcs-arguments.cpp2"
115-
template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32 { return print_res(8); }
116-
#line 19 "pure2-bugfix-for-ufcs-arguments.cpp2"
117-
template<typename UnnamedTypeParam1, typename U> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) -> cpp2::i32 { return print_res(9); }
109+
template<typename UnnamedTypeParam1_17_5> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32 { return print_res(7); }
110+
template<typename UnnamedTypeParam1_18_5> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32 { return print_res(8); }
111+
template<typename UnnamedTypeParam1_19_5, typename U> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) -> cpp2::i32 { return print_res(9); }
118112

119113
t m {};
120114
t const n {};

regression-tests/test-results/pure2-variadics.cpp

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,21 @@
1212
template<typename ...Ts> class x;
1313

1414

15+
#line 10 "pure2-variadics.cpp2"
16+
template<int ...Ts> class y;
17+
18+
#line 16 "pure2-variadics.cpp2"
19+
template<typename ...UnnamedTypeParam1_16_14> class t0;
20+
21+
22+
#line 21 "pure2-variadics.cpp2"
23+
template<auto ...T> class t1;
24+
25+
26+
#line 26 "pure2-variadics.cpp2"
27+
template<auto ...UnnamedTypeParam1_26_14> class t2;
28+
29+
1530
//=== Cpp2 type definitions and function declarations ===========================
1631

1732
#line 1 "pure2-variadics.cpp2"
@@ -29,12 +44,38 @@ template<typename ...Ts> class x {
2944
#line 7 "pure2-variadics.cpp2"
3045
};
3146

47+
// int pack expansion
48+
template<int ...Ts> class y {
49+
50+
public: [[nodiscard]] static auto func() -> auto;
51+
public: y() = default;
52+
public: y(y const&) = delete; /* No 'that' constructor, suppress copy */
53+
public: auto operator=(y const&) -> void = delete;
54+
55+
#line 13 "pure2-variadics.cpp2"
56+
};
57+
58+
// Discard type name pack expansion
59+
template<typename ...UnnamedTypeParam1_16_14> class t0 {
60+
public: template<int UnnamedTypeParam1_17_7> [[nodiscard]] static auto f() -> cpp2::i32;
61+
};
62+
63+
// Discard template type pack expansion
64+
template<auto ...T> class t1 {
65+
public: template<int UnnamedTypeParam1_22_7> [[nodiscard]] static auto f() -> cpp2::i32;
66+
};
67+
68+
// Discard typename and template type pack expansion
69+
template<auto ...UnnamedTypeParam1_26_14> class t2 {
70+
public: template<int UnnamedTypeParam1_27_7> [[nodiscard]] static auto f() -> cpp2::i32;
71+
};
72+
3273
template<typename ...Args> auto left_fold_print(std::ostream& out, Args const& ...args) -> void;
3374

34-
#line 14 "pure2-variadics.cpp2"
75+
#line 35 "pure2-variadics.cpp2"
3576
template<typename ...Args> [[nodiscard]] auto all(Args const& ...args) -> bool;
3677

37-
#line 18 "pure2-variadics.cpp2"
78+
#line 39 "pure2-variadics.cpp2"
3879
template <typename ...Args> [[nodiscard]] auto make_string(Args&& ...args) -> auto;
3980

4081
template <typename T, typename ...Args> [[nodiscard]] auto make(Args&& ...args) -> auto;
@@ -48,7 +89,19 @@ auto main() -> int;
4889
#line 6 "pure2-variadics.cpp2"
4990
template <typename ...Ts> auto x<Ts...>::func() -> void{}
5091

51-
#line 9 "pure2-variadics.cpp2"
92+
#line 12 "pure2-variadics.cpp2"
93+
template <int ...Ts> [[nodiscard]] auto y<Ts...>::func() -> auto { return (0 + ... + Ts); }
94+
95+
#line 17 "pure2-variadics.cpp2"
96+
template <typename ...UnnamedTypeParam1_16_14> template<int UnnamedTypeParam1_17_7> [[nodiscard]] auto t0<UnnamedTypeParam1_16_14...>::f() -> cpp2::i32 { return 0; }
97+
98+
#line 22 "pure2-variadics.cpp2"
99+
template <auto ...T> template<int UnnamedTypeParam1_22_7> [[nodiscard]] auto t1<T...>::f() -> cpp2::i32 { return 0; }
100+
101+
#line 27 "pure2-variadics.cpp2"
102+
template <auto ...UnnamedTypeParam1_26_14> template<int UnnamedTypeParam1_27_7> [[nodiscard]] auto t2<UnnamedTypeParam1_26_14...>::f() -> cpp2::i32 { return 0; }
103+
104+
#line 30 "pure2-variadics.cpp2"
52105
template<typename ...Args> auto left_fold_print(std::ostream& out, Args const& ...args) -> void{
53106
// Binary left fold expression
54107
(out << ... << args);
@@ -78,5 +131,7 @@ auto main() -> int
78131

79132
std::cout << ("\nfirst all() returned " + cpp2::to_string(all(true, true, true, false)));
80133
std::cout << "\nsecond all() returned " << cpp2::as_<std::string>(all(true, true, true, true));
134+
135+
std::cout << "\nsum of (1, 2, 3, 100) is: " << cpp2::as_<std::string>(CPP2_UFCS(func)(y<1,2,3,100>()));
81136
}
82137

source/lex.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,15 @@ auto labelized_position(token const* t)
336336
return labels[t].text;
337337
}
338338

339+
auto unnamed_type_param_name(int ordinal, token const* t)
340+
-> std::string
341+
{
342+
return "UnnamedTypeParam"
343+
+ std::to_string(ordinal)
344+
+ "_"
345+
+ labelized_position(t);
346+
}
347+
339348

340349
//-----------------------------------------------------------------------
341350
//

source/to_cpp1.h

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4277,9 +4277,8 @@ class cppfront
42774277
//-----------------------------------------------------------------------
42784278
// Handle type parameters
42794279

4280-
if (n.declaration->is_type()) {
4281-
assert( is_template_parameter );
4282-
printer.print_cpp2("typename ", identifier_pos);
4280+
// Common template naming
4281+
auto emit_template_name = [&]() {
42834282
if (n.declaration->is_variadic) {
42844283
printer.print_cpp2(
42854284
"...",
@@ -4288,12 +4287,18 @@ class cppfront
42884287
}
42894288

42904289
if (identifier == "_") {
4291-
printer.print_cpp2( "UnnamedTypeParam" + std::to_string(n.ordinal), identifier_pos );
4290+
printer.print_cpp2( unnamed_type_param_name(n.ordinal, n.declaration->identifier->get_token()),
4291+
identifier_pos );
42924292
}
42934293
else {
42944294
printer.print_cpp2( identifier, identifier_pos );
42954295
}
4296+
};
4297+
if (n.declaration->is_type()) {
4298+
assert( is_template_parameter );
4299+
printer.print_cpp2("typename ", identifier_pos);
42964300

4301+
emit_template_name();
42974302
return;
42984303
}
42994304

@@ -4306,7 +4311,8 @@ class cppfront
43064311
if (is_template_parameter) {
43074312
emit( type_id );
43084313
printer.print_cpp2(" ", type_id.position());
4309-
printer.print_cpp2( identifier, identifier_pos );
4314+
4315+
emit_template_name();
43104316
return;
43114317
}
43124318

@@ -4945,7 +4951,14 @@ class cppfront
49454951
auto separator = std::string{"<"};
49464952
for (auto& tparam : parent->template_parameters->parameters) {
49474953
assert (tparam->has_name());
4948-
list += separator + tparam->name()->to_string();
4954+
list += separator;
4955+
if ("_" == tparam->name()->to_string()) {
4956+
list += unnamed_type_param_name(tparam->ordinal,
4957+
tparam->declaration->identifier->get_token());
4958+
}
4959+
else {
4960+
list += tparam->name()->to_string();
4961+
}
49494962
if(tparam->declaration->is_variadic) {
49504963
list += "...";
49514964
}

0 commit comments

Comments
 (0)