[clang] [clang-format] Add AccessModifierMacros option (PR #187521)
Leszek Swirski via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 19 08:28:53 PDT 2026
https://github.com/LeszekSwirski updated https://github.com/llvm/llvm-project/pull/187521
>From c4062cc7fa89db83702326c072b2d3ca407496c6 Mon Sep 17 00:00:00 2001
From: Leszek Swirski <leszeks at google.com>
Date: Thu, 19 Mar 2026 16:22:13 +0100
Subject: [PATCH] [clang-format] Add AccessModifierMacros option
Fixes #64763.
This option allows users to specify custom macros that are treated as access modifiers.
---
clang/include/clang/Format/Format.h | 8 +++++++-
clang/lib/Format/Format.cpp | 1 +
clang/lib/Format/FormatToken.h | 4 +++-
clang/lib/Format/FormatTokenLexer.cpp | 4 ++++
clang/lib/Format/TokenAnnotator.cpp | 2 +-
clang/unittests/Format/FormatTest.cpp | 19 +++++++++++++++++++
6 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index c7e57d47f9ed1..d514cc539dd9d 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -62,6 +62,11 @@ struct FormatStyle {
/// \version 3.3
int AccessModifierOffset;
+ /// A list of macros that should be interpreted as access modifiers instead of
+ /// as a regular identifier.
+ /// \version 22
+ std::vector<std::string> AccessModifierMacros;
+
/// If ``true``, horizontally aligns arguments after an open bracket.
///
/// \code
@@ -5638,7 +5643,8 @@ struct FormatStyle {
WrapNamespaceBodyWithEmptyLinesStyle WrapNamespaceBodyWithEmptyLines;
bool operator==(const FormatStyle &R) const {
- return AccessModifierOffset == R.AccessModifierOffset &&
+ return AccessModifierMacros == R.AccessModifierMacros &&
+ AccessModifierOffset == R.AccessModifierOffset &&
AlignAfterOpenBracket == R.AlignAfterOpenBracket &&
AlignArrayOfStructures == R.AlignArrayOfStructures &&
AlignConsecutiveAssignments == R.AlignConsecutiveAssignments &&
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index f0e9aff2fd21a..96fb0b37990d7 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -1077,6 +1077,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("UseCRLF", UseCRLF);
}
+ IO.mapOptional("AccessModifierMacros", Style.AccessModifierMacros);
IO.mapOptional("AccessModifierOffset", Style.AccessModifierOffset);
IO.mapOptional("AlignArrayOfStructures", Style.AlignArrayOfStructures);
IO.mapOptional("AlignConsecutiveAssignments",
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 56abd702aaafe..66ea234dda7fc 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -25,6 +25,7 @@ namespace clang {
namespace format {
#define LIST_TOKEN_TYPES \
+ TYPE(AccessModifierMacro) \
TYPE(AfterPPDirective) \
TYPE(ArrayInitializerLSquare) \
TYPE(ArraySubscriptLSquare) \
@@ -705,7 +706,8 @@ struct FormatToken {
}
bool isAccessSpecifierKeyword() const {
- return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private);
+ return isOneOf(tok::kw_public, tok::kw_protected, tok::kw_private) ||
+ is(TT_AccessModifierMacro);
}
bool isAccessSpecifier(bool ColonRequired = true) const {
diff --git a/clang/lib/Format/FormatTokenLexer.cpp b/clang/lib/Format/FormatTokenLexer.cpp
index eb8658396ecde..7a8330c82528a 100644
--- a/clang/lib/Format/FormatTokenLexer.cpp
+++ b/clang/lib/Format/FormatTokenLexer.cpp
@@ -55,6 +55,10 @@ FormatTokenLexer::FormatTokenLexer(
auto Identifier = &IdentTable.get(StatementMacro);
Macros.insert({Identifier, TT_StatementMacro});
}
+ for (const std::string &AccessModifierMacro : Style.AccessModifierMacros) {
+ auto Identifier = &IdentTable.get(AccessModifierMacro);
+ Macros.insert({Identifier, TT_AccessModifierMacro});
+ }
for (const std::string &TypenameMacro : Style.TypenameMacros) {
auto Identifier = &IdentTable.get(TypenameMacro);
Macros.insert({Identifier, TT_TypenameMacro});
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 3208d8e28dd86..948c7c5abba37 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -2115,7 +2115,7 @@ class AnnotatingParser {
TT_RequiresClauseInARequiresExpression, TT_RequiresExpression,
TT_RequiresExpressionLParen, TT_RequiresExpressionLBrace,
TT_CompoundRequirementLBrace, TT_BracedListLBrace,
- TT_FunctionLikeMacro)) {
+ TT_FunctionLikeMacro, TT_AccessModifierMacro)) {
CurrentToken->setType(TT_Unknown);
}
CurrentToken->Role.reset();
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 3ee7ce38578aa..73f3e4801262a 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -13320,6 +13320,25 @@ TEST_F(FormatTest, FormatsAccessModifiers) {
NoEmptyLines);
}
+TEST_F(FormatTest, AccessModifierMacros) {
+ FormatStyle Style = getLLVMStyle();
+ Style.AccessModifierMacros.push_back("COMPREHENSIVE_O_PRIVATE");
+ Style.AccessModifierMacros.push_back("COMPREHENSIVE_O_PUBLIC");
+
+ verifyFormat("struct foo {\n"
+ "COMPREHENSIVE_O_PRIVATE:\n"
+ " void f() {}\n"
+ "\n"
+ "COMPREHENSIVE_O_PRIVATE:\n"
+ " int i;\n"
+ "\n"
+ "COMPREHENSIVE_O_PUBLIC:\n"
+ " int j;\n"
+ "};",
+ Style);
+}
+
+
TEST_F(FormatTest, FormatsAfterAccessModifiers) {
FormatStyle Style = getLLVMStyle();
More information about the cfe-commits
mailing list