Author: Owen Pan Date: 2024-10-02T19:06:56-07:00 New Revision: 14e1fef73625daf9fad1a2c51b16f67b3152a675
URL: https://github.com/llvm/llvm-project/commit/14e1fef73625daf9fad1a2c51b16f67b3152a675 DIFF: https://github.com/llvm/llvm-project/commit/14e1fef73625daf9fad1a2c51b16f67b3152a675.diff LOG: [clang-format] Handle template closer followed by empty paretheses (#110408) Fixes #109925. Added: Modified: clang/lib/Format/TokenAnnotator.cpp clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 130ae829f026d6..5398e2dadd485a 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -189,25 +189,29 @@ class AnnotatingParser { next(); } - for (bool SeenTernaryOperator = false; CurrentToken;) { + for (bool SeenTernaryOperator = false, MaybeAngles = true; CurrentToken;) { const bool InExpr = Contexts[Contexts.size() - 2].IsExpression; if (CurrentToken->is(tok::greater)) { const auto *Next = CurrentToken->Next; - // Try to do a better job at looking for ">>" within the condition of - // a statement. Conservatively insert spaces between consecutive ">" - // tokens to prevent splitting right bitshift operators and potentially - // altering program semantics. This check is overly conservative and - // will prevent spaces from being inserted in select nested template - // parameter cases, but should not alter program semantics. - if (Next && Next->is(tok::greater) && - Left->ParentBracket != tok::less && - CurrentToken->getStartOfNonWhitespace() == - Next->getStartOfNonWhitespace().getLocWithOffset(-1)) { - return false; - } - if (InExpr && SeenTernaryOperator && - (!Next || !Next->isOneOf(tok::l_paren, tok::l_brace))) { - return false; + if (CurrentToken->isNot(TT_TemplateCloser)) { + // Try to do a better job at looking for ">>" within the condition of + // a statement. Conservatively insert spaces between consecutive ">" + // tokens to prevent splitting right shift operators and potentially + // altering program semantics. This check is overly conservative and + // will prevent spaces from being inserted in select nested template + // parameter cases, but should not alter program semantics. + if (Next && Next->is(tok::greater) && + Left->ParentBracket != tok::less && + CurrentToken->getStartOfNonWhitespace() == + Next->getStartOfNonWhitespace().getLocWithOffset(-1)) { + return false; + } + if (InExpr && SeenTernaryOperator && + (!Next || !Next->isOneOf(tok::l_paren, tok::l_brace))) { + return false; + } + if (!MaybeAngles) + return false; } Left->MatchingParen = CurrentToken; CurrentToken->MatchingParen = Left; @@ -247,11 +251,11 @@ class AnnotatingParser { // operator that was misinterpreted because we are parsing template // parameters. // FIXME: This is getting out of hand, write a decent parser. - if (InExpr && !Line.startsWith(tok::kw_template) && + if (MaybeAngles && InExpr && !Line.startsWith(tok::kw_template) && Prev.is(TT_BinaryOperator)) { const auto Precedence = Prev.getPrecedence(); if (Precedence > prec::Conditional && Precedence < prec::Relational) - return false; + MaybeAngles = false; } if (Prev.isOneOf(tok::question, tok::colon) && !Style.isProto()) SeenTernaryOperator = true; @@ -1627,7 +1631,7 @@ class AnnotatingParser { return false; break; case tok::greater: - if (Style.Language != FormatStyle::LK_TextProto) + if (Style.Language != FormatStyle::LK_TextProto && Tok->is(TT_Unknown)) Tok->setType(TT_BinaryOperator); if (Tok->Previous && Tok->Previous->is(TT_TemplateCloser)) Tok->SpacesRequiredBefore = 1; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 40f77266fabdca..a38a86764d68c5 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2556,7 +2556,7 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { parseChildBlock(); break; case tok::r_paren: { - const auto *Prev = LeftParen->Previous; + auto *Prev = LeftParen->Previous; if (!MightBeStmtExpr && !MightBeFoldExpr && !Line->InMacroBody && Style.RemoveParentheses > FormatStyle::RPS_Leave) { const auto *Next = Tokens->peekNextToken(); @@ -2585,9 +2585,13 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { FormatTok->Optional = true; } } - if (Prev && Prev->is(TT_TypenameMacro)) { - LeftParen->setFinalizedType(TT_TypeDeclarationParen); - FormatTok->setFinalizedType(TT_TypeDeclarationParen); + if (Prev) { + if (Prev->is(TT_TypenameMacro)) { + LeftParen->setFinalizedType(TT_TypeDeclarationParen); + FormatTok->setFinalizedType(TT_TypeDeclarationParen); + } else if (Prev->is(tok::greater) && FormatTok->Previous == LeftParen) { + Prev->setFinalizedType(TT_TemplateCloser); + } } nextToken(); return SeenEqual; diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index c8184d6f789504..de1346b5ddd5a7 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -3533,6 +3533,13 @@ TEST_F(TokenAnnotatorTest, TemplateName) { EXPECT_TOKEN(Tokens[6], tok::greater, TT_TemplateCloser); } +TEST_F(TokenAnnotatorTest, TemplateInstantiation) { + auto Tokens = annotate("return FixedInt<N | M>();"); + ASSERT_EQ(Tokens.size(), 11u) << Tokens; + EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::greater, TT_TemplateCloser); +} + } // namespace } // namespace format } // namespace clang _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits