Skip to content

[clang-format] Fix SpaceBeforeParens with explicit template instantiations#183183

Merged
HazardyKnusperkeks merged 2 commits intollvm:mainfrom
bdunkin:bdunkin/fix-space-before-paren-template-specialization
Feb 27, 2026
Merged

[clang-format] Fix SpaceBeforeParens with explicit template instantiations#183183
HazardyKnusperkeks merged 2 commits intollvm:mainfrom
bdunkin:bdunkin/fix-space-before-paren-template-specialization

Conversation

@bdunkin
Copy link
Contributor

@bdunkin bdunkin commented Feb 24, 2026

This fixes explicit template instantiated functions not having spaces added/removed based on the value of SpaceBeforeParens.

Attribution Note - I have been authorized to contribute this change on behalf of my company: ArenaNet LLC

@llvmbot
Copy link
Member

llvmbot commented Feb 24, 2026

@llvm/pr-subscribers-clang-format

Author: Ben Dunkin (bdunkin)

Changes

This fixes explicit template instantiated functions not having spaces added/removed based on the value of SpaceBeforeParens.

Attribution Note - I have been authorized to contribute this change on behalf of my company: ArenaNet LLC


Full diff: https://github.com/llvm/llvm-project/pull/183183.diff

2 Files Affected:

  • (modified) clang/lib/Format/TokenAnnotator.cpp (+3-1)
  • (modified) clang/unittests/Format/FormatTest.cpp (+4)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 34e81bbc97578..8f235cfd6458c 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -4913,8 +4913,10 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
     return true;
   // Space before parentheses common for all languages
   if (Right.is(tok::l_paren)) {
-    if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen))
+    if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen) &&
+        !Line.MightBeFunctionDecl) {
       return spaceRequiredBeforeParens(Right);
+    }
     if (Left.isOneOf(TT_RequiresClause,
                      TT_RequiresClauseInARequiresExpression)) {
       return Style.SpaceBeforeParensOptions.AfterRequiresInClause ||
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 43633b582a8ab..dfc21bcefad53 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -17334,6 +17334,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
   verifyFormat("void f(int a, T b) {}", SpaceFuncDecl);
   verifyFormat("void __attribute__((asdf)) f(int a, T b) {}", SpaceFuncDecl);
   verifyFormat("A::A() : a(1) {}", SpaceFuncDecl);
+  verifyFormat("template <> void A<C> (C x);", SpaceFuncDecl);
+  verifyFormat("template <> void A<C>(C x) {}", SpaceFuncDecl);
   verifyFormat("void f () __attribute__((asdf));", SpaceFuncDecl);
   verifyFormat("void __attribute__((asdf)) f ();", SpaceFuncDecl);
   verifyFormat("#define A(x) x", SpaceFuncDecl);
@@ -17370,6 +17372,8 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
   verifyFormat("void f (int a, T b) {}", SpaceFuncDef);
   verifyFormat("void __attribute__((asdf)) f (int a, T b) {}", SpaceFuncDef);
   verifyFormat("A::A () : a(1) {}", SpaceFuncDef);
+  verifyFormat("template <> void A<C>(C x);", SpaceFuncDef);
+  verifyFormat("template <> void A<C> (C x) {}", SpaceFuncDef);
   verifyFormat("void f() __attribute__((asdf));", SpaceFuncDef);
   verifyFormat("void __attribute__((asdf)) f();", SpaceFuncDef);
   verifyFormat("#define A(x) x", SpaceFuncDef);

// Space before parentheses common for all languages
if (Right.is(tok::l_paren)) {
if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen))
if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it suffice (and not break anything) to move line 4964 up here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried it, and it does pass all the formatting tests including the new ones. Would that be preferred to the current change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say move the if. That's less code, and basically what you did do with your first approach. And I think the intent is clearer.

… function type signatures, rather than change the checks based on review feedback.
@HazardyKnusperkeks HazardyKnusperkeks merged commit 3d889c4 into llvm:main Feb 27, 2026
10 checks passed
sujianIBM pushed a commit to sujianIBM/llvm-project that referenced this pull request Mar 5, 2026
…tions (llvm#183183)

This fixes explicit template instantiated functions not having spaces
added/removed based on the value of `SpaceBeforeParens`.

Attribution Note - I have been authorized to contribute this change on
behalf of my company: ArenaNet LLC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants