Skip to content

Bugfix for missing semaphore in typed template parameters. #918

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 8 commits into from
Jan 16, 2024
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
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