Expose __attribute__ and __declspec

This commit is contained in:
Jonathan Müller 2018-03-28 18:26:16 +02:00
commit 7b030190bd
2 changed files with 42 additions and 15 deletions

View file

@ -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();
}
@ -545,12 +547,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__(<attribute>)
// ^
skip_brackets(stream);
// __attribute__((<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,13 +571,21 @@ namespace
// MSVC declspec
// __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 false;
}
}
} // namespace
cpp_attribute_list detail::parse_attributes(detail::cxtoken_stream& stream, bool skip_anway)
{
@ -612,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)
{

View file

@ -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<cpp_class>(*file,
[&](const cpp_entity& e) {