Skip to content

Commit 68fdc0e

Browse files
committed
Unify using syntax
I had been using the Cpp1 syntax since I had nothing substantially better. But that did leave the grammar divergence between using std::vector; // use one thing from std using namespace std; // use everything in std But then I remembered the `_` wildcard, so with this change instead of `using namespace NNN ;` we write `using NNN::_ ;`. This makes them more consistent: using std::vector ; // use one thing from std using std::_ ; // use everything in std Of course the latter still lowers to Cpp1 `using namespace std;`
1 parent d1b50a3 commit 68fdc0e

12 files changed

+54
-32
lines changed

docs/cpp2/declarations.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ chr : namespace == std::chrono;
208208
chrlit : namespace == std::chrono_literals;
209209

210210
main: () = {
211-
using namespace chrlit;
211+
using chrlit::_ ;
212212

213213
// The next two lines are equivalent
214214
std::cout << "1s is (std::chrono::nanoseconds(1s).count())$ns\n";

docs/cpp2/namespaces.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ main: () = {
2020

2121
## <a id="using"></a> `using`
2222

23-
A `#!cpp using` statement brings names declared in another namespace into the current scope as if they had been declared in the current scope. It has two forms:
23+
A `#!cpp using` statement brings names declared in another namespace into the current scope as if they had been declared in the current scope.
2424

25-
- `#!cpp using a_namespace::a_name;` brings the single name `a_name` into scope.
25+
`#!cpp using a_namespace::a_name ;` brings the single name `a_name` into scope.
2626

27-
- `#!cpp using namespace a_namespace;` brings all the namespace's names into scope.
27+
`#!cpp using a_namespace::_ ;` brings all the namespace's names into scope using the `#!cpp _` wildcard.
2828

2929
For example:
3030

@@ -40,15 +40,15 @@ main: () = {
4040
w: widgetlib::widget = /*...*/;
4141

4242
{
43-
// Using the name, no qualification needed
43+
// Using the specific name, no widgetlib:: qualification needed
4444
using widgetlib::widget;
4545
w2: widget = /*...*/;
4646
// ...
4747
}
4848

4949
{
50-
// Using the whole namespace, no qualification needed
51-
using namespace widgetlib;
50+
// Using the whole namespace, no widgetlib:: qualification needed
51+
using widgetlib::_;
5252
w3: widget = /*...*/;
5353
// ...
5454
}

regression-tests/mixed-bugfix-for-literal-as-nttp.cpp2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#include <chrono>
2-
using namespace std::chrono_literals;
32
main: () = {
3+
using std::chrono_literals::_ ;
44
assert( 10 as i32 == 10 );
55
assert( 10LL as i32 == 10 );
66
assert( 10s as std::chrono::seconds == 10s );

regression-tests/pure2-print.cpp2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ outer: @print type = {
1212
protected f: () -> int = 42;
1313

1414
g: (virtual this, i:int) -> int = {
15-
using namespace ::std;
15+
using ::std::_ ;
1616

1717
s := "string literal";
1818
ret: int = i;

regression-tests/test-results/gcc-10-c++20/mixed-type-safety-1.cpp.output

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/usr/bin/ld: /tmp/ccSlwpC6.o: in function `main':
1+
/usr/bin/ld: /tmp/ccoR2zYT.o: in function `main':
22
mixed-type-safety-1.cpp:(.text+0x327): undefined reference to `void print<std::integral_constant<bool, false> >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::integral_constant<bool, false> const&)'
33
/usr/bin/ld: mixed-type-safety-1.cpp:(.text+0x388): undefined reference to `void print<std::integral_constant<bool, true> >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::integral_constant<bool, true> const&)'
44
/usr/bin/ld: mixed-type-safety-1.cpp:(.text+0x422): undefined reference to `void print<std::integral_constant<bool, true> >(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::integral_constant<bool, true> const&)'

regression-tests/test-results/mixed-bugfix-for-literal-as-nttp.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212

1313
#line 1 "mixed-bugfix-for-literal-as-nttp.cpp2"
1414
#include <chrono>
15-
using namespace std::chrono_literals;
1615
auto main() -> int;
1716

1817
//=== Cpp2 function definitions =================================================
1918

2019
#line 1 "mixed-bugfix-for-literal-as-nttp.cpp2"
2120

22-
#line 3 "mixed-bugfix-for-literal-as-nttp.cpp2"
21+
#line 2 "mixed-bugfix-for-literal-as-nttp.cpp2"
2322
auto main() -> int{
23+
using namespace std::chrono_literals;
2424
if (cpp2::cpp2_default.is_active() && !(cpp2::impl::as_<cpp2::i32, 10>() == 10) ) { cpp2::cpp2_default.report_violation(""); }
2525
if (cpp2::cpp2_default.is_active() && !(cpp2::impl::as_<cpp2::i32, 10LL>() == 10) ) { cpp2::cpp2_default.report_violation(""); }
2626
if (cpp2::cpp2_default.is_active() && !(cpp2::impl::as_<std::chrono::seconds>(10s) == 10s) ) { cpp2::cpp2_default.report_violation(""); }

regression-tests/test-results/msvc-2022-c++latest/pure2-type-safety-1.cpp.output

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pure2-type-safety-1.cpp
22
pure2-type-safety-1.cpp2(26): error C2666: 'print': overloaded functions have similar conversions
33
pure2-type-safety-1.cpp2(29): note: could be 'void print(const std::string &,const bool)'
4-
C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\MSVC\14.40.33807\include\print(125): note: or 'void std::print<std::false_type>(const std::basic_format_string<char,std::integral_constant<bool,false>>,std::false_type &&)' [found using argument-dependent lookup]
4+
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\print(125): note: or 'void std::print<std::false_type>(const std::basic_format_string<char,std::integral_constant<bool,false>>,std::false_type &&)' [found using argument-dependent lookup]
55
pure2-type-safety-1.cpp2(26): note: while trying to match the argument list '(std::basic_string<char,std::char_traits<char>,std::allocator<char>>, std::false_type)'
66
pure2-type-safety-1.cpp2(26): note: the template instantiation context (the oldest one first) is
77
pure2-type-safety-1.cpp2(8): note: see reference to function template instantiation 'void test_generic<double,char[7]>(const _T0 &,const _T1 (&))' being compiled

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.7.3 Build 9817:1821
2+
cppfront compiler v0.7.3 Build 9821:0915
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-
"9817:1821"
1+
"9821:0915"

source/parse.h

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2107,9 +2107,15 @@ struct jump_statement_node
21072107
struct using_statement_node
21082108
{
21092109
token const* keyword = {};
2110-
bool for_namespace = false;
21112110
std::unique_ptr<id_expression_node> id;
21122111

2112+
auto for_namespace() const
2113+
-> bool
2114+
{
2115+
assert(id);
2116+
return id->to_string().ends_with("::_");
2117+
}
2118+
21132119
auto position() const
21142120
-> source_position
21152121
{
@@ -5183,11 +5189,16 @@ auto pretty_print_visualize(using_statement_node const& n, int indent)
51835189

51845190
auto ret = std::string{"\n"} + pre(indent) + n.keyword->as_string_view() + " ";
51855191

5186-
if (n.for_namespace) {
5192+
if (n.for_namespace()) {
51875193
ret += "namespace ";
51885194
}
51895195

51905196
ret += pretty_print_visualize(*n.id, indent);
5197+
if (n.for_namespace()) {
5198+
assert(ret.ends_with("::_"));
5199+
ret.resize( ret.size() - 3 ); // maybe someday: ret.remove_suffix(3)
5200+
}
5201+
51915202
if (ret.back() != ';') {
51925203
ret += ";";
51935204
}
@@ -7705,7 +7716,7 @@ class parser
77057716

77067717
//G using-statement:
77077718
//G 'using' qualified-id ';'
7708-
//G 'using' 'namespace' id-expression ';'
7719+
//G 'using' id-expression '::' '_' ';'
77097720
//G
77107721
auto using_statement()
77117722
-> std::unique_ptr<using_statement_node>
@@ -7715,26 +7726,31 @@ class parser
77157726
if (curr() != "using") {
77167727
return {};
77177728
}
7718-
n->keyword = &curr();
7719-
next();
77207729

7721-
if (curr() == "namespace") {
7722-
n->for_namespace = true;
7723-
next();
7730+
if (
7731+
peek(1)
7732+
&& *peek(1) == "namespace"
7733+
)
7734+
{
7735+
error("in Cpp2, write 'using the_namespace_name::_' to bring all names in the namespace into scope using the '_' wildcard");
7736+
return {};
77247737
}
77257738

7739+
n->keyword = &curr();
7740+
next();
7741+
77267742
auto id = id_expression();
77277743
if (!id) {
7728-
error(std::string{"expected valid id-expression after 'using"} + (n->for_namespace ? " namespace" : "") + "'");
7744+
error(std::string{"expected valid id-expression after 'using"} + (n->for_namespace() ? " namespace" : "") + "'");
77297745
return {};
77307746
}
7731-
if (!n->for_namespace && !id->is_qualified()) {
7732-
error("'using' for a specific name (not 'using namespace') must specify a qualified name", false);
7747+
n->id = std::move(id);
7748+
7749+
if (!n->for_namespace() && !n->id->is_qualified()) {
7750+
error("'using' must specify a qualified name", false);
77337751
return {};
77347752
}
77357753

7736-
n->id = std::move(id);
7737-
77387754
if (curr().type() != lexeme::Semicolon) {
77397755
error("expected ; at end of using-statement");
77407756
return {};
@@ -9647,7 +9663,7 @@ class parse_tree_printer : printing_visitor
96479663

96489664
auto start(using_statement_node const& n, int indent) -> void
96499665
{
9650-
o << pre(indent) << "using" << (n.for_namespace? " namespace" : "") << "\n";
9666+
o << pre(indent) << "using" << (n.for_namespace()? " namespace" : "") << "\n";
96519667
}
96529668

96539669
auto start(inspect_expression_node const& n, int indent) -> void

source/sema.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2713,7 +2713,7 @@ class sema
27132713
auto start(using_statement_node const& n, int) -> void
27142714
{
27152715
if (auto id = get_if<id_expression_node::qualified>(&n.id->id);
2716-
!n.for_namespace
2716+
!n.for_namespace()
27172717
&& id
27182718
)
27192719
{

source/to_cpp1.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2591,13 +2591,19 @@ class cppfront
25912591
assert(n.keyword);
25922592
emit(*n.keyword);
25932593

2594-
if (n.for_namespace) {
2594+
if (n.for_namespace()) {
25952595
printer.print_cpp2(" namespace", n.position());
25962596
} else {
25972597
current_names.push_back(active_using_declaration{n});
25982598
}
25992599

2600-
printer.print_cpp2(" " + print_to_string(*n.id) + ";", n.position());
2600+
auto id = print_to_string(*n.id);
2601+
if (n.for_namespace()) {
2602+
assert(id.ends_with("::_"));
2603+
id.resize( id.size() - 3 ); // maybe someday: id.remove_suffix(3)
2604+
}
2605+
2606+
printer.print_cpp2(" " + id + ";", n.position());
26012607
}
26022608

26032609

0 commit comments

Comments
 (0)