// Copyright (C) 2017-2022 Jonathan Müller and cppast contributors // SPDX-License-Identifier: MIT #include #include #include #include "test_parser.hpp" using namespace cppast; TEST_CASE("cpp_template_type_parameter") { auto code = R"( template using a = void; template using b = void; template using c = void; // libclang workaround when decltype here template using d = void; // potential maximal munch here, but ignore it template > using e = void; )"; cpp_entity_index idx; auto file = parse(idx, "cpp_template_type_parameter.cpp", code); auto count = test_visit( *file, [&](const cpp_alias_template& alias) { REQUIRE(equal_types(idx, alias.type_alias().underlying_type(), *cpp_builtin_type::build(cpp_void))); for (auto& p : alias.parameters()) { REQUIRE(p.kind() == cpp_entity_kind::template_type_parameter_t); auto& param = static_cast(p); if (param.name() == "A") { REQUIRE(alias.name() == "a"); REQUIRE(param.keyword() == cpp_template_keyword::keyword_typename); REQUIRE(!param.is_variadic()); REQUIRE(!param.default_type()); } else if (param.name() == "B") { REQUIRE(alias.name() == "b"); REQUIRE(param.keyword() == cpp_template_keyword::keyword_class); REQUIRE(param.is_variadic()); REQUIRE(!param.default_type()); } else if (param.name() == "") { REQUIRE(alias.name() == "c"); REQUIRE(param.keyword() == cpp_template_keyword::keyword_typename); REQUIRE(!param.is_variadic()); REQUIRE(param.default_type().has_value()); REQUIRE(equal_types(idx, param.default_type().value(), *cpp_unexposed_type::build("const int*"))); } else if (param.name() == "D") { REQUIRE(alias.name() == "d"); REQUIRE(param.keyword() == cpp_template_keyword::keyword_class); REQUIRE(!param.is_variadic()); REQUIRE(param.default_type().has_value()); REQUIRE(equal_types(idx, param.default_type().value(), *cpp_unexposed_type::build("decltype(1+3)"))); } else if (param.name() == "E") { REQUIRE(alias.name() == "e"); REQUIRE(param.keyword() == cpp_template_keyword::keyword_typename); REQUIRE(!param.is_variadic()); REQUIRE(param.default_type().has_value()); REQUIRE(equal_types(idx, param.default_type().value(), *cpp_unexposed_type::build("a"))); } else REQUIRE(false); } }, false); // can't check synopsis with comments REQUIRE(count == 5u); } TEST_CASE("cpp_non_type_template_parameter") { auto code = R"( template using a = void; template using b = void; template using c = void; template using d = void; )"; cpp_entity_index idx; auto file = parse(idx, "cpp_non_type_template_parameter.cpp", code); auto count = test_visit( *file, [&](const cpp_alias_template& alias) { REQUIRE(equal_types(idx, alias.type_alias().underlying_type(), *cpp_builtin_type::build(cpp_void))); for (auto& p : alias.parameters()) { REQUIRE(p.kind() == cpp_entity_kind::non_type_template_parameter_t); auto& param = static_cast(p); if (param.name() == "A") { REQUIRE(alias.name() == "a"); REQUIRE(equal_types(idx, param.type(), *cpp_builtin_type::build(cpp_int))); REQUIRE(!param.is_variadic()); REQUIRE(!param.default_value()); } else if (param.name() == "") { REQUIRE(alias.name() == "b"); REQUIRE( equal_types(idx, param.type(), *cpp_pointer_type::build(cpp_builtin_type::build(cpp_char)))); REQUIRE(!param.is_variadic()); REQUIRE(param.default_value()); REQUIRE(equal_expressions(param.default_value().value(), *cpp_unexposed_expression:: build(cpp_builtin_type::build(cpp_nullptr), cpp_token_string::tokenize("nullptr")))); } else if (param.name() == "C") { REQUIRE(alias.name() == "c"); REQUIRE(equal_types(idx, param.type(), *cpp_builtin_type::build(cpp_int))); REQUIRE(param.is_variadic()); REQUIRE(!param.default_value()); } else if (param.name() == "D") { REQUIRE(alias.name() == "d"); cpp_function_type::builder builder(cpp_builtin_type::build(cpp_void)); builder.is_variadic(); REQUIRE( equal_types(idx, param.type(), *cpp_pointer_type::build(builder.finish()))); REQUIRE(!param.is_variadic()); REQUIRE(!param.default_value()); } else REQUIRE(false); } }, false); // can't check synopsis with comments REQUIRE(count == 4u); } TEST_CASE("cpp_template_template_parameter") { // no need to check parameters of template parameter auto code = R"( namespace ns { template using def = void; } template