// Copyright (C) 2017 Jonathan Müller // This file is subject to the license terms in the LICENSE file // found in the top-level directory of this distribution. #include #include #include "test_parser.hpp" using namespace cppast; TEST_CASE("cpp_function_template") { // only check templated related stuff auto code = R"( template T a(const T& t); template using type = int; struct d { template static type b(T); template auto c() -> T; template operator T() const; template d(const T&); }; )"; cpp_entity_index idx; auto file = parse(idx, "cpp_function_template.cpp", code); auto count = test_visit(*file, [&](const cpp_function_template& tfunc) { if (tfunc.name() == "a") { check_template_parameters(tfunc, {{cpp_entity_kind::template_type_parameter_t, "T"}}); REQUIRE(tfunc.function().kind() == cpp_entity_kind::function_t); auto& func = static_cast(tfunc.function()); auto parameter = cpp_template_type_parameter_ref(cpp_entity_id(""), "T"); REQUIRE(equal_types(idx, func.return_type(), *cpp_template_parameter_type::build(parameter))); auto count = 0u; for (auto& param : func) { ++count; REQUIRE( equal_types(idx, param.type(), *cpp_reference_type:: build(cpp_cv_qualified_type:: build(cpp_template_parameter_type::build(parameter), cpp_cv_const), cpp_ref_lvalue))); } REQUIRE(count == 1u); } else if (tfunc.name() == "b") { check_parent(tfunc, "d", "d::b"); check_template_parameters(tfunc, {{cpp_entity_kind::non_type_template_parameter_t, "I"}, {cpp_entity_kind::template_type_parameter_t, "T"}}); REQUIRE(tfunc.function().kind() == cpp_entity_kind::function_t); auto& func = static_cast(tfunc.function()); cpp_template_instantiation_type::builder builder( cpp_template_ref(cpp_entity_id(""), "type")); builder.add_argument( cpp_unexposed_expression::build(cpp_builtin_type::build("int"), "I")); REQUIRE(equal_types(idx, func.return_type(), *builder.finish())); auto type_parameter = cpp_template_type_parameter_ref(cpp_entity_id(""), "T"); auto count = 0u; for (auto& param : func) { ++count; REQUIRE(equal_types(idx, param.type(), *cpp_template_parameter_type::build(type_parameter))); } REQUIRE(count == 1u); } else if (tfunc.name() == "c") { check_template_parameters(tfunc, {{cpp_entity_kind::template_type_parameter_t, "T"}}); REQUIRE(tfunc.function().kind() == cpp_entity_kind::member_function_t); auto& func = static_cast(tfunc.function()); REQUIRE(func.cv_qualifier() == cpp_cv_none); auto parameter = cpp_template_type_parameter_ref(cpp_entity_id(""), "T"); REQUIRE(equal_types(idx, func.return_type(), *cpp_template_parameter_type::build(parameter))); } else if (tfunc.name() == "operator T") { check_template_parameters(tfunc, {{cpp_entity_kind::template_type_parameter_t, "T"}}); REQUIRE(tfunc.function().kind() == cpp_entity_kind::conversion_op_t); auto& func = static_cast(tfunc.function()); REQUIRE(func.cv_qualifier() == cpp_cv_const); auto parameter = cpp_template_type_parameter_ref(cpp_entity_id(""), "T"); REQUIRE(equal_types(idx, func.return_type(), *cpp_template_parameter_type::build(parameter))); } else if (tfunc.name() == "d") { check_template_parameters(tfunc, {{cpp_entity_kind::template_type_parameter_t, "T"}}); REQUIRE(tfunc.function().kind() == cpp_entity_kind::constructor_t); auto& func = static_cast(tfunc.function()); auto parameter = cpp_template_type_parameter_ref(cpp_entity_id(""), "T"); auto count = 0u; for (auto& param : func) { ++count; REQUIRE( equal_types(idx, param.type(), *cpp_reference_type:: build(cpp_cv_qualified_type:: build(cpp_template_parameter_type::build(parameter), cpp_cv_const), cpp_ref_lvalue))); } REQUIRE(count == 1u); } else REQUIRE(false); }); REQUIRE(count == 5u); }