Skip to content

Commit ba843af

Browse files
committed
Move enum and flag_enum underlying type to a metafunction template argument
This original syntax now gets an error message: ``` file_attributes: @flag_enum type = { cached: u8; // 1 current; // 2 obsolete; // 4 cached_and_current := cached | current; } ``` And the new syntax is: ``` file_attributes: @flag_enum<u8> type = { cached; // 1 current; // 2 obsolete; // 4 cached_and_current := cached | current; } ```
1 parent f632e83 commit ba843af

File tree

7 files changed

+284
-208
lines changed

7 files changed

+284
-208
lines changed

regression-tests/pure2-enum.cpp2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ rgb: @enum type = {
1414
blue; // 2
1515
}
1616

17-
file_attributes: @flag_enum type = {
18-
cached: u8; // 1
17+
file_attributes: @flag_enum<u8> type = {
18+
cached; // 1
1919
current; // 2
2020
obsolete; // 4
2121
cached_and_current := cached | current;

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 8918:1648
2+
cppfront compiler v0.2.1 Build 8918:1650
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-
"8918:1648"
1+
"8918:1650"

source/cppfront.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,8 +1677,8 @@ class cppfront
16771677
printer.print_cpp2(",", a.comma);
16781678
}
16791679
first = false;
1680-
try_emit<unqualified_id_node::expression>(a.arg);
1681-
try_emit<unqualified_id_node::type_id >(a.arg);
1680+
try_emit<template_argument::expression>(a.arg);
1681+
try_emit<template_argument::type_id >(a.arg);
16821682
}
16831683
printer.print_cpp2(">", n.close_angle);
16841684
}
@@ -2946,7 +2946,7 @@ class cppfront
29462946
auto ufcs_string = std::string("CPP2_UFCS");
29472947

29482948
// If there are template arguments, use the _TEMPLATE version
2949-
if (i->id_expr->template_args_count() > 0) {
2949+
if (std::ssize(i->id_expr->template_arguments()) > 0) {
29502950
ufcs_string += "_TEMPLATE";
29512951
// we need to replace "fun<int,long,double>" to "fun, (<int,long,double>)" to be able to generate
29522952
// from obj.fun<int, long, double>(1,2) this CPP2_UFCS_TEMPLATE(fun, (<int,long, double>), obj, 1, 2)

source/parse.h

Lines changed: 80 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ struct id_expression_node;
130130
struct declaration_node;
131131
struct inspect_expression_node;
132132
struct literal_node;
133+
struct template_argument;
133134

134135

135136
struct primary_expression_node
@@ -166,7 +167,7 @@ struct primary_expression_node
166167
auto is_literal() const
167168
-> bool;
168169

169-
auto template_args_count() -> int;
170+
auto template_arguments() const -> std::vector<template_argument>&;
170171

171172
auto get_token() const -> token const*;
172173

@@ -1011,30 +1012,38 @@ auto prefix_expression_node::visit(auto& v, int depth)
10111012
struct type_id_node;
10121013
struct template_args_tag { };
10131014

1015+
struct template_argument
1016+
{
1017+
enum active { empty=0, expression, type_id };
1018+
source_position comma;
1019+
std::variant<
1020+
std::monostate,
1021+
std::unique_ptr<expression_node>,
1022+
std::unique_ptr<type_id_node>
1023+
> arg;
1024+
1025+
auto to_string() const
1026+
-> std::string;
1027+
1028+
// So that template_arguments() accessors can return a reference to an empty arg list
1029+
static inline std::vector<template_argument> no_template_args;
1030+
};
1031+
10141032

10151033
struct unqualified_id_node
10161034
{
10171035
token const* identifier = {}; // required
10181036

1019-
enum active { empty=0, expression, type_id };
1020-
10211037
// These are used only if it's a template-id
10221038
source_position open_angle = {};
10231039
source_position close_angle = {};
1024-
struct term {
1025-
source_position comma;
1026-
std::variant<
1027-
std::monostate,
1028-
std::unique_ptr<expression_node>,
1029-
std::unique_ptr<type_id_node>
1030-
> arg;
1031-
};
1032-
std::vector<term> template_args;
10331040

1034-
auto template_args_count()
1035-
-> int
1041+
std::vector<template_argument> template_args;
1042+
1043+
auto template_arguments()
1044+
-> std::vector<template_argument>&
10361045
{
1037-
return std::ssize(template_args);
1046+
return template_args;
10381047
}
10391048

10401049
auto get_token() const
@@ -1073,8 +1082,8 @@ struct unqualified_id_node
10731082
assert(template_args.empty()
10741083
|| template_args.front().comma == source_position{});
10751084
for (auto& a : template_args) {
1076-
try_visit<expression>(a.arg, v, depth+1);
1077-
try_visit<type_id >(a.arg, v, depth+1);
1085+
try_visit<template_argument::expression>(a.arg, v, depth+1);
1086+
try_visit<template_argument::type_id >(a.arg, v, depth+1);
10781087
}
10791088
v.end(template_args_tag{}, depth);
10801089
}
@@ -1094,6 +1103,12 @@ struct qualified_id_node
10941103
};
10951104
std::vector<term> ids;
10961105

1106+
auto template_arguments() const
1107+
-> std::vector<template_argument>&
1108+
{
1109+
return ids.back().id->template_arguments();
1110+
}
1111+
10971112
auto get_token() const
10981113
-> token const*
10991114
{
@@ -1207,14 +1222,14 @@ struct type_id_node
12071222
return tok && *tok == "concept";
12081223
}
12091224

1210-
auto template_args_count() const
1211-
-> int
1225+
auto template_arguments() const
1226+
-> std::vector<template_argument>&
12121227
{
12131228
if (id.index() == unqualified) {
1214-
return std::get<unqualified>(id)->template_args_count();
1229+
return std::get<unqualified>(id)->template_arguments();
12151230
}
12161231
// else
1217-
return 0;
1232+
return std::get<qualified>(id)->template_arguments();
12181233
}
12191234

12201235
auto to_string() const
@@ -1284,12 +1299,12 @@ auto unqualified_id_node::to_string() const
12841299
auto separator = std::string{"<"};
12851300
for (auto& t : template_args) {
12861301
ret += separator;
1287-
assert(t.arg.index() != empty);
1288-
if (t.arg.index() == expression) {
1302+
assert(t.arg.index() != template_argument::empty);
1303+
if (t.arg.index() == template_argument::expression) {
12891304
ret += "(expression)";
12901305
}
1291-
else if (t.arg.index() == type_id) {
1292-
ret += std::get<type_id>(t.arg)->to_string();
1306+
else if (t.arg.index() == template_argument::type_id) {
1307+
ret += std::get<template_argument::type_id>(t.arg)->to_string();
12931308
}
12941309
separator = ",";
12951310
}
@@ -1298,6 +1313,23 @@ auto unqualified_id_node::to_string() const
12981313
return ret;
12991314
}
13001315

1316+
auto template_argument::to_string() const
1317+
-> std::string
1318+
{
1319+
switch (arg.index()) {
1320+
break;case empty:
1321+
return {};
1322+
break;case expression:
1323+
return std::get<expression>(arg)->to_string();
1324+
break;case type_id:
1325+
return std::get<type_id>(arg)->to_string();
1326+
break;default:
1327+
assert(!"ICE: invalid template_argument state");
1328+
}
1329+
// else
1330+
return {};
1331+
}
1332+
13011333

13021334
struct is_as_expression_node
13031335
{
@@ -1434,14 +1466,14 @@ struct id_expression_node
14341466
std::unique_ptr<unqualified_id_node>
14351467
> id;
14361468

1437-
auto template_args_count()
1438-
-> int
1469+
auto template_arguments() const
1470+
-> std::vector<template_argument>&
14391471
{
14401472
if (is_unqualified()) {
1441-
return std::get<unqualified>(id)->template_args_count();
1473+
return std::get<unqualified>(id)->template_arguments();
14421474
}
14431475
// else
1444-
return 0;
1476+
return std::get<qualified>(id)->template_arguments();
14451477
}
14461478

14471479
auto is_fold_expression() const
@@ -2466,7 +2498,7 @@ struct declaration_node
24662498
std::unique_ptr<alias_node>
24672499
> type;
24682500

2469-
std::vector<std::unique_ptr<id_expression_node>> meta_functions;
2501+
std::vector<std::unique_ptr<id_expression_node>> metafunctions;
24702502
std::unique_ptr<parameter_declaration_list_node> template_parameters;
24712503
source_position requires_pos = {};
24722504
std::unique_ptr<logical_or_expression_node> requires_clause_expression;
@@ -3292,7 +3324,7 @@ struct declaration_node
32923324
try_visit<a_namespace>(type, v, depth+1);
32933325
try_visit<an_alias >(type, v, depth+1);
32943326

3295-
for (auto& m : meta_functions) {
3327+
for (auto& m : metafunctions) {
32963328
assert(m);
32973329
m->visit(v, depth+1);
32983330
}
@@ -3608,14 +3640,14 @@ auto function_type_node::is_destructor() const
36083640
}
36093641

36103642

3611-
auto primary_expression_node::template_args_count()
3612-
-> int
3643+
auto primary_expression_node::template_arguments() const
3644+
-> std::vector<template_argument>&
36133645
{
36143646
if (expr.index() == id_expression) {
3615-
return std::get<id_expression>(expr)->template_args_count();
3647+
return std::get<id_expression>(expr)->template_arguments();
36163648
}
36173649
// else
3618-
return 0;
3650+
return template_argument::no_template_args;
36193651
}
36203652

36213653

@@ -4146,8 +4178,8 @@ auto pretty_print_visualize(unqualified_id_node const& n, int indent)
41464178
ret += ", ";
41474179
}
41484180
first = false;
4149-
ret += try_pretty_print_visualize<unqualified_id_node::expression>(arg.arg, indent);
4150-
ret += try_pretty_print_visualize<unqualified_id_node::type_id >(arg.arg, indent);
4181+
ret += try_pretty_print_visualize<template_argument::expression>(arg.arg, indent);
4182+
ret += try_pretty_print_visualize<template_argument::type_id >(arg.arg, indent);
41514183
}
41524184
ret += ">";
41534185
}
@@ -4570,7 +4602,7 @@ auto pretty_print_visualize(declaration_node const& n, int indent, bool include_
45704602

45714603
auto metafunctions = std::string{};
45724604
if (include_metafunctions_list) {
4573-
for (auto& meta : n.meta_functions) {
4605+
for (auto& meta : n.metafunctions) {
45744606
metafunctions += " @" + pretty_print_visualize(*meta, indent);
45754607
}
45764608
}
@@ -6016,7 +6048,7 @@ class parser
60166048
n->open_angle = curr().position();
60176049
next();
60186050

6019-
auto term = unqualified_id_node::term{};
6051+
auto term = template_argument{};
60206052

60216053
do {
60226054
// If it doesn't start with * or const (which can only be a type id),
@@ -7439,7 +7471,7 @@ class parser
74397471
}
74407472

74417473

7442-
auto apply_type_meta_functions( declaration_node& decl )
7474+
auto apply_type_metafunctions( declaration_node& decl )
74437475
-> bool;
74447476

74457477

@@ -7589,7 +7621,7 @@ class parser
75897621
error("'@' must be followed by a a metafunction name", false);
75907622
return {};
75917623
}
7592-
n->meta_functions.push_back( std::move(idx) );
7624+
n->metafunctions.push_back( std::move(idx) );
75937625
}
75947626

75957627
// Next is an optional template parameter list
@@ -7647,9 +7679,9 @@ class parser
76477679
n->type = std::move(t);
76487680
assert (n->is_function());
76497681

7650-
if (!n->meta_functions.empty()) {
7682+
if (!n->metafunctions.empty()) {
76517683
errors.emplace_back(
7652-
n->meta_functions.front()->position(),
7684+
n->metafunctions.front()->position(),
76537685
"(temporary alpha limitation) metafunctions are currently not supported on functions, only on types"
76547686
);
76557687
return {};
@@ -7663,9 +7695,9 @@ class parser
76637695
assert (n->type.index() == declaration_node::a_namespace);
76647696
next();
76657697

7666-
if (!n->meta_functions.empty()) {
7698+
if (!n->metafunctions.empty()) {
76677699
errors.emplace_back(
7668-
n->meta_functions.front()->position(),
7700+
n->metafunctions.front()->position(),
76697701
"(temporary alpha limitation) metafunctions are currently not supported on namespaces, only on types"
76707702
);
76717703
return {};
@@ -7694,9 +7726,9 @@ class parser
76947726
n->type = std::move(t);
76957727
assert (n->is_object());
76967728

7697-
if (!n->meta_functions.empty()) {
7729+
if (!n->metafunctions.empty()) {
76987730
errors.emplace_back(
7699-
n->meta_functions.front()->position(),
7731+
n->metafunctions.front()->position(),
77007732
"(temporary alpha limitation) metafunctions are currently not supported on objects, only on types"
77017733
);
77027734
return {};
@@ -7840,7 +7872,7 @@ class parser
78407872

78417873
// If this is a type with metafunctions, apply those
78427874
if (n->is_type()) {
7843-
if (!apply_type_meta_functions(*n)) {
7875+
if (!apply_type_metafunctions(*n)) {
78447876
error(
78457877
"error encountered while applying type metafunctions",
78467878
false, {}, true

0 commit comments

Comments
 (0)