Skip to content

Commit 1b03d10

Browse files
MinhLu12foonathan
authored andcommitted
Add support for consteval
1 parent ce218df commit 1b03d10

File tree

6 files changed

+250
-9
lines changed

6 files changed

+250
-9
lines changed

include/cppast/cpp_function.hpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ class cpp_function final : public cpp_function_base
226226
{
227227
function->constexpr_ = true;
228228
}
229+
230+
/// \effects Marks the function as `consteval`.
231+
void is_consteval()
232+
{
233+
function->consteval_ = true;
234+
}
229235
};
230236

231237
/// \returns A reference to the return [cppast::cpp_type]().
@@ -248,17 +254,24 @@ class cpp_function final : public cpp_function_base
248254
return constexpr_;
249255
}
250256

257+
/// \returns Whether the function is marked `consteval`.
258+
bool is_consteval() const noexcept
259+
{
260+
return consteval_;
261+
}
262+
251263
private:
252264
cpp_entity_kind do_get_entity_kind() const noexcept override;
253265

254266
cpp_function(std::string name, std::unique_ptr<cpp_type> ret)
255267
: cpp_function_base(std::move(name)), return_type_(std::move(ret)),
256-
storage_(cpp_storage_class_auto), constexpr_(false)
268+
storage_(cpp_storage_class_auto), constexpr_(false), consteval_(false)
257269
{}
258270

259271
std::unique_ptr<cpp_type> return_type_;
260272
cpp_storage_class_specifiers storage_;
261273
bool constexpr_;
274+
bool consteval_;
262275
};
263276
} // namespace cppast
264277

include/cppast/cpp_member_function.hpp

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,12 @@ class cpp_member_function_base : public cpp_function_base
100100
return constexpr_;
101101
}
102102

103+
/// \returns Whether or not the member function is `consteval`.
104+
bool is_consteval() const noexcept
105+
{
106+
return consteval_;
107+
}
108+
103109
protected:
104110
/// Builder class for member functions.
105111
template <typename T>
@@ -132,14 +138,20 @@ class cpp_member_function_base : public cpp_function_base
132138
static_cast<cpp_member_function_base&>(*this->function).constexpr_ = true;
133139
}
134140

141+
/// \effects Marks the function as `consteval`.
142+
void is_consteval() noexcept
143+
{
144+
static_cast<cpp_member_function_base&>(*this->function).consteval_ = true;
145+
}
146+
135147
protected:
136148
basic_member_builder() noexcept = default;
137149
};
138150

139151
/// \effects Sets name and return type, as well as the rest to defaults.
140152
cpp_member_function_base(std::string name, std::unique_ptr<cpp_type> return_type)
141153
: cpp_function_base(std::move(name)), return_type_(std::move(return_type)), cv_(cpp_cv_none),
142-
ref_(cpp_ref_none), constexpr_(false)
154+
ref_(cpp_ref_none), constexpr_(false), consteval_(false)
143155
{}
144156

145157
protected:
@@ -151,6 +163,7 @@ class cpp_member_function_base : public cpp_function_base
151163
cpp_cv cv_;
152164
cpp_reference ref_;
153165
bool constexpr_;
166+
bool consteval_;
154167
};
155168

156169
/// A [cppast::cpp_entity]() modelling a member function.
@@ -239,6 +252,12 @@ class cpp_constructor final : public cpp_function_base
239252
{
240253
function->constexpr_ = true;
241254
}
255+
256+
/// \effects Marks the constructor `consteval`.
257+
void is_consteval() noexcept
258+
{
259+
function->consteval_ = true;
260+
}
242261
};
243262

244263
/// \returns Whether or not the constructor is `explicit`.
@@ -253,15 +272,22 @@ class cpp_constructor final : public cpp_function_base
253272
return constexpr_;
254273
}
255274

275+
/// \returns Whether or not the constructor is `consteval`.
276+
bool is_consteval() const noexcept
277+
{
278+
return consteval_;
279+
}
280+
256281
private:
257282
cpp_constructor(std::string name)
258-
: cpp_function_base(std::move(name)), explicit_(false), constexpr_(false)
283+
: cpp_function_base(std::move(name)), explicit_(false), constexpr_(false), consteval_(false)
259284
{}
260285

261286
cpp_entity_kind do_get_entity_kind() const noexcept override;
262287

263288
bool explicit_;
264289
bool constexpr_;
290+
bool consteval_;
265291

266292
friend basic_builder<cpp_constructor>;
267293
};

src/code_generator.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ bool write_variable_base(code_generator::output& output, const cpp_variable_base
465465
}
466466

467467
void write_storage_class(code_generator::output& output, cpp_storage_class_specifiers storage,
468-
bool is_constexpr)
468+
bool is_constexpr, bool is_consteval)
469469
{
470470
if (is_static(storage))
471471
output << keyword("static") << whitespace;
@@ -475,6 +475,8 @@ void write_storage_class(code_generator::output& output, cpp_storage_class_speci
475475
output << keyword("thread_local") << whitespace;
476476
if (is_constexpr)
477477
output << keyword("constexpr") << whitespace;
478+
else if (is_consteval)
479+
output << keyword("consteval") << whitespace;
478480
}
479481

480482
bool generate_variable(code_generator& generator, const cpp_variable& var,
@@ -483,7 +485,7 @@ bool generate_variable(code_generator& generator, const cpp_variable& var,
483485
code_generator::output output(type_safe::ref(generator), type_safe::ref(var), cur_access);
484486
if (output)
485487
{
486-
write_storage_class(output, var.storage_class(), var.is_constexpr());
488+
write_storage_class(output, var.storage_class(), var.is_constexpr(), false);
487489

488490
write_variable_base(output, var, var.name());
489491
output << punctuation(";") << newl;
@@ -602,7 +604,7 @@ bool generate_function(code_generator& generator, const cpp_function& func,
602604
{
603605
if (is_friended(func))
604606
output << keyword("friend") << whitespace;
605-
write_storage_class(output, func.storage_class(), func.is_constexpr());
607+
write_storage_class(output, func.storage_class(), func.is_constexpr(), func.is_consteval());
606608

607609
if (output.options() & code_generator::exclude_return)
608610
output.excluded(func) << whitespace;
@@ -705,6 +707,8 @@ bool generate_member_function(code_generator& generator, const cpp_member_functi
705707
output << keyword("friend") << whitespace;
706708
if (func.is_constexpr())
707709
output << keyword("constexpr") << whitespace;
710+
else if (func.is_consteval())
711+
output << keyword("consteval") << whitespace;
708712
else
709713
write_prefix_virtual(output, func.virtual_info());
710714

@@ -756,6 +760,8 @@ bool generate_conversion_op(code_generator& generator, const cpp_conversion_op&
756760
output << keyword("explicit") << whitespace;
757761
if (op.is_constexpr())
758762
output << keyword("constexpr") << whitespace;
763+
else if (op.is_consteval())
764+
output << keyword("consteval") << whitespace;
759765
else
760766
write_prefix_virtual(output, op.virtual_info());
761767

@@ -791,6 +797,8 @@ bool generate_constructor(code_generator& generator, const cpp_constructor& ctor
791797
output << keyword("explicit") << whitespace;
792798
if (ctor.is_constexpr())
793799
output << keyword("constexpr") << whitespace;
800+
if (ctor.is_consteval())
801+
output << keyword("consteval") << whitespace;
794802

795803
output << identifier(ctor.semantic_scope()) << identifier(ctor.name());
796804
write_function_parameters(output, ctor);

src/libclang/function_parser.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ struct prefix_info
220220
{
221221
cpp_attribute_list attributes;
222222
bool is_constexpr = false;
223+
bool is_consteval = false;
223224
bool is_virtual = false;
224225
bool is_explicit = false;
225226
bool is_friend = false;
@@ -284,7 +285,9 @@ prefix_info parse_prefix_info(detail::cxtoken_stream& stream, const char* name,
284285

285286
while (!stream.done() && !prefix_end(stream, name, is_ctor_dtor))
286287
{
287-
if (detail::skip_if(stream, "constexpr"))
288+
if (detail::skip_if(stream, "consteval"))
289+
result.is_consteval = true;
290+
else if (detail::skip_if(stream, "constexpr"))
288291
result.is_constexpr = true;
289292
else if (detail::skip_if(stream, "virtual"))
290293
result.is_virtual = true;
@@ -534,8 +537,13 @@ std::unique_ptr<cpp_entity> parse_cpp_function_impl(const detail::parse_context&
534537
builder.storage_class(cpp_storage_class_specifiers(
535538
detail::get_storage_class(cur)
536539
| (is_static ? cpp_storage_class_static : cpp_storage_class_none)));
540+
541+
DEBUG_ASSERT(!(prefix.is_constexpr && prefix.is_consteval), detail::parse_error_handler{}, cur,
542+
"function cannot be both constexpr and consteval");
537543
if (prefix.is_constexpr)
538544
builder.is_constexpr();
545+
else if (prefix.is_consteval)
546+
builder.is_consteval();
539547

540548
skip_parameters(stream);
541549

@@ -687,6 +695,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_member_function(const detail::pars
687695

688696
if (prefix.is_constexpr)
689697
builder.is_constexpr();
698+
else if (prefix.is_consteval)
699+
builder.is_consteval();
690700

691701
skip_parameters(stream);
692702
return handle_suffix(context, cur, builder, stream, prefix.is_virtual,
@@ -751,6 +761,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_
751761
builder.is_explicit();
752762
else if (prefix.is_constexpr)
753763
builder.is_constexpr();
764+
else if (prefix.is_consteval)
765+
builder.is_consteval();
754766

755767
return handle_suffix(context, cur, builder, stream, prefix.is_virtual,
756768
parse_scope(cur, is_friend));
@@ -785,6 +797,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_co
785797
builder.is_constexpr();
786798
else if (prefix.is_explicit)
787799
builder.is_explicit();
800+
else if (prefix.is_consteval)
801+
builder.is_consteval();
788802

789803
skip_parameters(stream);
790804

test/cpp_function.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,51 @@ void n(int i = int());
274274
REQUIRE(count == 15u);
275275
}
276276

277+
TEST_CASE("consteval cpp_function")
278+
{
279+
if (libclang_parser::libclang_minor_version() < 60)
280+
return;
281+
282+
auto code = R"(
283+
/// consteval void p();
284+
consteval void p();
285+
/// static consteval void q();
286+
static consteval void q();
287+
)";
288+
auto check_body = [](const cpp_function& func, cpp_function_body_kind kind) {
289+
REQUIRE(func.body_kind() == kind);
290+
REQUIRE(func.is_declaration() == is_declaration(kind));
291+
REQUIRE(func.is_definition() == is_definition(kind));
292+
};
293+
294+
cpp_entity_index idx;
295+
auto file = parse(idx, "consteval_function.cpp", code, false, cppast::cpp_standard::cpp_2a);
296+
auto count = test_visit<cpp_function>(*file, [&](const cpp_function& func) {
297+
if (func.name() == "p" || func.name() == "q")
298+
{
299+
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void)));
300+
REQUIRE(func.signature() == "()");
301+
REQUIRE(!func.is_variadic());
302+
REQUIRE(!func.noexcept_condition());
303+
check_body(func, cpp_function_declaration);
304+
305+
if (func.name() == "p")
306+
{
307+
REQUIRE(func.is_consteval());
308+
REQUIRE(func.storage_class() == cpp_storage_class_none);
309+
}
310+
else if (func.name() == "q")
311+
{
312+
REQUIRE(func.is_consteval());
313+
REQUIRE(func.storage_class() == cpp_storage_class_static);
314+
}
315+
}
316+
else
317+
REQUIRE(false);
318+
});
319+
REQUIRE(count == 2u);
320+
}
321+
277322
TEST_CASE("static cpp_function")
278323
{
279324
auto code = R"(

0 commit comments

Comments
 (0)