Skip to content

Commit 03b6ccc

Browse files
committed
[clang-format] Add SpaceBetweenUnderscoreParens option for GNU gettext macro
This adds a new configuration option SpaceBetweenUnderscoreParens to control spacing between underscore and opening parenthesis. This is specifically designed for the gettext internationalization macro '_()' commonly used in GNU projects like GDB. The option: - Defaults to true for LLVM style (preserving existing behavior) - Defaults to false for GNU style (removes space before '_(') - Only affects single underscore tokens '_', not other identifiers - Leaves all other spacing rules unchanged Examples: GNU style with SpaceBetweenUnderscoreParens=false: printf(_("Hello")); // No space before '_(' my_func (arg); // Space before other functions preserved LLVM style with SpaceBetweenUnderscoreParens=true: printf(_ ("Hello")); // Standard spacing rules apply This addresses the common pattern in GNU software where gettext messages use '_()' without spaces, improving consistency with GNU coding standards.
1 parent 70529df commit 03b6ccc

File tree

5 files changed

+62
-0
lines changed

5 files changed

+62
-0
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6605,6 +6605,18 @@ the configuration (without a prefix: ``Auto``).
66056605
int a [5]; vs. int a[5];
66066606
int a [5][5]; vs. int a[5][5];
66076607

6608+
.. _SpaceBetweenUnderscoreParens:
6609+
6610+
**SpaceBetweenUnderscoreParens** (``Boolean``) :versionbadge:`clang-format 19` :ref:`<SpaceBetweenUnderscoreParens>`
6611+
If ``false``, spaces will be removed between underscore and an opening
6612+
parenthesis. This is specifically for the gettext macro ``_()`` commonly
6613+
used in GNU projects.
6614+
6615+
.. code-block:: c++
6616+
6617+
true: false:
6618+
_ (message); vs. _(message);
6619+
66086620
.. _SpaceInEmptyBlock:
66096621

66106622
**SpaceInEmptyBlock** (``Boolean``) :versionbadge:`clang-format 10` :ref:`<SpaceInEmptyBlock>`

clang/include/clang/Format/Format.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4896,6 +4896,16 @@ struct FormatStyle {
48964896
/// \version 10
48974897
// bool SpaceInEmptyBlock;
48984898

4899+
/// If ``false``, spaces will be removed between underscore and an opening
4900+
/// parenthesis. This is specifically for the gettext macro ``_()`` commonly
4901+
/// used in GNU projects.
4902+
/// \code
4903+
/// true: false:
4904+
/// _ (message); vs. _(message);
4905+
/// \endcode
4906+
/// \version 19
4907+
bool SpaceBetweenUnderscoreParens;
4908+
48994909
/// Style of when to insert a space in empty braces.
49004910
enum SpaceInEmptyBracesStyle : int8_t {
49014911
/// Always insert a space in empty braces.

clang/lib/Format/Format.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,8 @@ template <> struct MappingTraits<FormatStyle> {
12191219
Style.SpaceBeforeCtorInitializerColon);
12201220
IO.mapOptional("SpaceBeforeInheritanceColon",
12211221
Style.SpaceBeforeInheritanceColon);
1222+
IO.mapOptional("SpaceBetweenUnderscoreParens",
1223+
Style.SpaceBetweenUnderscoreParens);
12221224
IO.mapOptional("SpaceBeforeJsonColon", Style.SpaceBeforeJsonColon);
12231225
IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens);
12241226
IO.mapOptional("SpaceBeforeParensOptions", Style.SpaceBeforeParensOptions);
@@ -1713,6 +1715,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
17131715
LLVMStyle.SpaceBeforeCpp11BracedList = false;
17141716
LLVMStyle.SpaceBeforeCtorInitializerColon = true;
17151717
LLVMStyle.SpaceBeforeInheritanceColon = true;
1718+
LLVMStyle.SpaceBetweenUnderscoreParens = true;
17161719
LLVMStyle.SpaceBeforeJsonColon = false;
17171720
LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
17181721
LLVMStyle.SpaceBeforeParensOptions = {};
@@ -2044,6 +2047,7 @@ FormatStyle getGNUStyle() {
20442047
Style.FixNamespaceComments = false;
20452048
Style.KeepFormFeed = true;
20462049
Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
2050+
Style.SpaceBetweenUnderscoreParens = false;
20472051
return Style;
20482052
}
20492053

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4901,6 +4901,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
49014901
// Handle builtins like identifiers.
49024902
if (Line.Type != LT_PreprocessorDirective &&
49034903
(Left.Tok.getIdentifierInfo() || Left.is(tok::r_paren))) {
4904+
// Check for special case: single underscore token (gettext macro).
4905+
if (Left.Tok.getIdentifierInfo() && !Style.SpaceBetweenUnderscoreParens &&
4906+
Left.TokenText == "_") {
4907+
return false;
4908+
}
49044909
return spaceRequiredBeforeParens(Right);
49054910
}
49064911
return false;

clang/unittests/Format/FormatTest.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17852,6 +17852,37 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) {
1785217852
Spaces);
1785317853
}
1785417854

17855+
TEST_F(FormatTest, SpaceBetweenUnderscoreParens) {
17856+
FormatStyle Style = getLLVMStyle();
17857+
Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
17858+
17859+
EXPECT_TRUE(Style.SpaceBetweenUnderscoreParens);
17860+
verifyFormat("func (arg);", Style);
17861+
verifyFormat("my_func (arg);", Style);
17862+
verifyFormat("_ (message);", Style);
17863+
verifyFormat("underscore_ (param);", Style);
17864+
17865+
Style.SpaceBetweenUnderscoreParens = false;
17866+
verifyFormat("func (arg);", Style);
17867+
verifyFormat("my_func (arg);", Style);
17868+
verifyFormat("_(message);", Style);
17869+
verifyFormat("underscore_ (param);", Style);
17870+
verifyFormat("_private_func (data);", Style);
17871+
17872+
FormatStyle GNUStyle = getGNUStyle();
17873+
EXPECT_FALSE(GNUStyle.SpaceBetweenUnderscoreParens);
17874+
EXPECT_EQ(GNUStyle.SpaceBeforeParens, FormatStyle::SBPO_Always);
17875+
verifyFormat("func (arg);", GNUStyle);
17876+
verifyFormat("my_func (arg);", GNUStyle);
17877+
verifyFormat("_(message);", GNUStyle);
17878+
verifyFormat("_private_func (data);", GNUStyle);
17879+
17880+
verifyFormat("printf (_(\"Hello\"));\n"
17881+
"func (arg);\n"
17882+
"_(\"World\");",
17883+
GNUStyle);
17884+
}
17885+
1785517886
TEST_F(FormatTest, ConfigurableSpacesInSquareBrackets) {
1785617887
verifyFormat("int a[5];");
1785717888
verifyFormat("a[3] += 42;");

0 commit comments

Comments
 (0)