From 2122dad8b095cdec313313a6ca4d1613aa956a06 Mon Sep 17 00:00:00 2001 From: Rokas Kupstys Date: Tue, 27 Mar 2018 11:50:08 +0300 Subject: [PATCH 1/2] Expose __attribute__ and __declspec attributes. Closes #50. --- src/libclang/cxtokenizer.cpp | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/src/libclang/cxtokenizer.cpp b/src/libclang/cxtokenizer.cpp index d374cef..edbbf72 100644 --- a/src/libclang/cxtokenizer.cpp +++ b/src/libclang/cxtokenizer.cpp @@ -545,12 +545,23 @@ namespace auto arguments = parse_attribute_arguments(stream); result.push_back(cpp_attribute(cpp_attribute_kind::alignas_, std::move(arguments))); } - else if (skip_if(stream, "__attribute__")) + else if (skip_if(stream, "__attribute__") && stream.peek() == "(") { // GCC/clang attributes - // __attribute__() - // ^ - skip_brackets(stream); + // __attribute__(()) + // ^^ + skip(stream, "("); + skip(stream, "("); + + auto scope = parse_attribute_using(stream); + while (!skip_if(stream, ")")) + { + auto attribute = parse_attribute_token(stream, scope); + result.push_back(std::move(attribute)); + detail::skip_if(stream, ","); + } + + skip(stream, ")"); return true; } else if (skip_if(stream, "__declspec")) @@ -558,7 +569,15 @@ namespace // MSVC declspec // __declspec() // ^ - skip_brackets(stream); + skip(stream, "("); + auto scope = parse_attribute_using(stream); + while (!skip_if(stream, ")")) + { + auto attribute = parse_attribute_token(stream, scope); + result.push_back(std::move(attribute)); + detail::skip_if(stream, ","); + } + return true; } From 19f237043b72c6150f370bb17dc230a69a12e6d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Wed, 28 Mar 2018 10:55:09 +0200 Subject: [PATCH 2/2] Handle attribute names that are keywords --- src/libclang/cxtokenizer.cpp | 20 +++++++++++--------- test/cpp_attribute.cpp | 8 +++++++- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/libclang/cxtokenizer.cpp b/src/libclang/cxtokenizer.cpp index edbbf72..afea2ae 100644 --- a/src/libclang/cxtokenizer.cpp +++ b/src/libclang/cxtokenizer.cpp @@ -297,7 +297,7 @@ namespace return clang_getRange(begin, end); } -} +} // namespace detail::cxtokenizer::cxtokenizer(const CXTranslationUnit& tu, const CXFile& file, const CXCursor& cur) @@ -335,7 +335,7 @@ namespace ++str; return true; } -} +} // namespace bool detail::skip_if(detail::cxtoken_stream& stream, const char* str, bool multi_token) { @@ -369,7 +369,7 @@ namespace return next_kind == CXToken_Literal; return false; } -} +} // namespace detail::cxtoken_iterator detail::find_closing_bracket(detail::cxtoken_stream stream) { @@ -483,8 +483,9 @@ namespace // (identifier ::)_opt identifier ( '(' some tokens ')' )_opt ..._opt // parse name - DEBUG_ASSERT(stream.peek().kind() == CXToken_Identifier, detail::parse_error_handler{}, - stream.cursor(), "expected identifier"); + DEBUG_ASSERT(stream.peek().kind() == CXToken_Identifier + || stream.peek().kind() == CXToken_Keyword, + detail::parse_error_handler{}, stream.cursor(), "expected identifier"); auto name = stream.get().value().std_str(); if (skip_if(stream, "::")) { @@ -493,8 +494,9 @@ namespace "attribute using + scope not allowed"); scope = std::move(name); - DEBUG_ASSERT(stream.peek().kind() == CXToken_Identifier, detail::parse_error_handler{}, - stream.cursor(), "expected identifier"); + DEBUG_ASSERT(stream.peek().kind() == CXToken_Identifier + || stream.peek().kind() == CXToken_Keyword, + detail::parse_error_handler{}, stream.cursor(), "expected identifier"); name = stream.get().value().std_str(); } @@ -583,7 +585,7 @@ namespace return false; } -} +} // namespace cpp_attribute_list detail::parse_attributes(detail::cxtoken_stream& stream, bool skip_anway) { @@ -631,7 +633,7 @@ namespace DEBUG_UNREACHABLE(detail::assert_handler{}); return cpp_token_kind::punctuation; } -} +} // namespace cpp_token_string detail::to_string(cxtoken_stream& stream, cxtoken_iterator end) { diff --git a/test/cpp_attribute.cpp b/test/cpp_attribute.cpp index 329366b..8854f91 100644 --- a/test/cpp_attribute.cpp +++ b/test/cpp_attribute.cpp @@ -39,6 +39,9 @@ TEST_CASE("cpp_attribute") // alignas struct alignas(8) type {}; alignas(type) int var; + +// keyword attributes +[[const]] int k(); )"; auto file = parse({}, "cpp_attribute.cpp", code); @@ -113,9 +116,12 @@ alignas(type) int var; else if (e.name() == "j") check_attribute(attr, "noreturn", type_safe::nullopt, false, "", cpp_attribute_kind::noreturn); + else if (e.name() == "k") + check_attribute(attr, "const", type_safe::nullopt, false, + "", cpp_attribute_kind::unknown); }, false); - REQUIRE(count == 9); + REQUIRE(count == 10); count = test_visit(*file, [&](const cpp_entity& e) {