Author: Owen Pan Date: 2024-06-16T13:50:59-07:00 New Revision: a106131a34ed87f597c78183ada56f01fd17641d
URL: https://github.com/llvm/llvm-project/commit/a106131a34ed87f597c78183ada56f01fd17641d DIFF: https://github.com/llvm/llvm-project/commit/a106131a34ed87f597c78183ada56f01fd17641d.diff LOG: [clang-format] Handle AttributeMacro before access modifiers (#95634) Closes #95094. Added: Modified: clang/lib/Format/TokenAnnotator.cpp clang/lib/Format/TokenAnnotator.h clang/lib/Format/UnwrappedLineFormatter.cpp clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/FormatTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1fe3b61a5a81f..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) || @@ -1998,6 +2000,8 @@ class AnnotatingParser { if (!consumeToken()) return LT_Invalid; } + if (Line.Type == LT_AccessModifier) + 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..f4f2bba0eb217 100644 --- a/clang/lib/Format/TokenAnnotator.h +++ b/clang/lib/Format/TokenAnnotator.h @@ -22,6 +22,8 @@ namespace format { enum LineType { LT_Invalid, + // Contains public/private/protected followed by TT_InheritanceColon. + LT_AccessModifier, LT_ImportStatement, LT_ObjCDecl, // An @interface, @implementation, or @protocol line. LT_ObjCMethodDecl, @@ -45,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_Other), Level(Line.Level), PPLevel(Line.PPLevel), MatchingOpeningBlockLineIndex(Line.MatchingOpeningBlockLineIndex), MatchingClosingBlockLineIndex(Line.MatchingClosingBlockLineIndex), 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/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 fb57333858529..fc63afce70042 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(x) protected:\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) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits