From b646f0955574c6ad4c156c9db522e46f597cfda9 Mon Sep 17 00:00:00 2001 From: Huang Zhen-Hong Date: Wed, 29 Jun 2022 15:09:05 +0800 Subject: [PATCH] [clang-format] Fix misplacement of `*` in declaration of pointer to struct Fixes #55810 Differential Revision: https://reviews.llvm.org/D127873 --- clang/lib/Format/TokenAnnotator.cpp | 25 ++++++++ clang/unittests/Format/FormatTest.cpp | 61 +++++++++++++++++++ clang/unittests/Format/TokenAnnotatorTest.cpp | 26 ++++++++ 3 files changed, 112 insertions(+) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 1ee95f26d1fc..029cb9097871 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2314,6 +2314,31 @@ private: if (NextToken->isOneOf(tok::comma, tok::semi)) return TT_PointerOrReference; + // After right braces, star tokens are likely to be pointers to struct, + // union, or class. + // struct {} *ptr; + if (PrevToken->is(tok::r_brace) && Tok.is(tok::star)) + return TT_PointerOrReference; + + // For "} &&" + if (PrevToken->is(tok::r_brace) && Tok.is(tok::ampamp)) { + const FormatToken *MatchingLBrace = PrevToken->MatchingParen; + + // We check whether there is a TemplateCloser(">") to indicate it's a + // template or not. If it's not a template, "&&" is likely a reference + // operator. + // struct {} &&ref = {}; + if (!MatchingLBrace) + return TT_PointerOrReference; + FormatToken *BeforeLBrace = MatchingLBrace->getPreviousNonComment(); + if (!BeforeLBrace || BeforeLBrace->isNot(TT_TemplateCloser)) + return TT_PointerOrReference; + + // If it is a template, "&&" is a binary operator. + // enable_if<>{} && ... + return TT_BinaryOperator; + } + if (PrevToken->Tok.isLiteral() || PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true, tok::kw_false, tok::r_brace)) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 972f3f195d85..d6deafe1093c 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -10431,6 +10431,67 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { "void F();", getGoogleStyleWithColumns(68)); + FormatStyle Style = getLLVMStyle(); + Style.PointerAlignment = FormatStyle::PAS_Left; + verifyFormat("struct {\n" + "}* ptr;", + Style); + verifyFormat("union {\n" + "}* ptr;", + Style); + verifyFormat("class {\n" + "}* ptr;", + Style); + verifyFormat("struct {\n" + "}&& ptr = {};", + Style); + verifyFormat("union {\n" + "}&& ptr = {};", + Style); + verifyFormat("class {\n" + "}&& ptr = {};", + Style); + + Style.PointerAlignment = FormatStyle::PAS_Middle; + verifyFormat("struct {\n" + "} * ptr;", + Style); + verifyFormat("union {\n" + "} * ptr;", + Style); + verifyFormat("class {\n" + "} * ptr;", + Style); + verifyFormat("struct {\n" + "} && ptr = {};", + Style); + verifyFormat("union {\n" + "} && ptr = {};", + Style); + verifyFormat("class {\n" + "} && ptr = {};", + Style); + + Style.PointerAlignment = FormatStyle::PAS_Right; + verifyFormat("struct {\n" + "} *ptr;", + Style); + verifyFormat("union {\n" + "} *ptr;", + Style); + verifyFormat("class {\n" + "} *ptr;", + Style); + verifyFormat("struct {\n" + "} &&ptr = {};", + Style); + verifyFormat("union {\n" + "} &&ptr = {};", + Style); + verifyFormat("class {\n" + "} &&ptr = {};", + Style); + verifyIndependentOfContext("MACRO(int *i);"); verifyIndependentOfContext("MACRO(auto *a);"); verifyIndependentOfContext("MACRO(const A *a);"); diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 2dbc5da07d4d..df1b05226747 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -85,6 +85,32 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) { Tokens = annotate("case &x:"); EXPECT_EQ(Tokens.size(), 5u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::amp, TT_UnaryOperator); + + Tokens = annotate("struct {\n" + "} *ptr;"); + EXPECT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference); + Tokens = annotate("union {\n" + "} *ptr;"); + EXPECT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference); + Tokens = annotate("class {\n" + "} *ptr;"); + EXPECT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::star, TT_PointerOrReference); + + Tokens = annotate("struct {\n" + "} &&ptr = {};"); + EXPECT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_PointerOrReference); + Tokens = annotate("union {\n" + "} &&ptr = {};"); + EXPECT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_PointerOrReference); + Tokens = annotate("class {\n" + "} &&ptr = {};"); + EXPECT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[3], tok::ampamp, TT_PointerOrReference); } TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) { -- 2.34.1