sammccall created this revision.
sammccall added a reviewer: benhamilton.
sammccall requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
The second space in `void foo() &` is always produced by clang-format,
and isn't evidence of any particular style.
Before this patch, it was considered evidence of PAS_Right, because
there is a space before a pointerlike ampersand.
This caused the following code to have "unstable" pointer alignment:
void a() &;
void b() &;
int *x;
PAS_Left, Derive=false would produce 'int* x' with other lines unchanged.
But subsequent formatting with Derive=true would produce 'int *x' again.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D118921
Files:
clang/lib/Format/Format.cpp
clang/unittests/Format/FormatTest.cpp
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -9683,6 +9683,25 @@
AlignLeftBreakTemplate);
verifyFormat("void (*foopt)(int) = &func;");
+
+ FormatStyle DerivePointerAlignment = getLLVMStyle();
+ DerivePointerAlignment.DerivePointerAlignment = true;
+ // There's always a space between the function and its trailing qualifiers.
+ // This isn't evidence for PAS_Right (or for PAS_Left).
+ std::string Prefix = "void a() &;\n"
+ "void b() &;\n";
+ verifyFormat(Prefix + "int* x;", DerivePointerAlignment);
+ verifyFormat(Prefix + "int *x;", DerivePointerAlignment);
+ // Same if the function is an overloaded operator instead.
+ Prefix = "void operator()() &;\n"
+ "void operator()() &;\n";
+ verifyFormat(Prefix + "int* x;", DerivePointerAlignment);
+ verifyFormat(Prefix + "int *x;", DerivePointerAlignment);
+ // However a space between cv-qualifiers and ref-qualifiers *is* evidence.
+ Prefix = "void a() const &;\n"
+ "void b() const &;\n";
+ EXPECT_EQ(Prefix + "int *x;",
+ format(Prefix + "int* x;", DerivePointerAlignment));
}
TEST_F(FormatTest, UnderstandsNewAndDelete) {
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -18,6 +18,7 @@
#include "ContinuationIndenter.h"
#include "DefinitionBlockSeparator.h"
#include "FormatInternal.h"
+#include "FormatToken.h"
#include "FormatTokenLexer.h"
#include "NamespaceEndCommentsFixer.h"
#include "QualifierAlignmentFixer.h"
@@ -1945,6 +1946,17 @@
for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
if (!Tok->is(TT_PointerOrReference))
continue;
+ // Don't treat space in `void foo() &&` as evidence.
+ if (const auto *Prev = Tok->getPreviousNonComment()) {
+ if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
+ if (const auto *Func =
+ Prev->MatchingParen->getPreviousNonComment()) {
+ if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
+ TT_OverloadedOperator))
+ continue;
+ }
+ }
+ }
bool SpaceBefore = Tok->hasWhitespaceBefore();
bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
if (SpaceBefore && !SpaceAfter)
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -9683,6 +9683,25 @@
AlignLeftBreakTemplate);
verifyFormat("void (*foopt)(int) = &func;");
+
+ FormatStyle DerivePointerAlignment = getLLVMStyle();
+ DerivePointerAlignment.DerivePointerAlignment = true;
+ // There's always a space between the function and its trailing qualifiers.
+ // This isn't evidence for PAS_Right (or for PAS_Left).
+ std::string Prefix = "void a() &;\n"
+ "void b() &;\n";
+ verifyFormat(Prefix + "int* x;", DerivePointerAlignment);
+ verifyFormat(Prefix + "int *x;", DerivePointerAlignment);
+ // Same if the function is an overloaded operator instead.
+ Prefix = "void operator()() &;\n"
+ "void operator()() &;\n";
+ verifyFormat(Prefix + "int* x;", DerivePointerAlignment);
+ verifyFormat(Prefix + "int *x;", DerivePointerAlignment);
+ // However a space between cv-qualifiers and ref-qualifiers *is* evidence.
+ Prefix = "void a() const &;\n"
+ "void b() const &;\n";
+ EXPECT_EQ(Prefix + "int *x;",
+ format(Prefix + "int* x;", DerivePointerAlignment));
}
TEST_F(FormatTest, UnderstandsNewAndDelete) {
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -18,6 +18,7 @@
#include "ContinuationIndenter.h"
#include "DefinitionBlockSeparator.h"
#include "FormatInternal.h"
+#include "FormatToken.h"
#include "FormatTokenLexer.h"
#include "NamespaceEndCommentsFixer.h"
#include "QualifierAlignmentFixer.h"
@@ -1945,6 +1946,17 @@
for (FormatToken *Tok = Line->First; Tok && Tok->Next; Tok = Tok->Next) {
if (!Tok->is(TT_PointerOrReference))
continue;
+ // Don't treat space in `void foo() &&` as evidence.
+ if (const auto *Prev = Tok->getPreviousNonComment()) {
+ if (Prev->is(tok::r_paren) && Prev->MatchingParen) {
+ if (const auto *Func =
+ Prev->MatchingParen->getPreviousNonComment()) {
+ if (Func->isOneOf(TT_FunctionDeclarationName, TT_StartOfName,
+ TT_OverloadedOperator))
+ continue;
+ }
+ }
+ }
bool SpaceBefore = Tok->hasWhitespaceBefore();
bool SpaceAfter = Tok->Next->hasWhitespaceBefore();
if (SpaceBefore && !SpaceAfter)
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits