Skip to content

Commit f6ecbb4

Browse files
committed
Add partial support for variadics (basic cases, only simple fold expressions)
1 parent c78058a commit f6ecbb4

15 files changed

+148
-17
lines changed

regression-tests/pure2-variadics.cpp2

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
x: <Ts...: type> type = {
3+
tup: std::tuple<Ts...> = ();
4+
}
5+
6+
make_string: <Args...: type> (forward args...: Args) -> _ = :std::string = args...;
7+
8+
make: <T, Args...: type> (forward args...: Args) -> _ = :T = args...;
9+
10+
main: ()
11+
= {
12+
a: x<int, long, std::string> = ();
13+
14+
std::cout << std::string("xyzzy", 3) << "\n";
15+
std::cout << make_string("plugh", :u8=3) << "\n";
16+
std::cout << make<std::string>("abracadabra", :u8=3) << "\n";
17+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
xyz
2+
plu
3+
abr

regression-tests/test-results/clang-12/pure2-variadics.cpp.output

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
xyz
2+
plu
3+
abr

regression-tests/test-results/gcc-10/pure2-variadics.cpp.output

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
xyz
2+
plu
3+
abr

regression-tests/test-results/gcc-13/pure2-variadics.cpp.output

Whitespace-only changes.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
xyz
2+
plu
3+
abr
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pure2-variadics.cpp
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
#define CPP2_USE_MODULES Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
10+
#line 2 "pure2-variadics.cpp2"
11+
template<typename ...Ts> class x;
12+
13+
14+
//=== Cpp2 type definitions and function declarations ===========================
15+
16+
17+
#line 2 "pure2-variadics.cpp2"
18+
template<typename ...Ts> class x {
19+
private: std::tuple<Ts...> tup {};
20+
public: x() = default;
21+
public: x(x const&) = delete; /* No 'that' constructor, suppress copy */
22+
public: auto operator=(x const&) -> void = delete;
23+
24+
#line 4 "pure2-variadics.cpp2"
25+
};
26+
27+
template<typename ...Args> [[nodiscard]] auto make_string(Args&& ...args) -> auto;
28+
29+
template<typename T, typename ...Args> [[nodiscard]] auto make(Args&& ...args) -> auto;
30+
31+
auto main() -> int;
32+
33+
34+
//=== Cpp2 function definitions =================================================
35+
36+
37+
#line 6 "pure2-variadics.cpp2"
38+
template<typename ...Args> [[nodiscard]] auto make_string(Args&& ...args) -> auto { return std::string{CPP2_FORWARD(args)...}; }
39+
40+
template<typename T, typename ...Args> [[nodiscard]] auto make(Args&& ...args) -> auto { return T{CPP2_FORWARD(args)...}; }
41+
42+
auto main() -> int
43+
{
44+
x<int,long,std::string> a {};
45+
46+
std::cout << std::string("xyzzy", 3) << "\n";
47+
std::cout << make_string("plugh", cpp2::u8{3}) << "\n";
48+
std::cout << make<std::string>("abracadabra", cpp2::u8{3}) << "\n";
49+
}
50+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-variadics.cpp2... ok (all Cpp2, passes safety checks)
2+

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 8911:1701
2+
cppfront compiler v0.2.1 Build 8912:1051
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-
"8911:1701"
1+
"8912:1051"

source/cppfront.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2514,7 +2514,14 @@ class cppfront
25142514
emit(*type_id);
25152515
printer.print_cpp2("{", decl->position());
25162516

2517-
assert(decl->initializer);
2517+
if (!decl->initializer) {
2518+
errors.emplace_back(
2519+
decl->position(),
2520+
"an anonymous object declaration must have '=' and an initializer"
2521+
);
2522+
return;
2523+
}
2524+
25182525
emit(*decl->initializer, false);
25192526

25202527
printer.print_cpp2("}", decl->position());
@@ -3888,8 +3895,6 @@ class cppfront
38883895
)
38893896
{
38903897
pass = "&&";
3891-
//assert(emitting_move_that_function); // this should already have been set
3892-
////emitting_move_that_function = true;
38933898
}
38943899

38953900
auto func_name = get_enclosing_function_name();
@@ -3918,6 +3923,12 @@ class cppfront
39183923

39193924
if (n.declaration->is_type()) {
39203925
printer.print_cpp2("typename ", n.declaration->identifier->position());
3926+
if (n.declaration->is_variadic) {
3927+
printer.print_cpp2(
3928+
"...",
3929+
n.declaration->identifier->position()
3930+
);
3931+
}
39213932
assert (n.declaration->identifier);
39223933
emit(*n.declaration->identifier);
39233934
return;
@@ -3999,6 +4010,7 @@ class cppfront
39994010

40004011
if (
40014012
!is_returns
4013+
&& !n.declaration->is_variadic
40024014
&& !type_id.is_wildcard()
40034015
&& !is_dependent_parameter_type
40044016
&& !type_id.is_pointer_qualified()
@@ -4023,6 +4035,7 @@ class cppfront
40234035
else if (
40244036
type_id.is_wildcard()
40254037
|| is_dependent_parameter_type
4038+
|| n.declaration->is_variadic
40264039
)
40274040
{
40284041
auto name = std::string{"auto"};
@@ -4080,6 +4093,7 @@ class cppfront
40804093
&& !type_id.is_wildcard()
40814094
&& !is_dependent_parameter_type
40824095
&& !type_id.is_pointer_qualified()
4096+
&& !n.declaration->is_variadic
40834097
)
40844098
{
40854099
switch (n.pass) {
@@ -4097,7 +4111,23 @@ class cppfront
40974111
printer.print_extra( " " + identifier);
40984112
}
40994113
else {
4100-
printer.print_cpp2( " " + identifier, n.declaration->identifier->position());
4114+
printer.print_cpp2( " ", n.declaration->identifier->position());
4115+
if (n.declaration->is_variadic)
4116+
{
4117+
if (n.direction() == passing_style::out) {
4118+
errors.emplace_back(
4119+
n.declaration->position(),
4120+
"a variadic parameter cannot be 'out'"
4121+
);
4122+
return;
4123+
}
4124+
4125+
printer.print_cpp2(
4126+
"...",
4127+
n.declaration->identifier->position()
4128+
);
4129+
}
4130+
printer.print_cpp2( identifier, n.declaration->identifier->position());
41014131
}
41024132

41034133
if (
@@ -5167,7 +5197,7 @@ class cppfront
51675197
|| n.is_object()
51685198
|| (
51695199
n.is_function()
5170-
&& n.has_name() // only if it is not unnambed function aka lambda
5200+
&& n.has_name() // only if it is not unnamed function aka lambda
51715201
&& n.initializer // only if the function has a definition (is not abstract)
51725202
&& printer.get_phase() == printer.phase2_func_defs
51735203
)

source/parse.h

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ auto is_prefix_operator(token const& tok)
5555

5656

5757
//G postfix-operator:
58-
//G one of '++' '--' '*' '&' '~' '$'
58+
//G one of '++' '--' '*' '&' '~' '$' '...'
5959
//G
6060
auto is_postfix_operator(lexeme l)
6161
-> bool
@@ -67,6 +67,7 @@ auto is_postfix_operator(lexeme l)
6767
case lexeme::Ampersand:
6868
case lexeme::Tilde:
6969
case lexeme::Dollar:
70+
case lexeme::Ellipsis:
7071
return true;
7172
break;default:
7273
return false;
@@ -2346,11 +2347,11 @@ struct declaration_node
23462347
{
23472348
// The capture_group is declared first, because it should outlive
23482349
// any owned postfix_expressions that could refer to it
2349-
capture_group captures;
2350-
2351-
source_position pos;
2350+
capture_group captures;
2351+
source_position pos;
2352+
bool is_variadic = false;
23522353
std::unique_ptr<unqualified_id_node> identifier;
2353-
accessibility access = accessibility::default_;
2354+
accessibility access = accessibility::default_;
23542355

23552356
enum active : std::uint8_t { a_function, an_object, a_type, a_namespace, an_alias };
23562357
std::variant<
@@ -6224,7 +6225,7 @@ class parser
62246225
pos = start_pos; // backtrack
62256226
}
62266227
else {
6227-
error("expected , in parameter list", true, {}, true);
6228+
error("expected ',' in parameter list", true, {}, true);
62286229
}
62296230
return {};
62306231
}
@@ -6496,15 +6497,17 @@ class parser
64966497
bool is_parameter = false,
64976498
bool is_template_parameter = false,
64986499
std::unique_ptr<unqualified_id_node> id = {},
6499-
accessibility access = {}
6500+
accessibility access = {},
6501+
bool is_variadic = false
65006502
)
65016503
-> std::unique_ptr<declaration_node>
65026504
{
65036505
auto n = std::make_unique<declaration_node>( current_declarations.back() );
65046506
n->pos = start;
65056507

6506-
n->identifier = std::move(id);
6507-
n->access = access;
6508+
n->identifier = std::move(id);
6509+
n->access = access;
6510+
n->is_variadic = is_variadic;
65086511

65096512
// If we're in a type scope and the next token is ';', treat this as if
65106513
// ': _;' without an initializer.
@@ -7164,6 +7167,12 @@ class parser
71647167
return {};
71657168
}
71667169

7170+
auto is_variadic = false;
7171+
if (curr().type() == lexeme::Ellipsis) {
7172+
is_variadic = true;
7173+
next();
7174+
}
7175+
71677176
// Provide some useful Cpp1->Cpp2 migration diagnostics for common mistakes
71687177
//
71697178
if (
@@ -7232,6 +7241,14 @@ class parser
72327241
return {};
72337242
}
72347243

7244+
if (is_variadic) {
7245+
errors.emplace_back(
7246+
curr().position(),
7247+
"an alias declaration may not be variadic"
7248+
);
7249+
return {};
7250+
}
7251+
72357252
n->pos = start_pos;
72367253
n->identifier = std::move(id);
72377254
n->access = access;
@@ -7247,7 +7264,8 @@ class parser
72477264
is_parameter,
72487265
is_template_parameter,
72497266
std::move(id),
7250-
access
7267+
access,
7268+
is_variadic
72517269
);
72527270
if (!n) {
72537271
pos = start_pos; // backtrack
@@ -7539,6 +7557,7 @@ class parse_tree_printer : printing_visitor
75397557
{
75407558
o << pre(indent) << "declaration [" << &n << "]\n";
75417559
o << pre(indent+1) << "parent: [" << n.parent_declaration << "]\n";
7560+
o << pre(indent+1) << "is_variadic: [" << std::boolalpha << n.is_variadic << "]\n";
75427561
switch (n.type.index()) {
75437562
break;case declaration_node::a_function:
75447563
o << pre(indent+1) << "function\n";

0 commit comments

Comments
 (0)