Skip to content

Commit 928f1fb

Browse files
committed
fix(to_cpp1): define type-scope object alias with wildcard type inline
1 parent ccf7011 commit 928f1fb

5 files changed

+119
-24
lines changed

regression-tests/pure2-bugfix-for-ufcs-name-lookup.cpp2

+4-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ ns: namespace = {
1212
f: (_) -> int == 1;
1313
} // namespace ns
1414

15-
// v: @struct type = {
16-
// f :== :(_) 0; // Pending on #706.
17-
// g: (i) i.f();
18-
// }
15+
v: @struct type = {
16+
f :== :(_) = 0;
17+
g: (i) = _ = i.f();
18+
}
1919

2020
main: () = {
2121
{

regression-tests/pure2-type-and-namespace-aliases.cpp2

+22
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,25 @@ main: () = {
3333
myfunc2 :== myfunc;
3434
myfunc2();
3535
}
36+
37+
myclass5: type == myclass4;
38+
39+
myclass3: @struct type = {
40+
// Defined inline.
41+
i0 :== :std::array = (0);
42+
i1 :== i0;
43+
i3: _ == i0;
44+
i7 :== :() = 0;
45+
46+
// Defined out of line.
47+
o2: myclass3 == myclass3();
48+
o4: myclass3 == o2;
49+
o5: myclass4 == myclass4();
50+
o6: myclass5 == myclass5();
51+
}
52+
53+
myclass4: @struct type = { }
54+
55+
myclass6: @struct <T: type> type = {
56+
v: <U> _ requires true == 0;
57+
}

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

+9-4
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ namespace ns {
2222

2323
}
2424

25+
class v;
26+
2527

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

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

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

4951
auto main() -> int;
5052

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

69+
#line 17 "pure2-bugfix-for-ufcs-name-lookup.cpp2"
70+
[[nodiscard]] auto v::g(auto const& i) -> decltype(auto) { return static_cast<void>(CPP2_UFCS(f)(i)); }
71+
6772
#line 20 "pure2-bugfix-for-ufcs-name-lookup.cpp2"
6873
auto main() -> int{
6974
{

regression-tests/test-results/pure2-type-and-namespace-aliases.cpp

+41
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ class myclass;
2121
template<typename T> class myclass2;
2222

2323

24+
#line 39 "pure2-type-and-namespace-aliases.cpp2"
25+
class myclass3;
26+
27+
28+
#line 53 "pure2-type-and-namespace-aliases.cpp2"
29+
class myclass4;
30+
31+
template<typename T> class myclass6;
32+
33+
2434
//=== Cpp2 type definitions and function declarations ===========================
2535

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

6171
auto main() -> int;
6272

73+
#line 37 "pure2-type-and-namespace-aliases.cpp2"
74+
using myclass5 = myclass4;
75+
76+
class myclass3 {
77+
// Defined inline.
78+
public: static constexpr auto i0 = std::array{0};
79+
public: static constexpr auto i1 = i0;
80+
public: static constexpr auto i3 = i0;
81+
public: static constexpr auto i7 = []() -> decltype(auto) { return 0; };
82+
83+
// Defined out of line.
84+
public: static const myclass3 o2;
85+
public: static const myclass3 o4;
86+
public: static const myclass4 o5;
87+
public: static const myclass5 o6;
88+
};
89+
90+
class myclass4 {};
91+
92+
template<typename T> class myclass6 {
93+
#line 56 "pure2-type-and-namespace-aliases.cpp2"
94+
public: template<typename U>
95+
CPP2_REQUIRES_ (true) static constexpr auto v = 0;
96+
};
97+
6398
//=== Cpp2 function definitions =================================================
6499

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

132+
#line 47 "pure2-type-and-namespace-aliases.cpp2"
133+
inline CPP2_CONSTEXPR myclass3 myclass3::o2{ myclass3() };
134+
inline CPP2_CONSTEXPR myclass3 myclass3::o4{ o2 };
135+
inline CPP2_CONSTEXPR myclass4 myclass3::o5{ myclass4() };
136+
inline CPP2_CONSTEXPR myclass5 myclass3::o6{ myclass5() };
137+

source/to_cpp1.h

+43-16
Original file line numberDiff line numberDiff line change
@@ -1255,7 +1255,7 @@ class cppfront
12551255

12561256
// Now we'll open the Cpp1 file
12571257
auto cpp1_filename = sourcefile.substr(0, std::ssize(sourcefile) - 1);
1258-
1258+
12591259
// Use explicit filename override if present,
12601260
// otherwise strip leading path
12611261
if (!flag_cpp1_filename.empty()) {
@@ -3458,12 +3458,12 @@ class cppfront
34583458
last_was_prefixed = true;
34593459
}
34603460

3461-
// Handle the other Cpp2 postfix operators that stay postfix in Cpp1
3461+
// Handle the other Cpp2 postfix operators that stay postfix in Cpp1
34623462
// (currently '...' for expansion, not when used as a range operator)
34633463
else if (
34643464
is_postfix_operator(i->op->type())
34653465
&& !i->last_expr // not being used as a range operator
3466-
)
3466+
)
34673467
{
34683468
flush_args();
34693469
suffix.emplace_back( i->op->to_string(), i->op->position());
@@ -3504,7 +3504,7 @@ class cppfront
35043504
}
35053505

35063506
auto print = print_to_string(
3507-
*i->id_expr,
3507+
*i->id_expr,
35083508
false, // not a local name
35093509
i->op->type() == lexeme::Dot || i->op->type() == lexeme::DotDot // member access
35103510
);
@@ -4453,8 +4453,8 @@ class cppfront
44534453
{
44544454
assert(n.declaration);
44554455
auto is_param_to_namespace_scope_type =
4456-
n.declaration->parent_is_type()
4457-
&& n.declaration->parent_declaration->parent_is_namespace()
4456+
n.declaration->parent_is_type()
4457+
&& n.declaration->parent_declaration->parent_is_namespace()
44584458
;
44594459

44604460
auto emit_in_phase_0 =
@@ -5091,7 +5091,7 @@ class cppfront
50915091
|| n.is_swap()
50925092
|| n.is_destructor()
50935093
|| (
5094-
n.my_decl
5094+
n.my_decl
50955095
&& generating_move_from == n.my_decl
50965096
)
50975097
)
@@ -5105,7 +5105,7 @@ class cppfront
51055105
if (
51065106
n.is_assignment()
51075107
|| (
5108-
n.my_decl
5108+
n.my_decl
51095109
&& generating_assignment_from == n.my_decl
51105110
)
51115111
)
@@ -5776,8 +5776,18 @@ class cppfront
57765776
auto& a = std::get<declaration_node::an_alias>(n.type);
57775777
assert(a);
57785778

5779+
// Helper for aliases that emit as a defining declaration.
5780+
auto const type_scope_object_alias_emits_in_phase_1_only = [&]() {
5781+
assert(
5782+
n.parent_is_type()
5783+
&& n.is_object_alias()
5784+
);
5785+
return !a->type_id
5786+
|| a->type_id->is_wildcard();
5787+
};
5788+
57795789
// Namespace-scope aliases are emitted in phase 1,
5780-
// type-scope object aliases in both phases 1 and 2, and
5790+
// type-scope object aliases is emitted in phase 1 and maybe 2, and
57815791
// function-scope aliases in phase 2
57825792
if (
57835793
(
@@ -5789,6 +5799,7 @@ class cppfront
57895799
n.parent_is_type()
57905800
&& n.is_object_alias()
57915801
&& printer.get_phase() == printer.phase2_func_defs
5802+
&& !type_scope_object_alias_emits_in_phase_1_only()
57925803
)
57935804
||
57945805
(
@@ -5863,7 +5874,7 @@ class cppfront
58635874
// Handle object aliases:
58645875
// - at function scope, it's const&
58655876
// - at namespace scope, it's inline constexpr
5866-
// - at type scope, it's also inline constexpr but see note (*) below
5877+
// - at type scope, it's also static constexpr but see note (*) below
58675878
else if (a->is_object_alias())
58685879
{
58695880
auto type = std::string{"auto"};
@@ -5888,13 +5899,26 @@ class cppfront
58885899
}
58895900
};
58905901

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

5897-
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
5906+
if (type_scope_object_alias_emits_in_phase_1_only()) {
5907+
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
5908+
printer.print_cpp2(
5909+
"static constexpr "
5910+
+ type + " "
5911+
+ print_to_string(*n.identifier)
5912+
+ " = "
5913+
+ print_to_string( *std::get<alias_node::an_object>(a->initializer) )
5914+
+ ";\n",
5915+
n.position()
5916+
);
5917+
}
5918+
}
5919+
// At type scope, Cpp1 requires an out-of-line declaration dance
5920+
// for some cases to work - see https://stackoverflow.com/questions/11928089/
5921+
else if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
58985922
printer.print_cpp2(
58995923
"static const "
59005924
+ type + " "
@@ -6072,7 +6096,10 @@ class cppfront
60726096

60736097
// In class definitions, emit the explicit access specifier if there
60746098
// is one, or default to private for data and public for functions
6075-
if (printer.get_phase() == printer.phase1_type_defs_func_decls)
6099+
if (
6100+
printer.get_phase() == printer.phase1_type_defs_func_decls
6101+
&& n.identifier
6102+
)
60766103
{
60776104
if (!n.is_default_access()) {
60786105
assert (is_in_type);
@@ -6995,8 +7022,8 @@ class cppfront
69957022
return;
69967023
}
69977024
}
6998-
printer.preempt_position_push(n.position());
6999-
emit( *type, {}, print_to_string(*n.identifier) );
7025+
printer.preempt_position_push(n.position());
7026+
emit( *type, {}, print_to_string(*n.identifier) );
70007027
printer.preempt_position_pop();
70017028

70027029
if (

0 commit comments

Comments
 (0)