Skip to content

Commit

Permalink
[clang-format] Treats &/&& as reference when followed by ',' or ')'
Browse files Browse the repository at this point in the history
Ran into an issue where function declarations inside function
scopes or uses of sizeof inside a function would treat the && in
'sizeof(Type &&)' as a binary operator.

Attempt to fix this by assuming reference when followed by ',' or
')'. Also adds tests for these.

Also hit an edge case in another test that treated "and" the same
as "&&" since it parses as C++. Changed the "and" to "also" so it
is no longer a keyword.

Fixes #58923.

Differential Revision: https://reviews.llvm.org/D137755
  • Loading branch information
red1bluelost authored and owenca committed Nov 12, 2022
1 parent 96e2390 commit e864ac6
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 2 deletions.
3 changes: 2 additions & 1 deletion clang/lib/Format/TokenAnnotator.cpp
Expand Up @@ -2356,7 +2356,8 @@ class AnnotatingParser {
return TT_BinaryOperator;

if (!NextToken ||
NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept) ||
NextToken->isOneOf(tok::arrow, tok::equal, tok::kw_noexcept, tok::comma,
tok::r_paren) ||
NextToken->canBePointerOrReferenceQualifier() ||
(NextToken->is(tok::l_brace) && !NextToken->getNextNonComment())) {
return TT_PointerOrReference;
Expand Down
22 changes: 21 additions & 1 deletion clang/unittests/Format/FormatTest.cpp
Expand Up @@ -2132,6 +2132,10 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
verifyFormat("int *a = f1();", Style);
verifyFormat("int &b = f2();", Style);
verifyFormat("int &&c = f3();", Style);
verifyFormat("int f3() { return sizeof(Foo &); }", Style);
verifyFormat("int f4() { return sizeof(Foo &&); }", Style);
verifyFormat("void f5() { int f6(Foo &, Bar &); }", Style);
verifyFormat("void f5() { int f6(Foo &&, Bar &&); }", Style);
verifyFormat("for (auto a = 0, b = 0; const auto &c : {1, 2, 3})", Style);
verifyFormat("for (auto a = 0, b = 0; const int &c : {1, 2, 3})", Style);
verifyFormat("for (auto a = 0, b = 0; const Foo &c : {1, 2, 3})", Style);
Expand Down Expand Up @@ -2171,6 +2175,10 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
verifyFormat("int* a = f1();", Style);
verifyFormat("int& b = f2();", Style);
verifyFormat("int&& c = f3();", Style);
verifyFormat("int f3() { return sizeof(Foo&); }", Style);
verifyFormat("int f4() { return sizeof(Foo&&); }", Style);
verifyFormat("void f5() { int f6(Foo&, Bar&); }", Style);
verifyFormat("void f5() { int f6(Foo&&, Bar&&); }", Style);
verifyFormat("for (auto a = 0, b = 0; const auto& c : {1, 2, 3})", Style);
verifyFormat("for (auto a = 0, b = 0; const int& c : {1, 2, 3})", Style);
verifyFormat("for (auto a = 0, b = 0; const Foo& c : {1, 2, 3})", Style);
Expand Down Expand Up @@ -2211,6 +2219,10 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
verifyFormat("int *a = f1();", Style);
verifyFormat("int& b = f2();", Style);
verifyFormat("int&& c = f3();", Style);
verifyFormat("int f3() { return sizeof(Foo&); }", Style);
verifyFormat("int f4() { return sizeof(Foo&&); }", Style);
verifyFormat("void f5() { int f6(Foo&, Bar&); }", Style);
verifyFormat("void f5() { int f6(Foo&&, Bar&&); }", Style);
verifyFormat("for (auto a = 0, b = 0; const Foo *c : {1, 2, 3})", Style);
verifyFormat("for (int a = 0, b = 0; const Foo *c : {1, 2, 3})", Style);
verifyFormat("for (int a = 0, b++; const Foo *c : {1, 2, 3})", Style);
Expand All @@ -2232,6 +2244,10 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
verifyFormat("int* a = f1();", Style);
verifyFormat("int & b = f2();", Style);
verifyFormat("int && c = f3();", Style);
verifyFormat("int f3() { return sizeof(Foo &); }", Style);
verifyFormat("int f4() { return sizeof(Foo &&); }", Style);
verifyFormat("void f5() { int f6(Foo &, Bar &); }", Style);
verifyFormat("void f5() { int f6(Foo &&, Bar &&); }", Style);
verifyFormat("for (auto a = 0, b = 0; const auto & c : {1, 2, 3})", Style);
verifyFormat("for (auto a = 0, b = 0; const int & c : {1, 2, 3})", Style);
verifyFormat("for (auto a = 0, b = 0; const Foo & c : {1, 2, 3})", Style);
Expand Down Expand Up @@ -2268,6 +2284,10 @@ TEST_F(FormatTest, SeparatePointerReferenceAlignment) {
verifyFormat("int * a = f1();", Style);
verifyFormat("int &b = f2();", Style);
verifyFormat("int &&c = f3();", Style);
verifyFormat("int f3() { return sizeof(Foo &); }", Style);
verifyFormat("int f4() { return sizeof(Foo &&); }", Style);
verifyFormat("void f5() { int f6(Foo &, Bar &); }", Style);
verifyFormat("void f5() { int f6(Foo &&, Bar &&); }", Style);
verifyFormat("for (auto a = 0, b = 0; const Foo * c : {1, 2, 3})", Style);
verifyFormat("for (int a = 0, b = 0; const Foo * c : {1, 2, 3})", Style);
verifyFormat("for (int a = 0, b++; const Foo * c : {1, 2, 3})", Style);
Expand Down Expand Up @@ -9034,7 +9054,7 @@ TEST_F(FormatTest, AlignsStringLiterals) {
" \"looooooooooooooooooooooooooooooooooooooooooooooooong literal\");");
verifyFormat("someFunction(\"Always break between multi-line\"\n"
" \" string literals\",\n"
" and, other, parameters);");
" also, other, parameters);");
EXPECT_EQ("fun + \"1243\" /* comment */\n"
" \"5678\";",
format("fun + \"1243\" /* comment */\n"
Expand Down
18 changes: 18 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Expand Up @@ -157,6 +157,24 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
Tokens = annotate("if (Foo* Bar = getObj())");
ASSERT_EQ(Tokens.size(), 11u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference);

Tokens = annotate("int f3() { return sizeof(Foo&); }");
ASSERT_EQ(Tokens.size(), 14u) << Tokens;
EXPECT_TOKEN(Tokens[9], tok::amp, TT_PointerOrReference);

Tokens = annotate("int f4() { return sizeof(Foo&&); }");
ASSERT_EQ(Tokens.size(), 14u) << Tokens;
EXPECT_TOKEN(Tokens[9], tok::ampamp, TT_PointerOrReference);

Tokens = annotate("void f5() { int f6(Foo&, Bar&); }");
ASSERT_EQ(Tokens.size(), 17u) << Tokens;
EXPECT_TOKEN(Tokens[9], tok::amp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[12], tok::amp, TT_PointerOrReference);

Tokens = annotate("void f7() { int f8(Foo&&, Bar&&); }");
ASSERT_EQ(Tokens.size(), 17u) << Tokens;
EXPECT_TOKEN(Tokens[9], tok::ampamp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[12], tok::ampamp, TT_PointerOrReference);
}

TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {
Expand Down

0 comments on commit e864ac6

Please sign in to comment.