diff --git a/src/libclang/function_parser.cpp b/src/libclang/function_parser.cpp index 73b1518..33be5d3 100644 --- a/src/libclang/function_parser.cpp +++ b/src/libclang/function_parser.cpp @@ -545,6 +545,8 @@ std::unique_ptr detail::parse_cpp_member_function(const detail::pars std::move(prefix.semantic_parent)); } +#include + std::unique_ptr detail::parse_cpp_conversion_op(const detail::parse_context& context, const CXCursor& cur) { @@ -559,24 +561,27 @@ std::unique_ptr detail::parse_cpp_conversion_op(const detail::parse_ // heuristic to find arguments tokens // skip forward, skipping inside brackets auto type_start = stream.cur(); - while (true) + auto finished = false; + while (!stream.done() && !finished) { - if (detail::skip_if(stream, "(")) + if (stream.peek() == "(") { - if (detail::skip_if(stream, ")")) - break; + if (detail::skip_if(stream, "(") && detail::skip_if(stream, ")")) + finished = true; else detail::skip_brackets(stream); } - else if (detail::skip_if(stream, "[")) + else if (stream.peek() == "[") detail::skip_brackets(stream); - else if (detail::skip_if(stream, "{")) + else if (stream.peek() == "{") detail::skip_brackets(stream); - else if (detail::skip_if(stream, "<")) + else if (stream.peek() == "<") detail::skip_brackets(stream); else stream.bump(); } + DEBUG_ASSERT(finished, detail::parse_error_handler{}, cur, + "unable to find end of conversion op type"); // bump arguments back stream.bump_back(); stream.bump_back(); diff --git a/src/libclang/tokenizer.cpp b/src/libclang/tokenizer.cpp index 07ac0d0..3e8e83a 100644 --- a/src/libclang/tokenizer.cpp +++ b/src/libclang/tokenizer.cpp @@ -290,7 +290,7 @@ detail::token_iterator detail::find_closing_bracket(detail::token_stream stream) auto bracket_count = 1; auto paren_count = 0; // internal nested parenthesis - while (bracket_count != 0) + while (!stream.done() && bracket_count != 0) { auto& cur = stream.get().value(); if (paren_count == 0 && cur == open_bracket) @@ -307,7 +307,8 @@ detail::token_iterator detail::find_closing_bracket(detail::token_stream stream) } stream.bump_back(); // only check first parameter, token might be ">>" - DEBUG_ASSERT(paren_count == 0 && stream.peek().value()[0] == close_bracket[0], + DEBUG_ASSERT(bracket_count == 0 && paren_count == 0 + && stream.peek().value()[0] == close_bracket[0], parse_error_handler{}, stream.cursor(), "find_closing_bracket() internal parse error"); return stream.cur(); diff --git a/src/libclang/type_parser.cpp b/src/libclang/type_parser.cpp index d127a42..1e703bb 100644 --- a/src/libclang/type_parser.cpp +++ b/src/libclang/type_parser.cpp @@ -585,10 +585,14 @@ namespace return cpp_builtin_type::build(cpp_nullptr); }); + case CXType_Elaborated: + if (auto itype = try_parse_instantiation_type(context, cur, type)) + // elaborated types can be instantiation types + return itype; + // fallthrough case CXType_Record: case CXType_Enum: case CXType_Typedef: - case CXType_Elaborated: return make_leave_type(type, [&](std::string&& spelling) { auto decl = clang_getTypeDeclaration(type); if (remove_prefix(spelling, "(anonymous")) diff --git a/test/cpp_member_function.cpp b/test/cpp_member_function.cpp index 61402e7..06c51a8 100644 --- a/test/cpp_member_function.cpp +++ b/test/cpp_member_function.cpp @@ -3,6 +3,7 @@ // found in the top-level directory of this distribution. #include +#include #include "test_parser.hpp" @@ -155,6 +156,7 @@ TEST_CASE("cpp_conversion_op") auto code = R"( namespace ns { + template using type = char; } @@ -165,8 +167,8 @@ struct foo operator int&(); /// explicit operator bool()const; explicit operator bool() const; - /// constexpr operator ns::type(); - constexpr operator ns::type(); + /// constexpr operator ns::type(); + constexpr operator ns::type(); }; )"; @@ -196,10 +198,11 @@ struct foo } else if (!op.is_explicit() && op.is_constexpr()) { - REQUIRE(op.name() == "operator ns::type"); - REQUIRE(equal_types(idx, op.return_type(), - *cpp_user_defined_type::build( - cpp_type_ref(cpp_entity_id(""), "ns::type")))); + REQUIRE(op.name() == "operator ns::type"); + cpp_template_instantiation_type::builder builder( + cpp_template_ref(cpp_entity_id(""), "ns::type")); + builder.add_unexposed_arguments("int"); + REQUIRE(equal_types(idx, op.return_type(), *builder.finish())); REQUIRE(op.cv_qualifier() == cpp_cv_none); } else