Implement alignas parsing
This commit is contained in:
parent
ccb2aaa189
commit
756fe351f1
2 changed files with 91 additions and 23 deletions
|
|
@ -101,22 +101,50 @@ namespace
|
|||
auto end = clang_getRangeEnd(extent);
|
||||
|
||||
auto kind = clang_getCursorKind(cur);
|
||||
if ((cursor_is_function(kind) || cursor_is_function(clang_getTemplateCursorKind(cur))
|
||||
|| kind == CXCursor_VarDecl || kind == CXCursor_FieldDecl || kind == CXCursor_ParmDecl
|
||||
|| kind == CXCursor_NonTypeTemplateParameter)
|
||||
&& token_after_is(tu, file, cur, begin, "]", -2)
|
||||
&& token_after_is(tu, file, cur, begin, "]", -3))
|
||||
if (cursor_is_function(kind) || cursor_is_function(clang_getTemplateCursorKind(cur))
|
||||
|| kind == CXCursor_VarDecl || kind == CXCursor_FieldDecl || kind == CXCursor_ParmDecl
|
||||
|| kind == CXCursor_NonTypeTemplateParameter)
|
||||
{
|
||||
while (!token_after_is(tu, file, cur, begin, "[", -1)
|
||||
&& !token_after_is(tu, file, cur, begin, "[", -2))
|
||||
begin = get_next_location(tu, file, begin, -1);
|
||||
if (token_after_is(tu, file, cur, begin, "]", -2)
|
||||
&& token_after_is(tu, file, cur, begin, "]", -3))
|
||||
{
|
||||
while (!token_after_is(tu, file, cur, begin, "[", -1)
|
||||
&& !token_after_is(tu, file, cur, begin, "[", -2))
|
||||
begin = get_next_location(tu, file, begin, -1);
|
||||
|
||||
begin = get_next_location(tu, file, begin, -3);
|
||||
DEBUG_ASSERT(token_after_is(tu, file, cur, begin, "[")
|
||||
&& token_after_is(tu, file, cur, get_next_location(tu, file, begin),
|
||||
"["),
|
||||
detail::parse_error_handler{}, cur,
|
||||
"error in pre-function attribute parsing");
|
||||
begin = get_next_location(tu, file, begin, -3);
|
||||
DEBUG_ASSERT(token_after_is(tu, file, cur, begin, "[")
|
||||
&& token_after_is(tu, file, cur,
|
||||
get_next_location(tu, file, begin), "["),
|
||||
detail::parse_error_handler{}, cur,
|
||||
"error in pre-function attribute parsing");
|
||||
}
|
||||
else if (token_after_is(tu, file, cur, begin, ")", -2))
|
||||
{
|
||||
// maybe alignas specifier
|
||||
auto save_begin = begin;
|
||||
|
||||
auto paren_count = 1;
|
||||
begin = get_next_location(tu, file, begin, -1);
|
||||
for (auto last_begin = begin; paren_count != 0; last_begin = begin)
|
||||
{
|
||||
begin = get_next_location(tu, file, begin, -1);
|
||||
if (token_after_is(tu, file, cur, begin, "(", -1))
|
||||
--paren_count;
|
||||
else if (token_after_is(tu, file, cur, begin, ")", -1))
|
||||
++paren_count;
|
||||
|
||||
DEBUG_ASSERT(!clang_equalLocations(last_begin, begin),
|
||||
detail::parse_error_handler{}, cur,
|
||||
"infinite loop in alignas parsing");
|
||||
}
|
||||
begin = get_next_location(tu, file, begin, -(int(std::strlen("alignas")) + 1));
|
||||
|
||||
if (token_after_is(tu, file, cur, begin, "alignas"))
|
||||
begin = get_next_location(tu, file, begin, -1);
|
||||
else
|
||||
begin = save_begin;
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor_is_function(kind) || cursor_is_function(clang_getTemplateCursorKind(cur)))
|
||||
|
|
@ -431,6 +459,19 @@ namespace
|
|||
return cpp_attribute_kind::unknown;
|
||||
}
|
||||
|
||||
cpp_token_string parse_attribute_arguments(detail::cxtoken_stream& stream)
|
||||
{
|
||||
auto end = find_closing_bracket(stream);
|
||||
skip(stream, "(");
|
||||
|
||||
auto arguments = detail::to_string(stream, end);
|
||||
|
||||
stream.set_cur(end);
|
||||
skip(stream, ")");
|
||||
|
||||
return arguments;
|
||||
}
|
||||
|
||||
cpp_attribute parse_attribute_token(detail::cxtoken_stream& stream,
|
||||
type_safe::optional<std::string> scope)
|
||||
{
|
||||
|
|
@ -455,15 +496,7 @@ namespace
|
|||
// parse arguments
|
||||
type_safe::optional<cpp_token_string> arguments;
|
||||
if (stream.peek() == "(")
|
||||
{
|
||||
auto end = find_closing_bracket(stream);
|
||||
skip(stream, "(");
|
||||
|
||||
arguments = detail::to_string(stream, end);
|
||||
|
||||
stream.set_cur(end);
|
||||
skip(stream, ")");
|
||||
}
|
||||
arguments = parse_attribute_arguments(stream);
|
||||
|
||||
// parse variadic token
|
||||
auto is_variadic = skip_if(stream, "...");
|
||||
|
|
@ -499,6 +532,14 @@ namespace
|
|||
skip(stream, "]");
|
||||
return true;
|
||||
}
|
||||
else if (skip_if(stream, "alignas"))
|
||||
{
|
||||
// alignas specifier
|
||||
// alignas(<some arguments>)
|
||||
// ^
|
||||
auto arguments = parse_attribute_arguments(stream);
|
||||
result.push_back(cpp_attribute(cpp_attribute_kind::alignas_, std::move(arguments)));
|
||||
}
|
||||
else if (skip_if(stream, "__attribute__"))
|
||||
{
|
||||
// GCC/clang attributes
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <cppast/cpp_attribute.hpp>
|
||||
|
||||
#include <cppast/cpp_function.hpp>
|
||||
#include <cppast/cpp_variable.hpp>
|
||||
|
||||
#include "test_parser.hpp"
|
||||
|
||||
|
|
@ -34,6 +35,10 @@ TEST_CASE("cpp_attribute")
|
|||
[[maybe_unused]] void h();
|
||||
[[nodiscard]] int i();
|
||||
[[noreturn]] void j();
|
||||
|
||||
// alignas
|
||||
struct alignas(8) type {};
|
||||
alignas(type) int var;
|
||||
)";
|
||||
|
||||
auto file = parse({}, "cpp_attribute.cpp", code);
|
||||
|
|
@ -99,6 +104,28 @@ TEST_CASE("cpp_attribute")
|
|||
},
|
||||
false);
|
||||
REQUIRE(count == 9);
|
||||
|
||||
count = test_visit<cpp_class>(*file,
|
||||
[&](const cpp_entity& e) {
|
||||
auto& attributes = e.attributes();
|
||||
REQUIRE(attributes.size() == 1u);
|
||||
auto& attr = attributes.front();
|
||||
check_attribute(attr, "alignas", type_safe::nullopt, false,
|
||||
"8", cpp_attribute_kind::alignas_);
|
||||
},
|
||||
false);
|
||||
REQUIRE(count == 1u);
|
||||
|
||||
count = test_visit<cpp_variable>(*file,
|
||||
[&](const cpp_entity& e) {
|
||||
auto& attributes = e.attributes();
|
||||
REQUIRE(attributes.size() == 1u);
|
||||
auto& attr = attributes.front();
|
||||
check_attribute(attr, "alignas", type_safe::nullopt, false,
|
||||
"type", cpp_attribute_kind::alignas_);
|
||||
},
|
||||
false);
|
||||
REQUIRE(count == 1u);
|
||||
}
|
||||
|
||||
TEST_CASE("cpp_attribute matching")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue