Skip to content

Commit

Permalink
Bugfix for missing semaphore in typed template parameters. (#918)
Browse files Browse the repository at this point in the history
* 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]>
  • Loading branch information
MaxSagebaum and hsutter authored Jan 16, 2024
1 parent 7637c50 commit 86064d2
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 36 deletions.
23 changes: 23 additions & 0 deletions regression-tests/pure2-variadics.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,27 @@ x: <Ts...: type> type = {
func: () = {}
}

// int pack expansion
y: <Ts...: int> type = {

func: () ( 0 + ... + Ts);
}

// Discard type name pack expansion
t0: @struct <_...> type = {
f: <_: int> () -> i32 = 0;
}

// Discard template type pack expansion
t1: @struct <T...: _> type = {
f: <_: int> () -> i32 = 0;
}

// Discard typename and template type pack expansion
t2: @struct <_...: _> type = {
f: <_: int> () -> i32 = 0;
}

left_fold_print: <Args...: type> (inout out: std::ostream, args...: Args) = {
// Binary left fold expression
(out << ... << args);
Expand All @@ -31,4 +52,6 @@ main: ()

std::cout << "\nfirst all() returned (all(true, true, true, false))$";
std::cout << "\nsecond all() returned " << all(true, true, true, true) as std::string;

std::cout << "\nsum of (1, 2, 3, 100) is: " << y<1,2,3,100>().func() as std::string;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ plu
abr
3.14word-1500
first all() returned false
second all() returned true
second all() returned true
sum of (1, 2, 3, 100) is: 106
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ plu
abr
3.14word-1500
first all() returned false
second all() returned true
second all() returned true
sum of (1, 2, 3, 100) is: 106
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ plu
abr
3.14word-1500
first all() returned false
second all() returned true
second all() returned true
sum of (1, 2, 3, 100) is: 106
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ namespace ns {

// Variables.

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)
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)

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

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

// Functions.

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

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

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

// Aliases.

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)
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)

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

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)

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

#line 21 "mixed-bugfix-for-ufcs-non-local.cpp2"
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)
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)

#line 23 "mixed-bugfix-for-ufcs-non-local.cpp2"
auto g([[maybe_unused]] cpp2::in<t<CPP2_UFCS_NONLOCAL(f)(o)>> unnamed_param_1) -> void{}// Fails on Clang 12 (lambda in unevaluated context).
Expand Down
32 changes: 13 additions & 19 deletions regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,20 +35,20 @@ class B;
class t {
public: [[nodiscard]] auto f() & -> cpp2::i32;
public: [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32;
public: template<typename UnnamedTypeParam1> [[nodiscard]] auto f() & -> cpp2::i32;
public: template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32;
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;
public: template<typename UnnamedTypeParam1_10_7> [[nodiscard]] auto f() & -> cpp2::i32;
public: template<typename UnnamedTypeParam1_11_7> [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32;
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;
};

[[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32;
[[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32;
template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32;
template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32;
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;
template<typename UnnamedTypeParam1_17_5> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32;
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;
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;

extern t m;
extern t const n;
template<typename UnnamedTypeParam1, typename U> auto inline constexpr a = n;
template<typename UnnamedTypeParam1_23_5, typename U> auto inline constexpr a = n;

extern cpp2::i32 auto_1;
extern cpp2::i32 auto_2;
Expand Down Expand Up @@ -98,23 +98,17 @@ class B {
[[nodiscard]] auto t::f() & -> cpp2::i32 { return print_res(0); }
#line 9 "pure2-bugfix-for-ufcs-arguments.cpp2"
[[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32 { return print_res(1); }
#line 10 "pure2-bugfix-for-ufcs-arguments.cpp2"
template<typename UnnamedTypeParam1> [[nodiscard]] auto t::f() & -> cpp2::i32 { return print_res(2); }
#line 11 "pure2-bugfix-for-ufcs-arguments.cpp2"
template<typename UnnamedTypeParam1> [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32 { return print_res(3); }
#line 12 "pure2-bugfix-for-ufcs-arguments.cpp2"
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); }
template<typename UnnamedTypeParam1_10_7> [[nodiscard]] auto t::f() & -> cpp2::i32 { return print_res(2); }
template<typename UnnamedTypeParam1_11_7> [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32 { return print_res(3); }
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); }

#line 15 "pure2-bugfix-for-ufcs-arguments.cpp2"
[[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32 { return print_res(5); }
#line 16 "pure2-bugfix-for-ufcs-arguments.cpp2"
[[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32 { return print_res(6); }
#line 17 "pure2-bugfix-for-ufcs-arguments.cpp2"
template<typename UnnamedTypeParam1> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32 { return print_res(7); }
#line 18 "pure2-bugfix-for-ufcs-arguments.cpp2"
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); }
#line 19 "pure2-bugfix-for-ufcs-arguments.cpp2"
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); }
template<typename UnnamedTypeParam1_17_5> [[nodiscard]] auto f([[maybe_unused]] cpp2::in<t> unnamed_param_1) -> cpp2::i32 { return print_res(7); }
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); }
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); }

t m {};
t const n {};
Expand Down
61 changes: 58 additions & 3 deletions regression-tests/test-results/pure2-variadics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@
template<typename ...Ts> class x;


#line 10 "pure2-variadics.cpp2"
template<int ...Ts> class y;

#line 16 "pure2-variadics.cpp2"
template<typename ...UnnamedTypeParam1_16_14> class t0;


#line 21 "pure2-variadics.cpp2"
template<auto ...T> class t1;


#line 26 "pure2-variadics.cpp2"
template<auto ...UnnamedTypeParam1_26_14> class t2;


//=== Cpp2 type definitions and function declarations ===========================

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

// int pack expansion
template<int ...Ts> class y {

public: [[nodiscard]] static auto func() -> auto;
public: y() = default;
public: y(y const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(y const&) -> void = delete;

#line 13 "pure2-variadics.cpp2"
};

// Discard type name pack expansion
template<typename ...UnnamedTypeParam1_16_14> class t0 {
public: template<int UnnamedTypeParam1_17_7> [[nodiscard]] static auto f() -> cpp2::i32;
};

// Discard template type pack expansion
template<auto ...T> class t1 {
public: template<int UnnamedTypeParam1_22_7> [[nodiscard]] static auto f() -> cpp2::i32;
};

// Discard typename and template type pack expansion
template<auto ...UnnamedTypeParam1_26_14> class t2 {
public: template<int UnnamedTypeParam1_27_7> [[nodiscard]] static auto f() -> cpp2::i32;
};

template<typename ...Args> auto left_fold_print(std::ostream& out, Args const& ...args) -> void;

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

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

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

#line 9 "pure2-variadics.cpp2"
#line 12 "pure2-variadics.cpp2"
template <int ...Ts> [[nodiscard]] auto y<Ts...>::func() -> auto { return (0 + ... + Ts); }

#line 17 "pure2-variadics.cpp2"
template <typename ...UnnamedTypeParam1_16_14> template<int UnnamedTypeParam1_17_7> [[nodiscard]] auto t0<UnnamedTypeParam1_16_14...>::f() -> cpp2::i32 { return 0; }

#line 22 "pure2-variadics.cpp2"
template <auto ...T> template<int UnnamedTypeParam1_22_7> [[nodiscard]] auto t1<T...>::f() -> cpp2::i32 { return 0; }

#line 27 "pure2-variadics.cpp2"
template <auto ...UnnamedTypeParam1_26_14> template<int UnnamedTypeParam1_27_7> [[nodiscard]] auto t2<UnnamedTypeParam1_26_14...>::f() -> cpp2::i32 { return 0; }

#line 30 "pure2-variadics.cpp2"
template<typename ...Args> auto left_fold_print(std::ostream& out, Args const& ...args) -> void{
// Binary left fold expression
(out << ... << args);
Expand Down Expand Up @@ -78,5 +131,7 @@ auto main() -> int

std::cout << ("\nfirst all() returned " + cpp2::to_string(all(true, true, true, false)));
std::cout << "\nsecond all() returned " << cpp2::as_<std::string>(all(true, true, true, true));

std::cout << "\nsum of (1, 2, 3, 100) is: " << cpp2::as_<std::string>(CPP2_UFCS(func)(y<1,2,3,100>()));
}

9 changes: 9 additions & 0 deletions source/lex.h
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,15 @@ auto labelized_position(token const* t)
return labels[t].text;
}

auto unnamed_type_param_name(int ordinal, token const* t)
-> std::string
{
return "UnnamedTypeParam"
+ std::to_string(ordinal)
+ "_"
+ labelized_position(t);
}


//-----------------------------------------------------------------------
//
Expand Down
25 changes: 19 additions & 6 deletions source/to_cpp1.h
Original file line number Diff line number Diff line change
Expand Up @@ -4277,9 +4277,8 @@ class cppfront
//-----------------------------------------------------------------------
// Handle type parameters

if (n.declaration->is_type()) {
assert( is_template_parameter );
printer.print_cpp2("typename ", identifier_pos);
// Common template naming
auto emit_template_name = [&]() {
if (n.declaration->is_variadic) {
printer.print_cpp2(
"...",
Expand All @@ -4288,12 +4287,18 @@ class cppfront
}

if (identifier == "_") {
printer.print_cpp2( "UnnamedTypeParam" + std::to_string(n.ordinal), identifier_pos );
printer.print_cpp2( unnamed_type_param_name(n.ordinal, n.declaration->identifier->get_token()),
identifier_pos );
}
else {
printer.print_cpp2( identifier, identifier_pos );
}
};
if (n.declaration->is_type()) {
assert( is_template_parameter );
printer.print_cpp2("typename ", identifier_pos);

emit_template_name();
return;
}

Expand All @@ -4306,7 +4311,8 @@ class cppfront
if (is_template_parameter) {
emit( type_id );
printer.print_cpp2(" ", type_id.position());
printer.print_cpp2( identifier, identifier_pos );

emit_template_name();
return;
}

Expand Down Expand Up @@ -4945,7 +4951,14 @@ class cppfront
auto separator = std::string{"<"};
for (auto& tparam : parent->template_parameters->parameters) {
assert (tparam->has_name());
list += separator + tparam->name()->to_string();
list += separator;
if ("_" == tparam->name()->to_string()) {
list += unnamed_type_param_name(tparam->ordinal,
tparam->declaration->identifier->get_token());
}
else {
list += tparam->name()->to_string();
}
if(tparam->declaration->is_variadic) {
list += "...";
}
Expand Down

0 comments on commit 86064d2

Please sign in to comment.