Skip to content

Commit 25626db

Browse files
committed
Make @union accessor actually return the exact type
Closes #696
1 parent f4a2ddb commit 25626db

File tree

5 files changed

+54
-54
lines changed

5 files changed

+54
-54
lines changed

regression-tests/test-results/pure2-union.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ class name_or_number;
1616

1717
#line 2 "pure2-union.cpp2"
1818
class name_or_number {
19-
private: std::aligned_storage_t<cpp2::max(sizeof(std::string), sizeof(cpp2::i32))> _storage {}; private: cpp2::i8 discriminator__ {-1}; public: [[nodiscard]] auto is_name() const& -> bool;
20-
public: [[nodiscard]] auto name() const& -> auto&&;
21-
public: [[nodiscard]] auto name() & -> auto&&;
19+
private: std::aligned_storage_t<cpp2::max(sizeof(std::string), sizeof(cpp2::i32))> _storage {}; private: cpp2::i8 _discriminator {-1}; public: [[nodiscard]] auto is_name() const& -> bool;
20+
public: [[nodiscard]] auto name() const& -> std::string const&;
21+
public: [[nodiscard]] auto name() & -> std::string&;
2222
public: auto set_name(cpp2::in<std::string> value) & -> void;
2323
public: auto set_name(auto&& ...args) & -> void;
2424
public: [[nodiscard]] auto is_num() const& -> bool;
25-
public: [[nodiscard]] auto num() const& -> auto&&;
26-
public: [[nodiscard]] auto num() & -> auto&&;
25+
public: [[nodiscard]] auto num() const& -> cpp2::i32 const&;
26+
public: [[nodiscard]] auto num() & -> cpp2::i32&;
2727
public: auto set_num(cpp2::in<cpp2::i32> value) & -> void;
2828
public: auto set_num(auto&& ...args) & -> void;
2929
private: auto destroy() & -> void;
@@ -48,19 +48,19 @@ auto main() -> int;
4848

4949

5050

51-
[[nodiscard]] auto name_or_number::is_name() const& -> bool { return discriminator__ == 0; }
52-
[[nodiscard]] auto name_or_number::name() const& -> auto&& { return *cpp2::assert_not_null(reinterpret_cast<std::string const*>(&_storage)); }
53-
[[nodiscard]] auto name_or_number::name() & -> auto&& { return *cpp2::assert_not_null(reinterpret_cast<std::string*>(&_storage)); }
54-
auto name_or_number::set_name(cpp2::in<std::string> value) & -> void{if (!(is_name())) {destroy();std::construct_at(reinterpret_cast<std::string*>(&_storage), value);}else {*cpp2::assert_not_null(reinterpret_cast<std::string*>(&_storage)) = value;}discriminator__ = 0;}
55-
auto name_or_number::set_name(auto&& ...args) & -> void{if (!(is_name())) {destroy();std::construct_at(reinterpret_cast<std::string*>(&_storage), args...);}else {*cpp2::assert_not_null(reinterpret_cast<std::string*>(&_storage)) = std::string{args...};}discriminator__ = 0;}
56-
[[nodiscard]] auto name_or_number::is_num() const& -> bool { return discriminator__ == 1; }
57-
[[nodiscard]] auto name_or_number::num() const& -> auto&& { return *cpp2::assert_not_null(reinterpret_cast<cpp2::i32 const*>(&_storage)); }
58-
[[nodiscard]] auto name_or_number::num() & -> auto&& { return *cpp2::assert_not_null(reinterpret_cast<cpp2::i32*>(&_storage)); }
59-
auto name_or_number::set_num(cpp2::in<cpp2::i32> value) & -> void{if (!(is_num())) {destroy();std::construct_at(reinterpret_cast<cpp2::i32*>(&_storage), value);}else {*cpp2::assert_not_null(reinterpret_cast<cpp2::i32*>(&_storage)) = value;}discriminator__ = 1;}
60-
auto name_or_number::set_num(auto&& ...args) & -> void{if (!(is_num())) {destroy();std::construct_at(reinterpret_cast<cpp2::i32*>(&_storage), args...);}else {*cpp2::assert_not_null(reinterpret_cast<cpp2::i32*>(&_storage)) = cpp2::i32{args...};}discriminator__ = 1;}
51+
[[nodiscard]] auto name_or_number::is_name() const& -> bool { return _discriminator == 0; }
52+
[[nodiscard]] auto name_or_number::name() const& -> std::string const& { return *cpp2::assert_not_null(reinterpret_cast<std::string const*>(&_storage)); }
53+
[[nodiscard]] auto name_or_number::name() & -> std::string& { return *cpp2::assert_not_null(reinterpret_cast<std::string*>(&_storage)); }
54+
auto name_or_number::set_name(cpp2::in<std::string> value) & -> void{if (!(is_name())) {destroy();std::construct_at(reinterpret_cast<std::string*>(&_storage), value);}else {*cpp2::assert_not_null(reinterpret_cast<std::string*>(&_storage)) = value;}_discriminator = 0;}
55+
auto name_or_number::set_name(auto&& ...args) & -> void{if (!(is_name())) {destroy();std::construct_at(reinterpret_cast<std::string*>(&_storage), args...);}else {*cpp2::assert_not_null(reinterpret_cast<std::string*>(&_storage)) = std::string{args...};}_discriminator = 0;}
56+
[[nodiscard]] auto name_or_number::is_num() const& -> bool { return _discriminator == 1; }
57+
[[nodiscard]] auto name_or_number::num() const& -> cpp2::i32 const& { return *cpp2::assert_not_null(reinterpret_cast<cpp2::i32 const*>(&_storage)); }
58+
[[nodiscard]] auto name_or_number::num() & -> cpp2::i32& { return *cpp2::assert_not_null(reinterpret_cast<cpp2::i32*>(&_storage)); }
59+
auto name_or_number::set_num(cpp2::in<cpp2::i32> value) & -> void{if (!(is_num())) {destroy();std::construct_at(reinterpret_cast<cpp2::i32*>(&_storage), value);}else {*cpp2::assert_not_null(reinterpret_cast<cpp2::i32*>(&_storage)) = value;}_discriminator = 1;}
60+
auto name_or_number::set_num(auto&& ...args) & -> void{if (!(is_num())) {destroy();std::construct_at(reinterpret_cast<cpp2::i32*>(&_storage), args...);}else {*cpp2::assert_not_null(reinterpret_cast<cpp2::i32*>(&_storage)) = cpp2::i32{args...};}_discriminator = 1;}
6161
auto name_or_number::destroy() & -> void{
62-
if (discriminator__ == 0) {std::destroy_at(reinterpret_cast<std::string*>(&_storage));}
63-
if (discriminator__ == 1) {std::destroy_at(reinterpret_cast<cpp2::i32*>(&_storage));}
62+
if (_discriminator == 0) {std::destroy_at(reinterpret_cast<std::string*>(&_storage));}
63+
if (_discriminator == 1) {std::destroy_at(reinterpret_cast<cpp2::i32*>(&_storage));}
6464
}
6565

6666
name_or_number::~name_or_number() noexcept{destroy();}

regression-tests/test-results/version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11

2-
cppfront compiler v0.2.1 Build 8925:1318
2+
cppfront compiler v0.2.1 Build 8925:1454
33
Copyright(c) Herb Sutter All rights reserved
44

55
SPDX-License-Identifier: CC-BY-NC-ND-4.0

source/build.info

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"8925:1318"
1+
"8925:1454"

source/reflect.h

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1629,15 +1629,15 @@ auto value = 0;
16291629
CPP2_UFCS(require, m, CPP2_UFCS_0(is_public, m) || CPP2_UFCS_0(is_default_access, m),
16301630
"a union alternative cannot be protected or private");
16311631

1632-
if (CPP2_UFCS_0(is_object, m)) {
1633-
auto mo {CPP2_UFCS_0(as_object, m)};
1634-
CPP2_UFCS(require, mo, CPP2_UFCS_0(empty, CPP2_UFCS_0(initializer, mo)),
1635-
"a union alternative cannot have an initializer");
1636-
1637-
// Adding local variable 'e' to work around a Clang warning
1638-
value_member_info e {cpp2::as_<std::string>(CPP2_UFCS_0(name, mo)), CPP2_UFCS_0(type, mo), cpp2::as_<std::string>(value)};
1639-
CPP2_UFCS(push_back, alternatives, e);
1640-
}
1632+
auto mo {CPP2_UFCS_0(as_object, m)};
1633+
CPP2_UFCS(require, mo, CPP2_UFCS_0(empty, CPP2_UFCS_0(initializer, mo)),
1634+
"a union alternative cannot have an initializer");
1635+
1636+
// Adding local variable 'e' to work around a Clang warning
1637+
value_member_info e {cpp2::as_<std::string>(CPP2_UFCS_0(name, mo)), CPP2_UFCS_0(type, mo), cpp2::as_<std::string>(value)};
1638+
CPP2_UFCS(push_back, alternatives, e);
1639+
1640+
CPP2_UFCS_0(mark_for_removal_from_enclosing_type, mo);
16411641
} while (false); ++value; }
16421642
}
16431643

@@ -1659,7 +1659,7 @@ auto value = 0;
16591659
#line 1115 "reflect.h2"
16601660
// 2. Replace: Erase the contents and replace with modified contents
16611661

1662-
CPP2_UFCS_0(remove_all_members, t);
1662+
CPP2_UFCS_0(remove_marked_members, t);
16631663
{
16641664
std::string storage = " _storage: std::aligned_storage_t<cpp2::max( ";
16651665

@@ -1686,21 +1686,21 @@ std::string comma = "";
16861686

16871687
// Provide discriminator
16881688
#line 1135 "reflect.h2"
1689-
CPP2_UFCS(add_member, t, " discriminator__: " + cpp2::to_string(std::move(discriminator_type)) + " = -1;\n");
1689+
CPP2_UFCS(add_member, t, " _discriminator: " + cpp2::to_string(std::move(discriminator_type)) + " = -1;\n");
16901690

16911691
// Add the alternatives: is_alternative, get_alternative, and set_alternative
16921692
for (
16931693
auto const& a : alternatives )
16941694
{
1695-
CPP2_UFCS(add_member, t, " is_" + cpp2::to_string(a.name) + ": (this) -> bool = discriminator__ == " + cpp2::to_string(a.value) + ";\n");
1695+
CPP2_UFCS(add_member, t, " is_" + cpp2::to_string(a.name) + ": (this) -> bool = _discriminator == " + cpp2::to_string(a.value) + ";\n");
16961696

1697-
CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (this) -> forward _ = reinterpret_cast<* const " + cpp2::to_string(a.type) + ">(_storage&)*;\n");
1697+
CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (this) -> forward " + cpp2::to_string(a.type) + " = reinterpret_cast<* const " + cpp2::to_string(a.type) + ">(_storage&)*;\n");
16981698

1699-
CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (inout this) -> forward _ = reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)*;\n");
1699+
CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (inout this) -> forward " + cpp2::to_string(a.type) + " = reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)*;\n");
17001700

1701-
CPP2_UFCS(add_member, t, " set_" + cpp2::to_string(a.name) + ": (inout this, value: " + cpp2::to_string(a.type) + ") = { if !is_" + cpp2::to_string(a.name) + "() { destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), value); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = value; } discriminator__ = " + cpp2::to_string(a.value) + "; }\n");
1701+
CPP2_UFCS(add_member, t, " set_" + cpp2::to_string(a.name) + ": (inout this, value: " + cpp2::to_string(a.type) + ") = { if !is_" + cpp2::to_string(a.name) + "() { destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), value); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = value; } _discriminator = " + cpp2::to_string(a.value) + "; }\n");
17021702

1703-
CPP2_UFCS(add_member, t, " set_" + cpp2::to_string(a.name) + ": (inout this, forward args...: _) = { if !is_" + cpp2::to_string(a.name) + "() { destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), args...); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = :" + cpp2::to_string(a.type) + " = (args...); } discriminator__ = " + cpp2::to_string(a.value) + "; }\n");
1703+
CPP2_UFCS(add_member, t, " set_" + cpp2::to_string(a.name) + ": (inout this, forward args...: _) = { if !is_" + cpp2::to_string(a.name) + "() { destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), args...); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = :" + cpp2::to_string(a.type) + " = (args...); } _discriminator = " + cpp2::to_string(a.value) + "; }\n");
17041704
}
17051705
{
17061706
std::string destroy = " private destroy: (inout this) = {\n";
@@ -1711,7 +1711,7 @@ std::string destroy = " private destroy: (inout this) = {\n";
17111711
{
17121712
for (
17131713
auto const& a : alternatives ) {
1714-
destroy += "if discriminator__ == " + cpp2::to_string(a.value) + " { std::destroy_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&) ); }\n";
1714+
destroy += "if _discriminator == " + cpp2::to_string(a.value) + " { std::destroy_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&) ); }\n";
17151715
}
17161716

17171717
destroy += "}\n";

source/reflect.h2

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,15 +1086,15 @@ union: (inout t : meta::type_declaration)
10861086
m.require( m.is_public() || m.is_default_access(),
10871087
"a union alternative cannot be protected or private");
10881088

1089-
if m.is_object() {
1090-
mo := m.as_object();
1091-
mo.require( mo.initializer().empty(),
1092-
"a union alternative cannot have an initializer");
1093-
1094-
// Adding local variable 'e' to work around a Clang warning
1095-
e: value_member_info = ( mo.name() as std::string, mo.type(), value as std::string );
1096-
alternatives.push_back( e );
1097-
}
1089+
mo := m.as_object();
1090+
mo.require( mo.initializer().empty(),
1091+
"a union alternative cannot have an initializer");
1092+
1093+
// Adding local variable 'e' to work around a Clang warning
1094+
e: value_member_info = ( mo.name() as std::string, mo.type(), value as std::string );
1095+
alternatives.push_back( e );
1096+
1097+
mo.mark_for_removal_from_enclosing_type();
10981098
}
10991099

11001100
discriminator_type: std::string = ();
@@ -1114,7 +1114,7 @@ union: (inout t : meta::type_declaration)
11141114

11151115
// 2. Replace: Erase the contents and replace with modified contents
11161116

1117-
t.remove_all_members();
1117+
t.remove_marked_members();
11181118

11191119
// Provide storage
11201120
(storage: std::string = " _storage: std::aligned_storage_t<cpp2::max( ")
@@ -1132,29 +1132,29 @@ union: (inout t : meta::type_declaration)
11321132
}
11331133

11341134
// Provide discriminator
1135-
t.add_member( " discriminator__: (discriminator_type)$ = -1;\n");
1135+
t.add_member( " _discriminator: (discriminator_type)$ = -1;\n");
11361136

11371137
// Add the alternatives: is_alternative, get_alternative, and set_alternative
11381138
for alternatives
11391139
do (a)
11401140
{
1141-
t.add_member( " is_(a.name)$: (this) -> bool = discriminator__ == (a.value)$;\n");
1141+
t.add_member( " is_(a.name)$: (this) -> bool = _discriminator == (a.value)$;\n");
11421142

1143-
t.add_member( " (a.name)$: (this) -> forward _ = reinterpret_cast<* const (a.type)$>(_storage&)*;\n");
1143+
t.add_member( " (a.name)$: (this) -> forward (a.type)$ = reinterpret_cast<* const (a.type)$>(_storage&)*;\n");
11441144

1145-
t.add_member( " (a.name)$: (inout this) -> forward _ = reinterpret_cast<*(a.type)$>(_storage&)*;\n");
1145+
t.add_member( " (a.name)$: (inout this) -> forward (a.type)$ = reinterpret_cast<*(a.type)$>(_storage&)*;\n");
11461146

1147-
t.add_member( " set_(a.name)$: (inout this, value: (a.type)$) = { if !is_(a.name)$() { destroy(); std::construct_at( reinterpret_cast<*(a.type)$>(_storage&), value); } else { reinterpret_cast<*(a.type)$>(_storage&)* = value; } discriminator__ = (a.value)$; }\n");
1147+
t.add_member( " set_(a.name)$: (inout this, value: (a.type)$) = { if !is_(a.name)$() { destroy(); std::construct_at( reinterpret_cast<*(a.type)$>(_storage&), value); } else { reinterpret_cast<*(a.type)$>(_storage&)* = value; } _discriminator = (a.value)$; }\n");
11481148

1149-
t.add_member( " set_(a.name)$: (inout this, forward args...: _) = { if !is_(a.name)$() { destroy(); std::construct_at( reinterpret_cast<*(a.type)$>(_storage&), args...); } else { reinterpret_cast<*(a.type)$>(_storage&)* = :(a.type)$ = (args...); } discriminator__ = (a.value)$; }\n");
1149+
t.add_member( " set_(a.name)$: (inout this, forward args...: _) = { if !is_(a.name)$() { destroy(); std::construct_at( reinterpret_cast<*(a.type)$>(_storage&), args...); } else { reinterpret_cast<*(a.type)$>(_storage&)* = :(a.type)$ = (args...); } _discriminator = (a.value)$; }\n");
11501150
}
11511151

11521152
// Add destroy
11531153
(destroy: std::string = " private destroy: (inout this) = {\n")
11541154
{
1155-
for alternatives
1155+
for alternatives
11561156
do (a) {
1157-
destroy += "if discriminator__ == (a.value)$ { std::destroy_at( reinterpret_cast<*(a.type)$>(_storage&) ); }\n";
1157+
destroy += "if _discriminator == (a.value)$ { std::destroy_at( reinterpret_cast<*(a.type)$>(_storage&) ); }\n";
11581158
}
11591159

11601160
destroy += "}\n";

0 commit comments

Comments
 (0)