Skip to content

Commit

Permalink
Add partial support for variadics (basic cases, only simple fold expr…
Browse files Browse the repository at this point in the history
…essions)
  • Loading branch information
hsutter committed Sep 12, 2023
1 parent c78058a commit f6ecbb4
Show file tree
Hide file tree
Showing 15 changed files with 148 additions and 17 deletions.
17 changes: 17 additions & 0 deletions regression-tests/pure2-variadics.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

x: <Ts...: type> type = {
tup: std::tuple<Ts...> = ();
}

make_string: <Args...: type> (forward args...: Args) -> _ = :std::string = args...;

make: <T, Args...: type> (forward args...: Args) -> _ = :T = args...;

main: ()
= {
a: x<int, long, std::string> = ();

std::cout << std::string("xyzzy", 3) << "\n";
std::cout << make_string("plugh", :u8=3) << "\n";
std::cout << make<std::string>("abracadabra", :u8=3) << "\n";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
xyz
plu
abr
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
xyz
plu
abr
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
xyz
plu
abr
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
xyz
plu
abr
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pure2-variadics.cpp
50 changes: 50 additions & 0 deletions regression-tests/test-results/pure2-variadics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

#define CPP2_USE_MODULES Yes

//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"


#line 2 "pure2-variadics.cpp2"
template<typename ...Ts> class x;


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


#line 2 "pure2-variadics.cpp2"
template<typename ...Ts> class x {
private: std::tuple<Ts...> tup {};
public: x() = default;
public: x(x const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(x const&) -> void = delete;

#line 4 "pure2-variadics.cpp2"
};

template<typename ...Args> [[nodiscard]] auto make_string(Args&& ...args) -> auto;

template<typename T, typename ...Args> [[nodiscard]] auto make(Args&& ...args) -> auto;

auto main() -> int;


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


#line 6 "pure2-variadics.cpp2"
template<typename ...Args> [[nodiscard]] auto make_string(Args&& ...args) -> auto { return std::string{CPP2_FORWARD(args)...}; }

template<typename T, typename ...Args> [[nodiscard]] auto make(Args&& ...args) -> auto { return T{CPP2_FORWARD(args)...}; }

auto main() -> int
{
x<int,long,std::string> a {};

std::cout << std::string("xyzzy", 3) << "\n";
std::cout << make_string("plugh", cpp2::u8{3}) << "\n";
std::cout << make<std::string>("abracadabra", cpp2::u8{3}) << "\n";
}

2 changes: 2 additions & 0 deletions regression-tests/test-results/pure2-variadics.cpp2.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pure2-variadics.cpp2... ok (all Cpp2, passes safety checks)

2 changes: 1 addition & 1 deletion regression-tests/test-results/version
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

cppfront compiler v0.2.1 Build 8911:1701
cppfront compiler v0.2.1 Build 8912:1051
Copyright(c) Herb Sutter All rights reserved

SPDX-License-Identifier: CC-BY-NC-ND-4.0
Expand Down
2 changes: 1 addition & 1 deletion source/build.info
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"8911:1701"
"8912:1051"
40 changes: 35 additions & 5 deletions source/cppfront.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2514,7 +2514,14 @@ class cppfront
emit(*type_id);
printer.print_cpp2("{", decl->position());

assert(decl->initializer);
if (!decl->initializer) {
errors.emplace_back(
decl->position(),
"an anonymous object declaration must have '=' and an initializer"
);
return;
}

emit(*decl->initializer, false);

printer.print_cpp2("}", decl->position());
Expand Down Expand Up @@ -3888,8 +3895,6 @@ class cppfront
)
{
pass = "&&";
//assert(emitting_move_that_function); // this should already have been set
////emitting_move_that_function = true;
}

auto func_name = get_enclosing_function_name();
Expand Down Expand Up @@ -3918,6 +3923,12 @@ class cppfront

if (n.declaration->is_type()) {
printer.print_cpp2("typename ", n.declaration->identifier->position());
if (n.declaration->is_variadic) {
printer.print_cpp2(
"...",
n.declaration->identifier->position()
);
}
assert (n.declaration->identifier);
emit(*n.declaration->identifier);
return;
Expand Down Expand Up @@ -3999,6 +4010,7 @@ class cppfront

if (
!is_returns
&& !n.declaration->is_variadic
&& !type_id.is_wildcard()
&& !is_dependent_parameter_type
&& !type_id.is_pointer_qualified()
Expand All @@ -4023,6 +4035,7 @@ class cppfront
else if (
type_id.is_wildcard()
|| is_dependent_parameter_type
|| n.declaration->is_variadic
)
{
auto name = std::string{"auto"};
Expand Down Expand Up @@ -4080,6 +4093,7 @@ class cppfront
&& !type_id.is_wildcard()
&& !is_dependent_parameter_type
&& !type_id.is_pointer_qualified()
&& !n.declaration->is_variadic
)
{
switch (n.pass) {
Expand All @@ -4097,7 +4111,23 @@ class cppfront
printer.print_extra( " " + identifier);
}
else {
printer.print_cpp2( " " + identifier, n.declaration->identifier->position());
printer.print_cpp2( " ", n.declaration->identifier->position());
if (n.declaration->is_variadic)
{
if (n.direction() == passing_style::out) {
errors.emplace_back(
n.declaration->position(),
"a variadic parameter cannot be 'out'"
);
return;
}

printer.print_cpp2(
"...",
n.declaration->identifier->position()
);
}
printer.print_cpp2( identifier, n.declaration->identifier->position());
}

if (
Expand Down Expand Up @@ -5167,7 +5197,7 @@ class cppfront
|| n.is_object()
|| (
n.is_function()
&& n.has_name() // only if it is not unnambed function aka lambda
&& n.has_name() // only if it is not unnamed function aka lambda
&& n.initializer // only if the function has a definition (is not abstract)
&& printer.get_phase() == printer.phase2_func_defs
)
Expand Down
39 changes: 29 additions & 10 deletions source/parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ auto is_prefix_operator(token const& tok)


//G postfix-operator:
//G one of '++' '--' '*' '&' '~' '$'
//G one of '++' '--' '*' '&' '~' '$' '...'
//G
auto is_postfix_operator(lexeme l)
-> bool
Expand All @@ -67,6 +67,7 @@ auto is_postfix_operator(lexeme l)
case lexeme::Ampersand:
case lexeme::Tilde:
case lexeme::Dollar:
case lexeme::Ellipsis:
return true;
break;default:
return false;
Expand Down Expand Up @@ -2346,11 +2347,11 @@ struct declaration_node
{
// The capture_group is declared first, because it should outlive
// any owned postfix_expressions that could refer to it
capture_group captures;

source_position pos;
capture_group captures;
source_position pos;
bool is_variadic = false;
std::unique_ptr<unqualified_id_node> identifier;
accessibility access = accessibility::default_;
accessibility access = accessibility::default_;

enum active : std::uint8_t { a_function, an_object, a_type, a_namespace, an_alias };
std::variant<
Expand Down Expand Up @@ -6224,7 +6225,7 @@ class parser
pos = start_pos; // backtrack
}
else {
error("expected , in parameter list", true, {}, true);
error("expected ',' in parameter list", true, {}, true);
}
return {};
}
Expand Down Expand Up @@ -6496,15 +6497,17 @@ class parser
bool is_parameter = false,
bool is_template_parameter = false,
std::unique_ptr<unqualified_id_node> id = {},
accessibility access = {}
accessibility access = {},
bool is_variadic = false
)
-> std::unique_ptr<declaration_node>
{
auto n = std::make_unique<declaration_node>( current_declarations.back() );
n->pos = start;

n->identifier = std::move(id);
n->access = access;
n->identifier = std::move(id);
n->access = access;
n->is_variadic = is_variadic;

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

auto is_variadic = false;
if (curr().type() == lexeme::Ellipsis) {
is_variadic = true;
next();
}

// Provide some useful Cpp1->Cpp2 migration diagnostics for common mistakes
//
if (
Expand Down Expand Up @@ -7232,6 +7241,14 @@ class parser
return {};
}

if (is_variadic) {
errors.emplace_back(
curr().position(),
"an alias declaration may not be variadic"
);
return {};
}

n->pos = start_pos;
n->identifier = std::move(id);
n->access = access;
Expand All @@ -7247,7 +7264,8 @@ class parser
is_parameter,
is_template_parameter,
std::move(id),
access
access,
is_variadic
);
if (!n) {
pos = start_pos; // backtrack
Expand Down Expand Up @@ -7539,6 +7557,7 @@ class parse_tree_printer : printing_visitor
{
o << pre(indent) << "declaration [" << &n << "]\n";
o << pre(indent+1) << "parent: [" << n.parent_declaration << "]\n";
o << pre(indent+1) << "is_variadic: [" << std::boolalpha << n.is_variadic << "]\n";
switch (n.type.index()) {
break;case declaration_node::a_function:
o << pre(indent+1) << "function\n";
Expand Down

0 comments on commit f6ecbb4

Please sign in to comment.