Skip to content

Commit

Permalink
fix(to_cpp1): define type-scope object alias with wildcard type inline
Browse files Browse the repository at this point in the history
  • Loading branch information
JohelEGP committed Oct 9, 2024
1 parent ccf7011 commit 928f1fb
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 24 deletions.
8 changes: 4 additions & 4 deletions regression-tests/pure2-bugfix-for-ufcs-name-lookup.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ ns: namespace = {
f: (_) -> int == 1;
} // namespace ns

// v: @struct type = {
// f :== :(_) 0; // Pending on #706.
// g: (i) i.f();
// }
v: @struct type = {
f :== :(_) = 0;
g: (i) = _ = i.f();
}

main: () = {
{
Expand Down
22 changes: 22 additions & 0 deletions regression-tests/pure2-type-and-namespace-aliases.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,25 @@ main: () = {
myfunc2 :== myfunc;
myfunc2();
}

myclass5: type == myclass4;

myclass3: @struct type = {
// Defined inline.
i0 :== :std::array = (0);
i1 :== i0;
i3: _ == i0;
i7 :== :() = 0;

// Defined out of line.
o2: myclass3 == myclass3();
o4: myclass3 == o2;
o5: myclass4 == myclass4();
o6: myclass5 == myclass5();
}

myclass4: @struct type = { }

myclass6: @struct <T: type> type = {
v: <U> _ requires true == 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ namespace ns {

}

class v;


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

Expand All @@ -41,10 +43,10 @@ namespace ns {
[[nodiscard]] constexpr auto f([[maybe_unused]] auto const& unnamed_param_1) -> int;
} // namespace ns

// v: @struct type = {
// f :== :(_) 0; // Pending on #706.
// g: (i) i.f();
// }
class v {
public: static constexpr auto f = []([[maybe_unused]] auto const& unnamed_param_1) -> decltype(auto) { return 0; };
public: [[nodiscard]] static auto g(auto const& i) -> decltype(auto);
};

auto main() -> int;

Expand All @@ -64,6 +66,9 @@ namespace ns {
[[nodiscard]] constexpr auto f([[maybe_unused]] auto const& unnamed_param_1) -> int { return 1; }
}

#line 17 "pure2-bugfix-for-ufcs-name-lookup.cpp2"
[[nodiscard]] auto v::g(auto const& i) -> decltype(auto) { return static_cast<void>(CPP2_UFCS(f)(i)); }

#line 20 "pure2-bugfix-for-ufcs-name-lookup.cpp2"
auto main() -> int{
{
Expand Down
41 changes: 41 additions & 0 deletions regression-tests/test-results/pure2-type-and-namespace-aliases.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ class myclass;
template<typename T> class myclass2;


#line 39 "pure2-type-and-namespace-aliases.cpp2"
class myclass3;


#line 53 "pure2-type-and-namespace-aliases.cpp2"
class myclass4;

template<typename T> class myclass6;


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

#line 1 "pure2-type-and-namespace-aliases.cpp2"
Expand Down Expand Up @@ -60,6 +70,31 @@ template<typename T> class myclass2 {

auto main() -> int;

#line 37 "pure2-type-and-namespace-aliases.cpp2"
using myclass5 = myclass4;

class myclass3 {
// Defined inline.
public: static constexpr auto i0 = std::array{0};
public: static constexpr auto i1 = i0;
public: static constexpr auto i3 = i0;
public: static constexpr auto i7 = []() -> decltype(auto) { return 0; };

// Defined out of line.
public: static const myclass3 o2;
public: static const myclass3 o4;
public: static const myclass4 o5;
public: static const myclass5 o6;
};

class myclass4 {};

template<typename T> class myclass6 {
#line 56 "pure2-type-and-namespace-aliases.cpp2"
public: template<typename U>
CPP2_REQUIRES_ (true) static constexpr auto v = 0;
};

//=== Cpp2 function definitions =================================================

#line 1 "pure2-type-and-namespace-aliases.cpp2"
Expand Down Expand Up @@ -94,3 +129,9 @@ auto main() -> int{
myfunc2();
}

#line 47 "pure2-type-and-namespace-aliases.cpp2"
inline CPP2_CONSTEXPR myclass3 myclass3::o2{ myclass3() };
inline CPP2_CONSTEXPR myclass3 myclass3::o4{ o2 };
inline CPP2_CONSTEXPR myclass4 myclass3::o5{ myclass4() };
inline CPP2_CONSTEXPR myclass5 myclass3::o6{ myclass5() };

59 changes: 43 additions & 16 deletions source/to_cpp1.h
Original file line number Diff line number Diff line change
Expand Up @@ -1255,7 +1255,7 @@ class cppfront

// Now we'll open the Cpp1 file
auto cpp1_filename = sourcefile.substr(0, std::ssize(sourcefile) - 1);

// Use explicit filename override if present,
// otherwise strip leading path
if (!flag_cpp1_filename.empty()) {
Expand Down Expand Up @@ -3458,12 +3458,12 @@ class cppfront
last_was_prefixed = true;
}

// Handle the other Cpp2 postfix operators that stay postfix in Cpp1
// Handle the other Cpp2 postfix operators that stay postfix in Cpp1
// (currently '...' for expansion, not when used as a range operator)
else if (
is_postfix_operator(i->op->type())
&& !i->last_expr // not being used as a range operator
)
)
{
flush_args();
suffix.emplace_back( i->op->to_string(), i->op->position());
Expand Down Expand Up @@ -3504,7 +3504,7 @@ class cppfront
}

auto print = print_to_string(
*i->id_expr,
*i->id_expr,
false, // not a local name
i->op->type() == lexeme::Dot || i->op->type() == lexeme::DotDot // member access
);
Expand Down Expand Up @@ -4453,8 +4453,8 @@ class cppfront
{
assert(n.declaration);
auto is_param_to_namespace_scope_type =
n.declaration->parent_is_type()
&& n.declaration->parent_declaration->parent_is_namespace()
n.declaration->parent_is_type()
&& n.declaration->parent_declaration->parent_is_namespace()
;

auto emit_in_phase_0 =
Expand Down Expand Up @@ -5091,7 +5091,7 @@ class cppfront
|| n.is_swap()
|| n.is_destructor()
|| (
n.my_decl
n.my_decl
&& generating_move_from == n.my_decl
)
)
Expand All @@ -5105,7 +5105,7 @@ class cppfront
if (
n.is_assignment()
|| (
n.my_decl
n.my_decl
&& generating_assignment_from == n.my_decl
)
)
Expand Down Expand Up @@ -5776,8 +5776,18 @@ class cppfront
auto& a = std::get<declaration_node::an_alias>(n.type);
assert(a);

// Helper for aliases that emit as a defining declaration.
auto const type_scope_object_alias_emits_in_phase_1_only = [&]() {
assert(
n.parent_is_type()
&& n.is_object_alias()
);
return !a->type_id
|| a->type_id->is_wildcard();
};

// Namespace-scope aliases are emitted in phase 1,
// type-scope object aliases in both phases 1 and 2, and
// type-scope object aliases is emitted in phase 1 and maybe 2, and
// function-scope aliases in phase 2
if (
(
Expand All @@ -5789,6 +5799,7 @@ class cppfront
n.parent_is_type()
&& n.is_object_alias()
&& printer.get_phase() == printer.phase2_func_defs
&& !type_scope_object_alias_emits_in_phase_1_only()
)
||
(
Expand Down Expand Up @@ -5863,7 +5874,7 @@ class cppfront
// Handle object aliases:
// - at function scope, it's const&
// - at namespace scope, it's inline constexpr
// - at type scope, it's also inline constexpr but see note (*) below
// - at type scope, it's also static constexpr but see note (*) below
else if (a->is_object_alias())
{
auto type = std::string{"auto"};
Expand All @@ -5888,13 +5899,26 @@ class cppfront
}
};

// (*) If this is at type scope, Cpp1 requires an out-of-line declaration dance
// for some cases to work - see https://stackoverflow.com/questions/11928089/
if (n.parent_is_type())
{
assert (n.parent_declaration->name());

if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
if (type_scope_object_alias_emits_in_phase_1_only()) {
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
printer.print_cpp2(
"static constexpr "
+ type + " "
+ print_to_string(*n.identifier)
+ " = "
+ print_to_string( *std::get<alias_node::an_object>(a->initializer) )
+ ";\n",
n.position()
);
}
}
// At type scope, Cpp1 requires an out-of-line declaration dance
// for some cases to work - see https://stackoverflow.com/questions/11928089/
else if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
printer.print_cpp2(
"static const "
+ type + " "
Expand Down Expand Up @@ -6072,7 +6096,10 @@ class cppfront

// In class definitions, emit the explicit access specifier if there
// is one, or default to private for data and public for functions
if (printer.get_phase() == printer.phase1_type_defs_func_decls)
if (
printer.get_phase() == printer.phase1_type_defs_func_decls
&& n.identifier
)
{
if (!n.is_default_access()) {
assert (is_in_type);
Expand Down Expand Up @@ -6995,8 +7022,8 @@ class cppfront
return;
}
}
printer.preempt_position_push(n.position());
emit( *type, {}, print_to_string(*n.identifier) );
printer.preempt_position_push(n.position());
emit( *type, {}, print_to_string(*n.identifier) );
printer.preempt_position_pop();

if (
Expand Down

0 comments on commit 928f1fb

Please sign in to comment.