Skip to content

Commit 63efa6e

Browse files
committed
Added type and namespace alias declarations, closes #273
An alias can be to a namespace, type, function, or object. Aliases are always a non-mutable view of the original entity. This is natural for namespace and type and function aliases, since those kinds of entited can't be mutated, but it bears calling out for an object alias which behaves as `auto const&`. The current syntax is like non-alias declarations, but with `==` to connote equality with an existing entity, instead of `=` which connotes setting the new entity's value. For example: lit: namespace == ::std::literals; pmr_vec: <T> type == std::vector<T, std::pmr::polymorphic_allocator<T>>; func :== some_original::inconvenient::function_name; vec :== my_vector; // note: const&, aliases are never mutable Note: Function aliases are subsumed under the object case, so you can't declare a function alias with an explicit signature. Rationale: - if there's no need for a (repetitive) explicit signature, the object case covers it - if the parameters/returns must be exact (no conversions), a pointer to function covers it - if parameter/return conversions are allowed, std::function covers it But if we do learn about a reason to add support for function aliases having an explicit signature, and possibly with conversions to/from the parameter/return types, they'll be a natural fit here.
1 parent feff640 commit 63efa6e

12 files changed

+465
-7
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
N: namespace = {
3+
pmr_vec: <T> type == std::vector<T, std::pmr::polymorphic_allocator<T>>;
4+
}
5+
6+
N1: namespace == N;
7+
8+
myclass: type = {
9+
// Default to public
10+
str: type == std::string;
11+
12+
private str2: type == std::string;
13+
}
14+
15+
N3: namespace == ::std::literals;
16+
17+
myfunc: () = {
18+
v: N1::pmr_vec<myclass::str> = ("xyzzy", "plugh");
19+
20+
v2 :== v;
21+
22+
for v2 do :(s) =
23+
std::cout << "(s)$\n";
24+
}
25+
26+
main: () = {
27+
view: type == std::string_view;
28+
N4: namespace == std::literals;
29+
30+
myfunc2 :== myfunc;
31+
myfunc2();
32+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
xyzzy
2+
plugh

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

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
xyzzy
2+
plugh

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

Whitespace-only changes.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
xyzzy
2+
plugh
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pure2-type-and-namespace-aliases.cpp
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
2+
#define CPP2_USE_MODULES Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
10+
#line 2 "pure2-type-and-namespace-aliases.cpp2"
11+
namespace N {
12+
13+
}
14+
15+
#line 8 "pure2-type-and-namespace-aliases.cpp2"
16+
class myclass;
17+
18+
//=== Cpp2 type definitions and function declarations ===========================
19+
20+
21+
#line 2 "pure2-type-and-namespace-aliases.cpp2"
22+
namespace N {
23+
template<typename T> using pmr_vec = std::vector<T,std::pmr::polymorphic_allocator<T>>;
24+
}
25+
26+
namespace N1 = N;
27+
28+
class myclass {
29+
// Default to public
30+
public: using str = std::string;
31+
32+
private: using str2 = std::string;
33+
};
34+
35+
namespace N3 = ::std::literals;
36+
37+
auto myfunc() -> void;
38+
39+
#line 26 "pure2-type-and-namespace-aliases.cpp2"
40+
auto main() -> int;
41+
42+
//=== Cpp2 function definitions =================================================
43+
44+
45+
#line 2 "pure2-type-and-namespace-aliases.cpp2"
46+
namespace N {
47+
48+
}
49+
50+
#line 17 "pure2-type-and-namespace-aliases.cpp2"
51+
auto myfunc() -> void{
52+
N1::pmr_vec<myclass::str> v {"xyzzy", "plugh"};
53+
54+
auto const& v2 = std::move(v);
55+
56+
for ( auto const& cpp2_range = v2; auto const& s : cpp2_range )
57+
std::cout << cpp2::to_string(s) + "\n";
58+
}
59+
60+
auto main() -> int{
61+
using view = std::string_view;
62+
namespace N4 = std::literals;
63+
64+
auto const& myfunc2 = myfunc;
65+
myfunc2();
66+
}
67+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-type-and-namespace-aliases.cpp2... ok (all Cpp2, passes safety checks)
2+

source/cppfront.cpp

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2439,6 +2439,16 @@ class cppfront
24392439
return false;
24402440
}
24412441

2442+
auto is_pointer_declaration(
2443+
alias_node const*,
2444+
int,
2445+
int
2446+
)
2447+
-> bool
2448+
{
2449+
return false;
2450+
}
2451+
24422452
auto is_pointer_declaration(
24432453
declaration_sym const* decl,
24442454
int deref_cnt,
@@ -4423,6 +4433,7 @@ class cppfront
44234433
-> void
44244434
{
44254435
// In phase 0, only need to consider namespaces and types
4436+
44264437
if (
44274438
printer.get_phase() == printer.phase0_type_decls
44284439
&& !n.is_namespace()
@@ -4432,6 +4443,109 @@ class cppfront
44324443
return;
44334444
}
44344445

4446+
4447+
// Handle aliases
4448+
4449+
if (n.is_alias())
4450+
{
4451+
auto& a = std::get<declaration_node::an_alias>(n.type);
4452+
assert(a);
4453+
4454+
// Non-local aliases are emitted in phase 1, locals in phase 2
4455+
if (
4456+
(
4457+
!n.parent_is_function()
4458+
&& printer.get_phase() == printer.phase1_type_defs_func_decls
4459+
)
4460+
||
4461+
(
4462+
n.parent_is_function()
4463+
&& printer.get_phase() == printer.phase2_func_defs
4464+
)
4465+
)
4466+
{
4467+
assert(
4468+
a->is_type_alias()
4469+
|| a->is_namespace_alias()
4470+
|| a->is_object_alias()
4471+
);
4472+
4473+
// If we're in a type scope, handle the access specifier
4474+
if (n.parent_is_type()) {
4475+
if (n.access) {
4476+
printer.print_cpp2(n.access->to_string(true) + ": ", n.access->position());
4477+
}
4478+
else {
4479+
printer.print_cpp2("public: ", n.position());
4480+
}
4481+
}
4482+
4483+
// Emit template parameters if any
4484+
if (n.template_parameters) {
4485+
printer.print_cpp2("template", n.position());
4486+
emit(*n.template_parameters, false, true);
4487+
printer.print_cpp2(" ", n.position());
4488+
}
4489+
4490+
// Handle type aliases
4491+
if (a->is_type_alias()) {
4492+
printer.print_cpp2(
4493+
"using "
4494+
+ print_to_string(*n.identifier)
4495+
+ " = "
4496+
+ print_to_string( *std::get<alias_node::a_type>(a->initializer) )
4497+
+ ";\n",
4498+
n.position()
4499+
);
4500+
}
4501+
4502+
// Handle namespace aliases
4503+
else if (a->is_namespace_alias()) {
4504+
auto initializer = std::string{};
4505+
if (auto qid = std::get_if<alias_node::a_namespace_qualified>(&a->initializer)) {
4506+
assert(*qid);
4507+
initializer = print_to_string(**qid);
4508+
}
4509+
else if (auto uid = std::get_if<alias_node::a_namespace_unqualified>(&a->initializer)) {
4510+
assert(*uid);
4511+
initializer = print_to_string(**uid);
4512+
}
4513+
else {
4514+
assert(!"ICE: should be unreachable - invalid namespace alias initializer");
4515+
}
4516+
printer.print_cpp2(
4517+
"namespace "
4518+
+ print_to_string(*n.identifier)
4519+
+ " = "
4520+
+ initializer
4521+
+ ";\n",
4522+
n.position()
4523+
);
4524+
}
4525+
4526+
// Handle object aliases
4527+
else if (a->is_object_alias()) {
4528+
printer.print_cpp2(
4529+
"auto const& "
4530+
+ print_to_string(*n.identifier)
4531+
+ " = "
4532+
+ print_to_string( *std::get<alias_node::an_object>(a->initializer) )
4533+
+ ";\n",
4534+
n.position()
4535+
);
4536+
}
4537+
4538+
else {
4539+
assert(!"ICE: should be unreachable - invalid alias");
4540+
}
4541+
4542+
return;
4543+
}
4544+
}
4545+
4546+
4547+
// Handle other declarations
4548+
44354549
auto need_to_generate_assignment = false;
44364550
auto need_to_generate_move = false;
44374551

0 commit comments

Comments
 (0)