Skip to content

Commit 4d9d52d

Browse files
committed
Add support for fixed-width integer type aliases (i32, u64, etc.)
Note these are not reserved words, because that would conflict with existing code. Unqualified `i32` means `cpp2::i32`, but it's fine a program to have its own `i32` identifier and use it via namespace-qualification disambiguation. The naming pattern is: - `u` or `i` (unsigned or signed) - `8`, `16`, `32`, or `64` (bit width... I'm open to adding more as they can be portably supported) - (optional) `_fast` or `_small` (following `<cstdint>`'s `_fast` and `_least`)
1 parent 966856f commit 4d9d52d

13 files changed

+142
-9
lines changed

include/cpp2util.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@
207207
#include <cstddef>
208208
#include <utility>
209209
#include <cstdio>
210+
#include <cstdint>
210211

211212
#if defined(CPP2_USE_SOURCE_LOCATION)
212213
#include <source_location>
@@ -220,6 +221,43 @@
220221

221222
namespace cpp2 {
222223

224+
//-----------------------------------------------------------------------
225+
//
226+
// Convenience names for fixed-width integer types
227+
//
228+
// Note: De jure, some of these are optional per the C and C++ standards
229+
// De facto, all of these are supported in all implementations I know of
230+
//
231+
//-----------------------------------------------------------------------
232+
//
233+
using i8 = std::int8_t ;
234+
using i16 = std::int16_t ;
235+
using i32 = std::int32_t ;
236+
using i64 = std::int64_t ;
237+
using u8 = std::uint8_t ;
238+
using u16 = std::uint16_t ;
239+
using u32 = std::uint32_t ;
240+
using u64 = std::uint64_t ;
241+
242+
using i8_fast = std::int_fast8_t ;
243+
using i16_fast = std::int_fast16_t ;
244+
using i32_fast = std::int_fast32_t ;
245+
using i64_fast = std::int_fast64_t ;
246+
using u8_fast = std::uint_fast8_t ;
247+
using u16_fast = std::uint_fast16_t ;
248+
using u32_fast = std::uint_fast32_t ;
249+
using u64_fast = std::uint_fast64_t ;
250+
251+
using i8_small = std::int_least8_t ;
252+
using i16_small = std::int_least16_t ;
253+
using i32_small = std::int_least32_t ;
254+
using i64_small = std::int_least64_t ;
255+
using u8_small = std::uint_least8_t ;
256+
using u16_small = std::uint_least16_t;
257+
using u32_small = std::uint_least32_t;
258+
using u64_small = std::uint_least64_t;
259+
260+
223261
//-----------------------------------------------------------------------
224262
//
225263
// contract_group
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <typeinfo>
2+
#include <iostream>
3+
4+
namespace my {
5+
using u16 = float;
6+
}
7+
8+
test: (x:_) = {
9+
std::cout
10+
<< std::boolalpha
11+
<< std::is_floating_point_v<CPP2_TYPEOF(x)>
12+
<< "\n";
13+
}
14+
15+
main: (argc: int, argv: **char) -> int = {
16+
y: my::u16 = 42;
17+
test(y);
18+
19+
z: u16 = 42;
20+
test(z);
21+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
true
2+
false

regression-tests/test-results/clang-12/mixed-fixed-type-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+
true
2+
false

regression-tests/test-results/gcc-10/mixed-fixed-type-aliases.cpp.output

Whitespace-only changes.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// ----- Cpp2 support -----
2+
#include "cpp2util.h"
3+
4+
#line 1 "mixed-fixed-type-aliases.cpp2"
5+
#include <typeinfo>
6+
#include <iostream>
7+
8+
namespace my {
9+
using u16 = float;
10+
}
11+
12+
auto test(auto const& x) -> void;
13+
#line 15 "mixed-fixed-type-aliases.cpp2"
14+
[[nodiscard]] auto main(cpp2::in<int> argc, cpp2::in<char**> argv) -> int;
15+
16+
//=== Cpp2 definitions ==========================================================
17+
18+
#line 7 "mixed-fixed-type-aliases.cpp2"
19+
20+
auto test(auto const& x) -> void{
21+
std::cout
22+
<< std::boolalpha
23+
<< std::is_floating_point_v<CPP2_TYPEOF(x)>
24+
<< "\n";
25+
}
26+
27+
[[nodiscard]] auto main(cpp2::in<int> argc, cpp2::in<char**> argv) -> int{
28+
my::u16 y { 42 };
29+
test(std::move(y));
30+
31+
cpp2::u16 z { 42 };
32+
test(std::move(z));
33+
}
34+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
mixed-fixed-type-aliases.cpp2... ok (mixed Cpp1/Cpp2, Cpp2 code passes safety checks)
2+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
true
2+
false
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
mixed-fixed-type-aliases.cpp

source/cppfront.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,8 +1068,14 @@ class cppfront
10681068

10691069
//-----------------------------------------------------------------------
10701070
//
1071-
auto emit(token const& n) -> void
1071+
auto emit(token const& n, bool is_qualified = false) -> void
10721072
{
1073+
// Implicit "cpp2::" qualification of Cpp2 fixed-width type aliases
1074+
if (!is_qualified && n.type() == lexeme::Cpp2FixedType)
1075+
{
1076+
printer.print_cpp2("cpp2::", n.position());
1077+
}
1078+
10731079
if (n == "new") {
10741080
printer.print_cpp2("cpp2_new", n.position());
10751081
}
@@ -1089,7 +1095,8 @@ class cppfront
10891095
auto emit(
10901096
unqualified_id_node const& n,
10911097
bool in_synthesized_multi_return = false,
1092-
bool is_local_name = true
1098+
bool is_local_name = true,
1099+
bool is_qualified = false
10931100
)
10941101
-> void
10951102
{
@@ -1118,7 +1125,7 @@ class cppfront
11181125
}
11191126

11201127
assert(n.identifier);
1121-
emit(*n.identifier);
1128+
emit(*n.identifier, is_qualified); // inform the identifier if we know this is qualified
11221129

11231130
if (!n.template_args.empty()) {
11241131
printer.print_cpp2("<", n.open_angle);
@@ -1182,7 +1189,7 @@ class cppfront
11821189
if (id.scope_op) {
11831190
emit(*id.scope_op);
11841191
}
1185-
emit(*id.id);
1192+
emit(*id.id, false, true, true); // inform the unqualified-id that it's qualified
11861193
}
11871194

11881195
printer.emit_to_string();
@@ -1194,8 +1201,8 @@ class cppfront
11941201
//
11951202
auto emit(type_id_node const& n) -> void
11961203
{
1197-
try_emit<type_id_node::qualified >(n.id);
11981204
try_emit<type_id_node::unqualified>(n.id, false, false);
1205+
try_emit<type_id_node::qualified >(n.id);
11991206
try_emit<type_id_node::keyword >(n.id);
12001207

12011208
for (auto i = n.pc_qualifiers.rbegin(); i != n.pc_qualifiers.rend(); ++i) {

source/lex.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ enum class lexeme : std::int8_t {
9595
CharacterLiteral,
9696
Keyword,
9797
Cpp1MultiKeyword,
98+
Cpp2FixedType,
9899
Identifier
99100
};
100101

@@ -178,6 +179,7 @@ auto as(lexeme l)
178179
break;case lexeme::CharacterLiteral: return "CharacterLiteral";
179180
break;case lexeme::Keyword: return "Keyword";
180181
break;case lexeme::Cpp1MultiKeyword: return "Cpp1MultiKeyword";
182+
break;case lexeme::Cpp2FixedType: return "Cpp2FixedType";
181183
break;case lexeme::Identifier: return "Identifier";
182184
break;default: return "INTERNAL-ERROR";
183185
}
@@ -480,6 +482,17 @@ auto lex_line(
480482
return do_is_keyword(keys);
481483
};
482484

485+
auto peek_is_cpp2_fundamental_type_keyword = [&]()
486+
{
487+
const auto keys = std::regex(
488+
"^i8_fast|^i16_fast|^i32_fast|^i64_fast|^u8_fast|^u16_fast|^u32_fast|^u64_fast|"
489+
"^i8_least|^i16_least|^i32_least|^i64_least|^u8_least|^u16_least|^u32_least|^u64_least|"
490+
"^i8|^i16|^i32|^i64|^u8|^u16|^u32|^u64"
491+
);
492+
493+
return do_is_keyword(keys);
494+
};
495+
483496
auto peek_is_cpp1_multi_token_fundamental_keyword = [&]()
484497
{
485498
const auto multi_keys = std::regex(
@@ -889,12 +902,18 @@ auto lex_line(
889902
}
890903
}
891904

892-
// Cpp2 multi-token fundamental type keyword
905+
// Cpp1 multi-token fundamental type keyword
893906
//
894907
else if (auto j = peek_is_cpp1_multi_token_fundamental_keyword()) {
895908
store(j, lexeme::Cpp1MultiKeyword);
896909
}
897910

911+
// Cpp2 fixed-width type alias keyword
912+
//
913+
else if (auto j = peek_is_cpp2_fundamental_type_keyword()) {
914+
store(j, lexeme::Cpp2FixedType);
915+
}
916+
898917
// Other keyword
899918
//
900919
else if (auto j = peek_is_keyword()) {

source/parse.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2075,7 +2075,7 @@ class parser
20752075
assert (n->id.index() == type_id_node::unqualified);
20762076
return n;
20772077
}
2078-
if (curr().type() == lexeme::Keyword) {
2078+
if (curr().type() == lexeme::Keyword || curr().type() == lexeme::Cpp2FixedType) {
20792079
n->pos = curr().position();
20802080
n->id = &curr();
20812081
next();
@@ -2178,12 +2178,17 @@ class parser
21782178
//G template-argument:
21792179
//G # note: < > << >> are not allowed in expressions until new ( is opened
21802180
//G expression
2181-
//G id-expression
2181+
//G type-id
21822182
//G
21832183
auto unqualified_id() -> std::unique_ptr<unqualified_id_node>
21842184
{
21852185
// Handle the identifier
2186-
if (curr().type() != lexeme::Identifier) {
2186+
if (
2187+
curr().type() != lexeme::Identifier &&
2188+
curr().type() != lexeme::Keyword &&
2189+
curr().type() != lexeme::Cpp2FixedType
2190+
)
2191+
{
21872192
return {};
21882193
}
21892194

0 commit comments

Comments
 (0)