https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/95634
>From 1c4ab4a5fd869de44795abd48bbaa43176e7275e Mon Sep 17 00:00:00 2001 From: Owen Pan <owenpi...@gmail.com> Date: Fri, 14 Jun 2024 23:36:58 -0700 Subject: [PATCH 1/4] [clang-format] Handle AttributeMacro before access modifiers Closes #95094. --- clang/lib/Format/TokenAnnotator.cpp | 7 ++++- clang/lib/Format/TokenAnnotator.h | 1 + clang/lib/Format/UnwrappedLineFormatter.cpp | 35 ++++++++++----------- clang/unittests/Format/FormatTest.cpp | 15 +++++++++ 4 files changed, 39 insertions(+), 19 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fe3b61a5a81f..ff00e772a75f4 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1970,6 +1970,7 @@ class AnnotatingParser { } } + bool SeenAccessModifier = false; bool KeywordVirtualFound = false; bool ImportStatement = false; @@ -1978,7 +1979,9 @@ class AnnotatingParser { ImportStatement = true; while (CurrentToken) { - if (CurrentToken->is(tok::kw_virtual)) + if (CurrentToken->isAccessSpecifier()) + SeenAccessModifier = true; + else if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; if (Style.isJavaScript()) { // export {...} from '...'; @@ -1998,6 +2001,8 @@ class AnnotatingParser { if (!consumeToken()) return LT_Invalid; } + if (SeenAccessModifier) + return LT_AccessModifier; if (KeywordVirtualFound) return LT_VirtualFunctionDecl; if (ImportStatement) diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index d19d3d061e40c..136880eca718b 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -22,6 +22,7 @@ namespace format { enum LineType { LT_Invalid, + LT_AccessModifier, // Contains public/protected/private followed by colon. LT_ImportStatement, LT_ObjCDecl, // An @interface, @implementation, or @protocol line. LT_ObjCMethodDecl, diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 4d53361aaf333..729f3d78f4a35 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -57,7 +57,7 @@ class LevelIndentTracker { /// Update the indent state given that \p Line is going to be formatted /// next. void nextLine(const AnnotatedLine &Line) { - Offset = getIndentOffset(*Line.First); + Offset = getIndentOffset(Line); // Update the indent level cache size so that we can rely on it // having the right size in adjustToUnmodifiedline. if (Line.Level >= IndentForLevel.size()) @@ -111,42 +111,41 @@ class LevelIndentTracker { /// /// For example, 'public:' labels in classes are offset by 1 or 2 /// characters to the left from their level. - int getIndentOffset(const FormatToken &RootToken) { + int getIndentOffset(const AnnotatedLine &Line) { if (Style.Language == FormatStyle::LK_Java || Style.isJavaScript() || Style.isCSharp()) { return 0; } - auto IsAccessModifier = [this, &RootToken]() { - if (RootToken.isAccessSpecifier(Style.isCpp())) { + auto IsAccessModifier = [&](const FormatToken &RootToken) { + if (Line.Type == LT_AccessModifier || RootToken.isObjCAccessSpecifier()) return true; - } else if (RootToken.isObjCAccessSpecifier()) { - return true; - } + + const auto *Next = RootToken.Next; + // Handle Qt signals. - else if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && - RootToken.Next && RootToken.Next->is(tok::colon)) { - return true; - } else if (RootToken.Next && - RootToken.Next->isOneOf(Keywords.kw_slots, - Keywords.kw_qslots) && - RootToken.Next->Next && RootToken.Next->Next->is(tok::colon)) { + if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && + Next && Next->is(tok::colon)) { return true; } - // Handle malformed access specifier e.g. 'private' without trailing ':'. - else if (!RootToken.Next && RootToken.isAccessSpecifier(false)) { + + if (Next && Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots) && + Next->Next && Next->Next->is(tok::colon)) { return true; } - return false; + + // Handle malformed access specifier e.g. 'private' without trailing ':'. + return !Next && RootToken.isAccessSpecifier(false); }; - if (IsAccessModifier()) { + if (IsAccessModifier(*Line.First)) { // The AccessModifierOffset may be overridden by IndentAccessModifiers, // in which case we take a negative value of the IndentWidth to simulate // the upper indent level. return Style.IndentAccessModifiers ? -Style.IndentWidth : Style.AccessModifierOffset; } + return 0; } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index fb57333858529..2ca85c7b70e65 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12912,6 +12912,15 @@ TEST_F(FormatTest, FormatsAccessModifiers) { " int j;\n" "};", Style); + Style.AttributeMacros.push_back("FOO"); + Style.AttributeMacros.push_back("BAR"); + verifyFormat("struct foo {\n" + "FOO private:\n" + " int i;\n" + "BAR private:\n" + " int j;\n" + "};", + Style); FormatStyle NoEmptyLines = getLLVMStyle(); NoEmptyLines.MaxEmptyLinesToKeep = 0; @@ -26130,6 +26139,12 @@ TEST_F(FormatTest, IndentAccessModifiers) { " int i;\n" "};", Style); + Style.AttributeMacros.push_back("FOO"); + verifyFormat("class C {\n" + " FOO public:\n" + " int i;\n" + "};", + Style); } TEST_F(FormatTest, LimitlessStringsAndComments) { >From fc7e0472f7970f3d4396c66ed3cade5e4579cc83 Mon Sep 17 00:00:00 2001 From: Owen Pan <owenpi...@gmail.com> Date: Sat, 15 Jun 2024 10:34:29 -0700 Subject: [PATCH 2/4] Add support for function-like `AttributeMacro`. --- clang/lib/Format/UnwrappedLineParser.cpp | 2 ++ clang/unittests/Format/FormatTest.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 899e68eadf70e..1fad02de202a3 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -368,6 +368,8 @@ bool UnwrappedLineParser::parseLevel(const FormatToken *OpeningBrace, do { if (FormatTok->isAttribute()) { nextToken(); + if (FormatTok->is(tok::l_paren)) + parseParens(); continue; } tok::TokenKind Kind = FormatTok->Tok.getKind(); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 2ca85c7b70e65..fc63afce70042 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -12917,7 +12917,7 @@ TEST_F(FormatTest, FormatsAccessModifiers) { verifyFormat("struct foo {\n" "FOO private:\n" " int i;\n" - "BAR private:\n" + "BAR(x) protected:\n" " int j;\n" "};", Style); >From 00eb2fce9f441cebe7424a7034bd254d1a925391 Mon Sep 17 00:00:00 2001 From: Owen Pan <owenpi...@gmail.com> Date: Sun, 16 Jun 2024 01:23:17 -0700 Subject: [PATCH 3/4] Set `Line.Type` to `LT_AccessModifier` only if `:` is `TT_InheritanceColon`. --- clang/lib/Format/TokenAnnotator.cpp | 9 ++++----- clang/lib/Format/TokenAnnotator.h | 3 ++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index ff00e772a75f4..1332445070314 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1419,6 +1419,8 @@ class AnnotatingParser { Tok->setType(TT_CtorInitializerColon); } else { Tok->setType(TT_InheritanceColon); + if (Prev->isOneOf(tok::kw_public, tok::kw_private, tok::kw_protected)) + Line.Type = LT_AccessModifier; } } else if (canBeObjCSelectorComponent(*Tok->Previous) && Tok->Next && (Tok->Next->isOneOf(tok::r_paren, tok::comma) || @@ -1970,7 +1972,6 @@ class AnnotatingParser { } } - bool SeenAccessModifier = false; bool KeywordVirtualFound = false; bool ImportStatement = false; @@ -1979,9 +1980,7 @@ class AnnotatingParser { ImportStatement = true; while (CurrentToken) { - if (CurrentToken->isAccessSpecifier()) - SeenAccessModifier = true; - else if (CurrentToken->is(tok::kw_virtual)) + if (CurrentToken->is(tok::kw_virtual)) KeywordVirtualFound = true; if (Style.isJavaScript()) { // export {...} from '...'; @@ -2001,7 +2000,7 @@ class AnnotatingParser { if (!consumeToken()) return LT_Invalid; } - if (SeenAccessModifier) + if (Line.Type == LT_AccessModifier) return LT_AccessModifier; if (KeywordVirtualFound) return LT_VirtualFunctionDecl; diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 136880eca718b..7a76f72c8a88a 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -22,7 +22,8 @@ namespace format { enum LineType { LT_Invalid, - LT_AccessModifier, // Contains public/protected/private followed by colon. + // Contains public/private/protected followed by TT_InheritanceColon. + LT_AccessModifier, LT_ImportStatement, LT_ObjCDecl, // An @interface, @implementation, or @protocol line. LT_ObjCMethodDecl, >From a292d93569b8793c20318048405d7463c8c55382 Mon Sep 17 00:00:00 2001 From: Owen Pan <owenpi...@gmail.com> Date: Sun, 16 Jun 2024 03:29:11 -0700 Subject: [PATCH 4/4] Initialize `AnnotatedLine::Type` in the ctor. --- clang/lib/Format/TokenAnnotator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h index 7a76f72c8a88a..08947918a51c0 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -47,7 +47,7 @@ enum ScopeType { class AnnotatedLine { public: AnnotatedLine(const UnwrappedLine &Line) - : First(Line.Tokens.front().Tok), Level(Line.Level), + : First(Line.Tokens.front().Tok), Type(LT_Invalid), Level(Line.Level), PPLevel(Line.PPLevel), MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex), MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex), _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits