Expose __attribute__ and __declspec
This commit is contained in:
commit
7b030190bd
2 changed files with 42 additions and 15 deletions
|
|
@ -297,7 +297,7 @@ namespace
|
||||||
|
|
||||||
return clang_getRange(begin, end);
|
return clang_getRange(begin, end);
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
detail::cxtokenizer::cxtokenizer(const CXTranslationUnit& tu, const CXFile& file,
|
detail::cxtokenizer::cxtokenizer(const CXTranslationUnit& tu, const CXFile& file,
|
||||||
const CXCursor& cur)
|
const CXCursor& cur)
|
||||||
|
|
@ -335,7 +335,7 @@ namespace
|
||||||
++str;
|
++str;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
bool detail::skip_if(detail::cxtoken_stream& stream, const char* str, bool multi_token)
|
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 next_kind == CXToken_Literal;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
detail::cxtoken_iterator detail::find_closing_bracket(detail::cxtoken_stream stream)
|
detail::cxtoken_iterator detail::find_closing_bracket(detail::cxtoken_stream stream)
|
||||||
{
|
{
|
||||||
|
|
@ -483,8 +483,9 @@ namespace
|
||||||
// (identifier ::)_opt identifier ( '(' some tokens ')' )_opt ..._opt
|
// (identifier ::)_opt identifier ( '(' some tokens ')' )_opt ..._opt
|
||||||
|
|
||||||
// parse name
|
// parse name
|
||||||
DEBUG_ASSERT(stream.peek().kind() == CXToken_Identifier, detail::parse_error_handler{},
|
DEBUG_ASSERT(stream.peek().kind() == CXToken_Identifier
|
||||||
stream.cursor(), "expected identifier");
|
|| stream.peek().kind() == CXToken_Keyword,
|
||||||
|
detail::parse_error_handler{}, stream.cursor(), "expected identifier");
|
||||||
auto name = stream.get().value().std_str();
|
auto name = stream.get().value().std_str();
|
||||||
if (skip_if(stream, "::"))
|
if (skip_if(stream, "::"))
|
||||||
{
|
{
|
||||||
|
|
@ -493,8 +494,9 @@ namespace
|
||||||
"attribute using + scope not allowed");
|
"attribute using + scope not allowed");
|
||||||
scope = std::move(name);
|
scope = std::move(name);
|
||||||
|
|
||||||
DEBUG_ASSERT(stream.peek().kind() == CXToken_Identifier, detail::parse_error_handler{},
|
DEBUG_ASSERT(stream.peek().kind() == CXToken_Identifier
|
||||||
stream.cursor(), "expected identifier");
|
|| stream.peek().kind() == CXToken_Keyword,
|
||||||
|
detail::parse_error_handler{}, stream.cursor(), "expected identifier");
|
||||||
name = stream.get().value().std_str();
|
name = stream.get().value().std_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -545,12 +547,23 @@ namespace
|
||||||
auto arguments = parse_attribute_arguments(stream);
|
auto arguments = parse_attribute_arguments(stream);
|
||||||
result.push_back(cpp_attribute(cpp_attribute_kind::alignas_, std::move(arguments)));
|
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
|
// GCC/clang attributes
|
||||||
// __attribute__(<attribute>)
|
// __attribute__((<attribute>))
|
||||||
// ^
|
// ^^
|
||||||
skip_brackets(stream);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
else if (skip_if(stream, "__declspec"))
|
else if (skip_if(stream, "__declspec"))
|
||||||
|
|
@ -558,13 +571,21 @@ namespace
|
||||||
// MSVC declspec
|
// MSVC declspec
|
||||||
// __declspec(<attribute>)
|
// __declspec(<attribute>)
|
||||||
// ^
|
// ^
|
||||||
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
cpp_attribute_list detail::parse_attributes(detail::cxtoken_stream& stream, bool skip_anway)
|
cpp_attribute_list detail::parse_attributes(detail::cxtoken_stream& stream, bool skip_anway)
|
||||||
{
|
{
|
||||||
|
|
@ -612,7 +633,7 @@ namespace
|
||||||
DEBUG_UNREACHABLE(detail::assert_handler{});
|
DEBUG_UNREACHABLE(detail::assert_handler{});
|
||||||
return cpp_token_kind::punctuation;
|
return cpp_token_kind::punctuation;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
cpp_token_string detail::to_string(cxtoken_stream& stream, cxtoken_iterator end)
|
cpp_token_string detail::to_string(cxtoken_stream& stream, cxtoken_iterator end)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,9 @@ TEST_CASE("cpp_attribute")
|
||||||
// alignas
|
// alignas
|
||||||
struct alignas(8) type {};
|
struct alignas(8) type {};
|
||||||
alignas(type) int var;
|
alignas(type) int var;
|
||||||
|
|
||||||
|
// keyword attributes
|
||||||
|
[[const]] int k();
|
||||||
)";
|
)";
|
||||||
|
|
||||||
auto file = parse({}, "cpp_attribute.cpp", code);
|
auto file = parse({}, "cpp_attribute.cpp", code);
|
||||||
|
|
@ -113,9 +116,12 @@ alignas(type) int var;
|
||||||
else if (e.name() == "j")
|
else if (e.name() == "j")
|
||||||
check_attribute(attr, "noreturn", type_safe::nullopt,
|
check_attribute(attr, "noreturn", type_safe::nullopt,
|
||||||
false, "", cpp_attribute_kind::noreturn);
|
false, "", cpp_attribute_kind::noreturn);
|
||||||
|
else if (e.name() == "k")
|
||||||
|
check_attribute(attr, "const", type_safe::nullopt, false,
|
||||||
|
"", cpp_attribute_kind::unknown);
|
||||||
},
|
},
|
||||||
false);
|
false);
|
||||||
REQUIRE(count == 9);
|
REQUIRE(count == 10);
|
||||||
|
|
||||||
count = test_visit<cpp_class>(*file,
|
count = test_visit<cpp_class>(*file,
|
||||||
[&](const cpp_entity& e) {
|
[&](const cpp_entity& e) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue