jackhong12 created this revision. jackhong12 added reviewers: owenpan, MyDeveloperDay, curdeius, HazardyKnusperkeks. Herald added a project: All. jackhong12 requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
In https://reviews.llvm.org/D127873, I missed the case `bool b = 3 == int{3} && true;`. `&&` here will be annotated as a reference operator. There is a more concise way to handle this problem. Before token annotation, clang-format will split the declaration into multiple lines in the struct, union, class, and enum cases. For instance, `struct {int n} &&ptr={};` will be separated as `struct {`, `int n;` and `} &&ptr={};`. So, the matching `{` will be NULL, and we can leverage this to indicate whether `&&` is a reference operator or not. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D131750 Files: clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTest.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Index: clang/unittests/Format/TokenAnnotatorTest.cpp =================================================================== --- clang/unittests/Format/TokenAnnotatorTest.cpp +++ clang/unittests/Format/TokenAnnotatorTest.cpp @@ -88,6 +88,10 @@ EXPECT_EQ(Tokens.size(), 5u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::amp, TT_UnaryOperator); + Tokens = annotate("bool b = 3 == int{3} && true;\n"); + EXPECT_EQ(Tokens.size(), 13u) << Tokens; + EXPECT_TOKEN(Tokens[9], tok::ampamp, TT_BinaryOperator); + Tokens = annotate("struct {\n" "} *ptr;"); EXPECT_EQ(Tokens.size(), 7u) << Tokens; Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -10474,6 +10474,7 @@ verifyFormat("class {\n" "}&& ptr = {};", Style); + verifyFormat("bool b = 3 == int{3} && true;"); Style.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("struct {\n" Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -2365,24 +2365,14 @@ !PrevToken->MatchingParen) 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; - } + // Before token annotation, clang-format will split the declaration into + // multiple lines in the struct, union, class, and enum cases. For instance, + // `struct {int n} &&ptr={};` will be separated as `struct {`, `int n;` and + // `} &&ptr={};`. So, the matching `{` will be NULL, and we can leverage + // this to indicate whether `&&` is a reference operator or not. + if (PrevToken->is(tok::r_brace) && Tok.is(tok::ampamp) && + !PrevToken->MatchingParen) + return TT_PointerOrReference; if (PrevToken->Tok.isLiteral() || PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
Index: clang/unittests/Format/TokenAnnotatorTest.cpp =================================================================== --- clang/unittests/Format/TokenAnnotatorTest.cpp +++ clang/unittests/Format/TokenAnnotatorTest.cpp @@ -88,6 +88,10 @@ EXPECT_EQ(Tokens.size(), 5u) << Tokens; EXPECT_TOKEN(Tokens[1], tok::amp, TT_UnaryOperator); + Tokens = annotate("bool b = 3 == int{3} && true;\n"); + EXPECT_EQ(Tokens.size(), 13u) << Tokens; + EXPECT_TOKEN(Tokens[9], tok::ampamp, TT_BinaryOperator); + Tokens = annotate("struct {\n" "} *ptr;"); EXPECT_EQ(Tokens.size(), 7u) << Tokens; Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -10474,6 +10474,7 @@ verifyFormat("class {\n" "}&& ptr = {};", Style); + verifyFormat("bool b = 3 == int{3} && true;"); Style.PointerAlignment = FormatStyle::PAS_Middle; verifyFormat("struct {\n" Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -2365,24 +2365,14 @@ !PrevToken->MatchingParen) 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; - } + // Before token annotation, clang-format will split the declaration into + // multiple lines in the struct, union, class, and enum cases. For instance, + // `struct {int n} &&ptr={};` will be separated as `struct {`, `int n;` and + // `} &&ptr={};`. So, the matching `{` will be NULL, and we can leverage + // this to indicate whether `&&` is a reference operator or not. + if (PrevToken->is(tok::r_brace) && Tok.is(tok::ampamp) && + !PrevToken->MatchingParen) + return TT_PointerOrReference; if (PrevToken->Tok.isLiteral() || PrevToken->isOneOf(tok::r_paren, tok::r_square, tok::kw_true,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits