aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Pan <owenpiano@gmail.com>2024-03-16 13:51:36 -0700
committerGitHub <noreply@github.com>2024-03-16 13:51:36 -0700
commit84b5178124e47f6019b56c04abcfb978a94b1c3c (patch)
treec7f15ee2aeeb8e648bf0dd23418e11f274ca4eb0
parent2867095917cef0d01a68b112bcb01e2f85de4308 (diff)
downloadllvm-84b5178124e47f6019b56c04abcfb978a94b1c3c.zip
llvm-84b5178124e47f6019b56c04abcfb978a94b1c3c.tar.gz
llvm-84b5178124e47f6019b56c04abcfb978a94b1c3c.tar.bz2
[clang-format] Correctly parse C++11 attributes in enum specifiers (#85498)
Fixes #85476.
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp15
-rw-r--r--clang/unittests/Format/FormatTest.cpp21
2 files changed, 30 insertions, 6 deletions
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index a1f6ce0..2b893f7 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -1224,7 +1224,6 @@ void UnwrappedLineParser::parsePPUnknown() {
static bool tokenCanStartNewLine(const FormatToken &Tok) {
// Semicolon can be a null-statement, l_square can be a start of a macro or
// a C++11 attribute, but this doesn't seem to be common.
- assert(Tok.isNot(TT_AttributeSquare));
return !Tok.isOneOf(tok::semi, tok::l_brace,
// Tokens that can only be used as binary operators and a
// part of overloaded operator names.
@@ -3712,14 +3711,19 @@ bool UnwrappedLineParser::parseEnum() {
if (Style.Language == FormatStyle::LK_Proto && FormatTok->is(tok::equal))
return false;
- // Eat up enum class ...
- if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
- nextToken();
+ if (IsCpp) {
+ // Eat up enum class ...
+ if (FormatTok->isOneOf(tok::kw_class, tok::kw_struct))
+ nextToken();
+ while (FormatTok->is(tok::l_square))
+ if (!handleCppAttributes())
+ return false;
+ }
while (FormatTok->Tok.getIdentifierInfo() ||
FormatTok->isOneOf(tok::colon, tok::coloncolon, tok::less,
tok::greater, tok::comma, tok::question,
- tok::l_square, tok::r_square)) {
+ tok::l_square)) {
if (Style.isVerilog()) {
FormatTok->setFinalizedType(TT_VerilogDimensionedTypeName);
nextToken();
@@ -3732,7 +3736,6 @@ bool UnwrappedLineParser::parseEnum() {
// We can have macros or attributes in between 'enum' and the enum name.
if (FormatTok->is(tok::l_paren))
parseParens();
- assert(FormatTok->isNot(TT_AttributeSquare));
if (FormatTok->is(tok::identifier)) {
nextToken();
// If there are two identifiers in a row, this is likely an elaborate
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index fc367a7..add92d3 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -3802,6 +3802,27 @@ TEST_F(FormatTest, FormatsEnum) {
" // Comment 2\n"
" TWO,\n"
"};");
+ verifyFormat("enum [[clang::enum_extensibility(open)]] E {\n"
+ " // Comment 1\n"
+ " ONE,\n"
+ " // Comment 2\n"
+ " TWO\n"
+ "};");
+ verifyFormat("enum [[nodiscard]] [[clang::enum_extensibility(open)]] E {\n"
+ " // Comment 1\n"
+ " ONE,\n"
+ " // Comment 2\n"
+ " TWO\n"
+ "};");
+ verifyFormat("enum [[clang::enum_extensibility(open)]] E { // foo\n"
+ " A,\n"
+ " // bar\n"
+ " B\n"
+ "};",
+ "enum [[clang::enum_extensibility(open)]] E{// foo\n"
+ " A,\n"
+ " // bar\n"
+ " B};");
// Not enums.
verifyFormat("enum X f() {\n"