From dc5abeb78516573940cc23723c131cd7eb3cec69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Sun, 2 Apr 2017 19:23:49 +0200 Subject: [PATCH] Ensure compatibility with clang 4.0.0 There are some bug fixes for libclang, so now some workarounds were broken. --- src/libclang/class_parser.cpp | 4 +--- src/libclang/namespace_parser.cpp | 6 +++--- src/libclang/tokenizer.cpp | 23 ++++++++++++++++++----- test/code_generator.cpp | 3 +-- test/cpp_enum.cpp | 1 + 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/libclang/class_parser.cpp b/src/libclang/class_parser.cpp index 9f58e5d..dee38a2 100644 --- a/src/libclang/class_parser.cpp +++ b/src/libclang/class_parser.cpp @@ -81,9 +81,7 @@ namespace detail::skip(stream, "virtual"); detail::skip_if(stream, to_string(access)); - std::string name; - while (!stream.done()) - name += stream.get().c_str(); + auto name = detail::to_string(stream, stream.end()); auto type = detail::parse_type(context, class_cur, clang_getCursorType(cur)); builder.base_class(std::move(name), std::move(type), access, is_virtual); diff --git a/src/libclang/namespace_parser.cpp b/src/libclang/namespace_parser.cpp index 6f8c380..7f19c01 100644 --- a/src/libclang/namespace_parser.cpp +++ b/src/libclang/namespace_parser.cpp @@ -88,7 +88,7 @@ std::unique_ptr detail::parse_cpp_namespace_alias(const detail::pars // ; std::string target_name; - while (!detail::skip_if(stream, ";")) + while (!stream.done() && !detail::skip_if(stream, ";")) target_name += stream.get().c_str(); auto target = cpp_namespace_ref(parse_ns_target_cursor(cur), std::move(target_name)); @@ -112,7 +112,7 @@ std::unique_ptr detail::parse_cpp_using_directive(const detail::pars // ; std::string target_name; - while (!detail::skip_if(stream, ";")) + while (!stream.done() && !detail::skip_if(stream, ";")) target_name += stream.get().c_str(); auto target = cpp_namespace_ref(parse_ns_target_cursor(cur), std::move(target_name)); @@ -177,7 +177,7 @@ std::unique_ptr detail::parse_cpp_using_declaration( // ; std::string target_name; - while (!detail::skip_if(stream, ";")) + while (!stream.done() && !detail::skip_if(stream, ";")) target_name += stream.get().c_str(); auto target = cpp_entity_ref(parse_entity_target_cursor(cur), std::move(target_name)); diff --git a/src/libclang/tokenizer.cpp b/src/libclang/tokenizer.cpp index 152ed2a..3225200 100644 --- a/src/libclang/tokenizer.cpp +++ b/src/libclang/tokenizer.cpp @@ -104,9 +104,7 @@ namespace auto child_extent = clang_getCursorExtent(child); end = clang_getRangeStart(child_extent); range_shrunk = true; - return CXChildVisit_Break; } - return CXChildVisit_Continue; }); if (!range_shrunk && !token_after_is(tu, file, cur, end, ";")) @@ -135,7 +133,11 @@ namespace --paren_count; prev = next; } +#if CINDEX_VERSION_MINOR < 37 end = prev; +#else + end = next; +#endif } else if (kind == CXCursor_TemplateTemplateParameter && token_after_is(tu, file, cur, end, "<")) @@ -176,9 +178,16 @@ namespace // need to shrink range anyway end = get_next_location(tu, file, end, -1); } - else if (clang_isExpression(kind) || kind == CXCursor_CXXBaseSpecifier + else if (kind == CXCursor_EnumDecl && !token_after_is(tu, file, cur, end, ";")) + { + while (!token_after_is(tu, file, cur, end, ";")) + end = get_next_location(tu, file, end); + } + else if (clang_isExpression(kind) +#if CINDEX_VERSION_MINOR < 37 + || kind == CXCursor_CXXBaseSpecifier || kind == CXCursor_TemplateTypeParameter +#endif || kind == CXCursor_FieldDecl || kind == CXCursor_ParmDecl - || kind == CXCursor_TemplateTypeParameter || kind == CXCursor_NonTypeTemplateParameter || kind == CXCursor_TemplateTemplateParameter) // need to shrink range by one @@ -202,7 +211,9 @@ void detail::skip(detail::token_stream& stream, const char* str) { if (*str) { - // non-empty + // non-empty string + DEBUG_ASSERT(!stream.done(), parse_error_handler{}, stream.cursor(), + format("expected '", str, "', got exhausted stream")); auto& token = stream.peek(); DEBUG_ASSERT(token == str, parse_error_handler{}, stream.cursor(), format("expected '", str, "', got '", token.c_str(), "'")); @@ -227,6 +238,8 @@ bool detail::skip_if(detail::token_stream& stream, const char* str, bool multi_t { if (!*str) return true; + else if (stream.done()) + return false; auto save = stream.cur(); do { diff --git a/test/code_generator.cpp b/test/code_generator.cpp index 389bb25..8ed4108 100644 --- a/test/code_generator.cpp +++ b/test/code_generator.cpp @@ -32,8 +32,7 @@ enum class bar void func(int(*)(int)); extern void(* ptr)(int(*)(int))=&func; - -templateint var;)"; +)"; auto file = parse({}, "code_generator.cpp", code); REQUIRE(get_code(*file) == code); diff --git a/test/cpp_enum.cpp b/test/cpp_enum.cpp index 685cb21..f6153e0 100644 --- a/test/cpp_enum.cpp +++ b/test/cpp_enum.cpp @@ -141,6 +141,7 @@ enum c : int; REQUIRE(e.is_declaration()); REQUIRE(!e.is_definition()); REQUIRE(!e.is_scoped()); + REQUIRE(e.underlying_type().has_value()); REQUIRE( equal_types(idx, e.underlying_type().value(), *cpp_builtin_type::build(cpp_int))); REQUIRE(count_children(e) == 0u);