Skip to content

Commit 9226b2a

Browse files
committed
fix(to_cpp1): define type-scope object alias with wildcard type inline
1 parent c5feb42 commit 9226b2a

5 files changed

+119
-24
lines changed

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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 22 additions & 0 deletions
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

Lines changed: 9 additions & 4 deletions
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) mutable -> auto { return 0; };
48+
public: [[nodiscard]] static auto g(auto const& i) -> 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) -> auto { return 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

Lines changed: 41 additions & 0 deletions
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 = []() mutable -> 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

Lines changed: 43 additions & 16 deletions
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()) {
@@ -3428,12 +3428,12 @@ class cppfront
34283428
last_was_prefixed = true;
34293429
}
34303430

3431-
// Handle the other Cpp2 postfix operators that stay postfix in Cpp1
3431+
// Handle the other Cpp2 postfix operators that stay postfix in Cpp1
34323432
// (currently '...' for expansion, not when used as a range operator)
34333433
else if (
34343434
is_postfix_operator(i->op->type())
34353435
&& !i->last_expr // not being used as a range operator
3436-
)
3436+
)
34373437
{
34383438
flush_args();
34393439
suffix.emplace_back( i->op->to_string(), i->op->position());
@@ -3474,7 +3474,7 @@ class cppfront
34743474
}
34753475

34763476
auto print = print_to_string(
3477-
*i->id_expr,
3477+
*i->id_expr,
34783478
false, // not a local name
34793479
i->op->type() == lexeme::Dot || i->op->type() == lexeme::DotDot // member access
34803480
);
@@ -4406,8 +4406,8 @@ class cppfront
44064406
{
44074407
assert(n.declaration);
44084408
auto is_param_to_namespace_scope_type =
4409-
n.declaration->parent_is_type()
4410-
&& n.declaration->parent_declaration->parent_is_namespace()
4409+
n.declaration->parent_is_type()
4410+
&& n.declaration->parent_declaration->parent_is_namespace()
44114411
;
44124412

44134413
auto emit_in_phase_0 =
@@ -5033,7 +5033,7 @@ class cppfront
50335033
|| n.is_swap()
50345034
|| n.is_destructor()
50355035
|| (
5036-
n.my_decl
5036+
n.my_decl
50375037
&& generating_move_from == n.my_decl
50385038
)
50395039
)
@@ -5047,7 +5047,7 @@ class cppfront
50475047
if (
50485048
n.is_assignment()
50495049
|| (
5050-
n.my_decl
5050+
n.my_decl
50515051
&& generating_assignment_from == n.my_decl
50525052
)
50535053
)
@@ -5718,8 +5718,18 @@ class cppfront
57185718
auto& a = std::get<declaration_node::an_alias>(n.type);
57195719
assert(a);
57205720

5721+
// Helper for aliases that emit as a defining declaration.
5722+
auto const type_scope_object_alias_emits_in_phase_1_only = [&]() {
5723+
assert(
5724+
n.parent_is_type()
5725+
&& n.is_object_alias()
5726+
);
5727+
return !a->type_id
5728+
|| a->type_id->is_wildcard();
5729+
};
5730+
57215731
// Namespace-scope aliases are emitted in phase 1,
5722-
// type-scope object aliases in both phases 1 and 2, and
5732+
// type-scope object aliases is emitted in phase 1 and maybe 2, and
57235733
// function-scope aliases in phase 2
57245734
if (
57255735
(
@@ -5731,6 +5741,7 @@ class cppfront
57315741
n.parent_is_type()
57325742
&& n.is_object_alias()
57335743
&& printer.get_phase() == printer.phase2_func_defs
5744+
&& !type_scope_object_alias_emits_in_phase_1_only()
57345745
)
57355746
||
57365747
(
@@ -5805,7 +5816,7 @@ class cppfront
58055816
// Handle object aliases:
58065817
// - at function scope, it's const&
58075818
// - at namespace scope, it's inline constexpr
5808-
// - at type scope, it's also inline constexpr but see note (*) below
5819+
// - at type scope, it's also static constexpr but see note (*) below
58095820
else if (a->is_object_alias())
58105821
{
58115822
auto type = std::string{"auto"};
@@ -5830,13 +5841,26 @@ class cppfront
58305841
}
58315842
};
58325843

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

5839-
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
5848+
if (type_scope_object_alias_emits_in_phase_1_only()) {
5849+
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
5850+
printer.print_cpp2(
5851+
"static constexpr "
5852+
+ type + " "
5853+
+ print_to_string(*n.identifier)
5854+
+ " = "
5855+
+ print_to_string( *std::get<alias_node::an_object>(a->initializer) )
5856+
+ ";\n",
5857+
n.position()
5858+
);
5859+
}
5860+
}
5861+
// At type scope, Cpp1 requires an out-of-line declaration dance
5862+
// for some cases to work - see https://stackoverflow.com/questions/11928089/
5863+
else if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
58405864
printer.print_cpp2(
58415865
"static const "
58425866
+ type + " "
@@ -6014,7 +6038,10 @@ class cppfront
60146038

60156039
// In class definitions, emit the explicit access specifier if there
60166040
// is one, or default to private for data and public for functions
6017-
if (printer.get_phase() == printer.phase1_type_defs_func_decls)
6041+
if (
6042+
printer.get_phase() == printer.phase1_type_defs_func_decls
6043+
&& n.identifier
6044+
)
60186045
{
60196046
if (!n.is_default_access()) {
60206047
assert (is_in_type);
@@ -6935,8 +6962,8 @@ class cppfront
69356962
return;
69366963
}
69376964
}
6938-
printer.preempt_position_push(n.position());
6939-
emit( *type, {}, print_to_string(*n.identifier) );
6965+
printer.preempt_position_push(n.position());
6966+
emit( *type, {}, print_to_string(*n.identifier) );
69406967
printer.preempt_position_pop();
69416968

69426969
if (

0 commit comments

Comments
 (0)