From 40236f606b3a8e022fc884c4d2d6781cca82c04f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Tue, 18 Dec 2018 13:44:39 +0100 Subject: [PATCH] Support multiple separate attributes in front Fixes #60. --- src/libclang/cxtokenizer.cpp | 52 ++++++++++++++++++++---------------- test/cpp_attribute.cpp | 15 ++++++++++- 2 files changed, 43 insertions(+), 24 deletions(-) diff --git a/src/libclang/cxtokenizer.cpp b/src/libclang/cxtokenizer.cpp index e49dbcf..a8cbb09 100644 --- a/src/libclang/cxtokenizer.cpp +++ b/src/libclang/cxtokenizer.cpp @@ -207,33 +207,39 @@ CXSourceRange get_extent(const CXTranslationUnit& tu, const CXFile& file, const || kind == CXCursor_VarDecl || kind == CXCursor_FieldDecl || kind == CXCursor_ParmDecl || kind == CXCursor_NonTypeTemplateParameter) { - auto save_begin = begin; - if (consume_if_token_before_is(tu, file, begin, "]]")) + while (token_before_is(tu, file, begin, "]]") || token_before_is(tu, file, begin, ")")) { - while (!consume_if_token_before_is(tu, file, begin, "[[")) - begin = get_prev_location(tu, file, begin, 1); - } - else if (consume_if_token_before_is(tu, file, begin, ")")) - { - // maybe alignas specifier - - auto paren_count = 1; - for (auto last_begin = begin; paren_count != 0; last_begin = begin) + auto save_begin = begin; + if (consume_if_token_before_is(tu, file, begin, "]]")) { - if (token_before_is(tu, file, begin, "(")) - --paren_count; - else if (token_before_is(tu, file, begin, ")")) - ++paren_count; - - begin = get_prev_location(tu, file, begin, 1); - DEBUG_ASSERT(!clang_equalLocations(last_begin, begin), - detail::parse_error_handler{}, cur, - "infinite loop in alignas parsing"); + while (!consume_if_token_before_is(tu, file, begin, "[[")) + begin = get_prev_location(tu, file, begin, 1); } + else if (consume_if_token_before_is(tu, file, begin, ")")) + { + // maybe alignas specifier - if (!consume_if_token_before_is(tu, file, begin, "alignas")) - // not alignas - begin = save_begin; + auto paren_count = 1; + for (auto last_begin = begin; paren_count != 0; last_begin = begin) + { + if (token_before_is(tu, file, begin, "(")) + --paren_count; + else if (token_before_is(tu, file, begin, ")")) + ++paren_count; + + begin = get_prev_location(tu, file, begin, 1); + DEBUG_ASSERT(!clang_equalLocations(last_begin, begin), + detail::parse_error_handler{}, cur, + "infinite loop in alignas parsing"); + } + + if (!consume_if_token_before_is(tu, file, begin, "alignas")) + { + // not alignas + begin = save_begin; + break; + } + } } } diff --git a/test/cpp_attribute.cpp b/test/cpp_attribute.cpp index 863bbb2..79bdf33 100644 --- a/test/cpp_attribute.cpp +++ b/test/cpp_attribute.cpp @@ -42,6 +42,9 @@ alignas(type) int var; // keyword attributes [[const]] int k(); + +// multiple attributes but separately +[[a]] [[b]] [[c]] int l(); )"; auto file = parse({}, "cpp_attribute.cpp", code); @@ -122,9 +125,19 @@ alignas(type) int var; else if (e.name() == "k") check_attribute(attr, "const", type_safe::nullopt, false, "", cpp_attribute_kind::unknown); + else if (e.name() == "l") + { + REQUIRE_NOTHROW(attributes.size() == 3); + check_attribute(attributes[0], "a", type_safe::nullopt, + false, "", cpp_attribute_kind::unknown); + check_attribute(attributes[1], "b", type_safe::nullopt, + false, "", cpp_attribute_kind::unknown); + check_attribute(attributes[2], "c", type_safe::nullopt, + false, "", cpp_attribute_kind::unknown); + } }, false); - REQUIRE(count == 10); + REQUIRE(count == 11); count = test_visit(*file, [&](const cpp_entity& e) {