diff --git a/include/cppast/diagnostic.hpp b/include/cppast/diagnostic.hpp index e4cac19..2d4bc3a 100644 --- a/include/cppast/diagnostic.hpp +++ b/include/cppast/diagnostic.hpp @@ -50,7 +50,7 @@ namespace cppast /// \returns A source location where entity and file name is available. static source_location make_entity(std::string entity, std::string file) { - return {std::move(entity), std::move(file), type_safe::nullopt}; + return {std::move(entity), std::move(file), type_safe::nullopt, type_safe::nullopt}; } /// \returns A possible string representation of the source location. diff --git a/src/libclang/function_parser.cpp b/src/libclang/function_parser.cpp index 5042536..4e4b2b1 100644 --- a/src/libclang/function_parser.cpp +++ b/src/libclang/function_parser.cpp @@ -229,16 +229,19 @@ namespace bool is_friend = false; }; - bool prefix_end(detail::cxtoken_stream& stream, const char* name, bool is_ctor) + bool prefix_end(detail::cxtoken_stream& stream, const char* name, bool is_ctor_dtor) { auto cur = stream.cur(); // name can have multiple tokens if it is an operator if (!detail::skip_if(stream, name, true)) return false; else if (stream.peek() == "," || stream.peek() == ">" || stream.peek() == ">>") + { // argument to template parameters + stream.set_cur(cur); return false; - else if (is_ctor) + } + else if (is_ctor_dtor) { // need to make sure it is not actually a class name if (stream.peek() == "::") @@ -269,15 +272,22 @@ namespace else return true; } + else if (std::strcmp(name, "operator") != 0 && stream.peek().kind() == CXToken_Identifier) + { + // can't be function name + stream.set_cur(cur); + return false; + } else return true; } - prefix_info parse_prefix_info(detail::cxtoken_stream& stream, const char* name, bool is_ctor) + prefix_info parse_prefix_info(detail::cxtoken_stream& stream, const char* name, + bool is_ctor_dtor) { prefix_info result; - while (!stream.done() && !prefix_end(stream, name, is_ctor)) + while (!stream.done() && !prefix_end(stream, name, is_ctor_dtor)) { if (detail::skip_if(stream, "constexpr")) result.is_constexpr = true; @@ -811,7 +821,7 @@ std::unique_ptr detail::parse_cpp_destructor(const detail::parse_con detail::cxtokenizer tokenizer(context.tu, context.file, cur); detail::cxtoken_stream stream(tokenizer, cur); - auto prefix_info = parse_prefix_info(stream, "~", false); + auto prefix_info = parse_prefix_info(stream, "~", true); DEBUG_ASSERT(!prefix_info.is_constexpr && !prefix_info.is_explicit, detail::assert_handler{}); auto name = std::string("~") + stream.get().c_str(); diff --git a/test/cpp_function.cpp b/test/cpp_function.cpp index aa73a33..43c8ebd 100644 --- a/test/cpp_function.cpp +++ b/test/cpp_function.cpp @@ -48,6 +48,8 @@ namespace ns /// void l(); void l(); + + using m = int; } /// void ns::l(); @@ -56,6 +58,9 @@ void ns::l() // might confuse parser auto b = noexcept(g()); } + +/// ns::m m(); +ns::m m(); )"; auto check_body = [](const cpp_function& func, cpp_function_body_kind kind) { @@ -223,10 +228,22 @@ void ns::l() check_body(func, cpp_function_declaration); } } + else if (func.name() == "m") + { + REQUIRE(equal_types(idx, func.return_type(), + *cpp_user_defined_type::build( + cpp_type_ref(cpp_entity_id(""), "ns::m")))); + REQUIRE(count_children(func.parameters()) == 0u); + REQUIRE(!func.is_variadic()); + REQUIRE(!func.noexcept_condition()); + REQUIRE(!func.is_constexpr()); + REQUIRE(func.storage_class() == cpp_storage_class_none); + check_body(func, cpp_function_declaration); + } else REQUIRE(false); }); - REQUIRE(count == 13u); + REQUIRE(count == 14u); } TEST_CASE("static cpp_function")