Skip to content

Commit 22496c9

Browse files
committed
feat: try to check that the lookup by Cpp1 and cppfront match
1 parent 9816d1b commit 22496c9

File tree

3 files changed

+41
-5
lines changed

3 files changed

+41
-5
lines changed

source/parse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2552,6 +2552,7 @@ struct declaration_node
25522552
> type;
25532553

25542554
std::vector<std::unique_ptr<id_expression_node>> metafunctions;
2555+
std::vector<std::string> metafunction_lookup_checks;
25552556
std::unique_ptr<parameter_declaration_list_node> template_parameters;
25562557
source_position requires_pos = {};
25572558
std::unique_ptr<logical_or_expression_node> requires_clause_expression;

source/sema.h

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,13 +73,18 @@ auto demangle(std::string_view s)
7373
return res;
7474
}
7575

76+
struct lookup_res {
77+
meta::lookup_res meta_res;
78+
std::string demangled_name;
79+
};
80+
7681
auto lookup(
7782
std::string const& name,
7883
current_names_span current_names
7984
)
80-
-> meta::expected<meta::lookup_res>
85+
-> meta::expected<lookup_res>
8186
{
82-
auto res = meta::lookup_res{};
87+
auto res = lookup_res{};
8388
auto libraries = meta::get_reachable_metafunction_symbols();
8489

8590
(void)current_names;
@@ -93,7 +98,7 @@ auto lookup(
9398
{
9499
auto dname = demangle(sym.substr(meta::symbol_prefix.size()));
95100
if (dname == name) {
96-
return {{lib.name, sym}};
101+
return {{{lib.name, sym}, std::move(dname)}};
97102
}
98103
}
99104
}
@@ -105,7 +110,7 @@ auto lookup(
105110
}
106111

107112
// Case not yet handled.
108-
if (res.library.empty()) {
113+
if (res.meta_res.library.empty()) {
109114
return meta::diagnostic{"(ICE) metafunction '" + name + "' not found"};
110115
}
111116
// else
@@ -125,7 +130,30 @@ auto parser::apply_type_metafunctions( declaration_node& n )
125130
n,
126131
rtype,
127132
[&](std::string const& msg) { error( msg, false ); },
128-
[&](std::string const& name) { return lookup(name, current_names); }
133+
[&](std::string const& name) {
134+
return lookup(name, current_names).and_then(
135+
[&](lookup_res res)
136+
-> meta::expected<meta::lookup_res>
137+
{
138+
auto to_metafunction = [](std::string name) {
139+
return "static_cast<void(*)(cpp2::meta::type_declaration&)>(" + std::move(name) + ")";
140+
};
141+
auto check = std::string{};
142+
check += "static_assert(";
143+
check += to_metafunction(name);
144+
check += " == ";
145+
check += to_metafunction("::" + std::move(res.demangled_name));
146+
check += ", ";
147+
// A static_assert doesn't really check that its the evaluated metafunction
148+
// For that, we would have to load the metafunction symbol at runtime
149+
check += "\"the metafunction name '" + name + "' must be ";
150+
check += "reachable and equal to the one evaluated by cppfront\"";
151+
check += ");\n";
152+
n.metafunction_lookup_checks.push_back(check);
153+
return res.meta_res;
154+
}
155+
);
156+
}
129157
);
130158
}
131159

source/to_cpp1.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5523,6 +5523,13 @@ class cppfront
55235523
}
55245524

55255525

5526+
if (printer.get_phase() == printer.phase1_type_defs_func_decls) {
5527+
for (auto&& check : n.metafunction_lookup_checks) {
5528+
printer.print_extra(check);
5529+
}
5530+
}
5531+
5532+
55265533
// If this is a function that has multiple return values,
55275534
// first we need to emit the struct that contains the returns
55285535
if (

0 commit comments

Comments
 (0)