[clang] [clang-format] Fix a bug in RemoveParentheses: ReturnStatement (PR #67911)
owenca wrote: @tru np! That was my intention anyways. https://github.com/llvm/llvm-project/pull/67911 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in RemoveParentheses: ReturnStatement (PR #67911)
tru wrote: oh sorry for merging this @owenca - it was tagged for the 17.x release and I thought it was a PR towards the backport branch so ti wasn't my intention to merge it into main for you. https://github.com/llvm/llvm-project/pull/67911 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in RemoveParentheses: ReturnStatement (PR #67911)
https://github.com/tru closed https://github.com/llvm/llvm-project/pull/67911 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in RemoveParentheses: ReturnStatement (PR #67911)
https://github.com/mydeveloperday approved this pull request. https://github.com/llvm/llvm-project/pull/67911 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [clang-format] Fix a bug in RemoveParentheses: ReturnStatement (PR #67911)
llvmbot wrote: @llvm/pr-subscribers-clang-format Changes Don't remove the outermost parentheses surrounding a return statement expression when inside a function/lambda that has the decltype(auto) return type. Fixed #67892. --- Full diff: https://github.com/llvm/llvm-project/pull/67911.diff 3 Files Affected: - (modified) clang/lib/Format/UnwrappedLineParser.cpp (+24) - (modified) clang/lib/Format/UnwrappedLineParser.h (+11) - (modified) clang/unittests/Format/FormatTest.cpp (+50) ``diff diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index bf38ed73c4a0b4e..dda5fd077e590e5 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -173,10 +173,12 @@ void UnwrappedLineParser::reset() { CommentsBeforeNextToken.clear(); FormatTok = nullptr; MustBreakBeforeNextToken = false; + IsDecltypeAutoFunction = false; PreprocessorDirectives.clear(); CurrentLines = DeclarationScopeStack.clear(); NestedTooDeep.clear(); + NestedLambdas.clear(); PPStack.clear(); Line->FirstStartColumn = FirstStartColumn; @@ -1766,6 +1768,17 @@ void UnwrappedLineParser::parseStructuralElement( if (parseStructLike()) return; break; +case tok::kw_decltype: + nextToken(); + if (FormatTok->is(tok::l_paren)) { +parseParens(); +assert(FormatTok->Previous); +if (FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto, + tok::l_paren)) { + Line->SeenDecltypeAuto = true; +} + } + break; case tok::period: nextToken(); // In Java, classes have an implicit static member "class". @@ -1827,6 +1840,7 @@ void UnwrappedLineParser::parseStructuralElement( if (InRequiresExpression) FormatTok->setFinalizedType(TT_BracedListLBrace); if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) { +IsDecltypeAutoFunction = Line->SeenDecltypeAuto; // A block outside of parentheses must be the last part of a // structural element. // FIXME: Figure out cases where this is not true, and add projections @@ -1844,6 +1858,7 @@ void UnwrappedLineParser::parseStructuralElement( } FormatTok->setFinalizedType(TT_FunctionLBrace); parseBlock(); +IsDecltypeAutoFunction = false; addUnwrappedLine(); return; } @@ -2249,9 +2264,15 @@ bool UnwrappedLineParser::tryToParseLambda() { return true; } } + FormatTok->setFinalizedType(TT_LambdaLBrace); LSquare.setFinalizedType(TT_LambdaLSquare); + + NestedLambdas.push_back(Line->SeenDecltypeAuto); parseChildBlock(); + assert(!NestedLambdas.empty()); + NestedLambdas.pop_back(); + return true; } @@ -2469,6 +2490,8 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if; const bool ReturnParens = Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement && +((NestedLambdas.empty() && !IsDecltypeAutoFunction) || + (!NestedLambdas.empty() && !NestedLambdas.back())) && Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next && Next->is(tok::semi); if ((DoubleParens && !Blacklisted) || ReturnParens) { @@ -4379,6 +4402,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) { Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex; Line->FirstStartColumn = 0; Line->IsContinuation = false; + Line->SeenDecltypeAuto = false; if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove) --Line->Level; diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 4138baaabe2693d..a4f150d19571266 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -61,6 +61,9 @@ struct UnwrappedLine { bool MustBeDeclaration = false; + /// Whether the parser has seen \c decltype(auto) in this line. + bool SeenDecltypeAuto = false; + /// \c True if this line should be indented by ContinuationIndent in /// addition to the normal indention level. bool IsContinuation = false; @@ -335,6 +338,14 @@ class UnwrappedLineParser { // statement contains more than some predefined number of nested statements). SmallVector NestedTooDeep; + // Keeps a stack of the states of nested lambdas (true if the return type of + // the lambda is `decltype(auto)`). + SmallVector NestedLambdas; + + // Whether the parser is parsing the body of a function whose return type is + // `decltype(auto)`. + bool IsDecltypeAutoFunction = false; + // Represents preprocessor branch type, so we can find matching // #if/#else/#endif directives. enum PPBranchKind { diff --git
[clang] [clang-format] Fix a bug in RemoveParentheses: ReturnStatement (PR #67911)
https://github.com/owenca created https://github.com/llvm/llvm-project/pull/67911 Don't remove the outermost parentheses surrounding a return statement expression when inside a function/lambda that has the decltype(auto) return type. Fixed #67892. >From 561af2122a9155b44e340d89549b13b0ea9b2ce6 Mon Sep 17 00:00:00 2001 From: Owen Pan Date: Sun, 1 Oct 2023 03:11:23 -0700 Subject: [PATCH] [clang-format] Fix a bug in RemoveParentheses: ReturnStatement Don't remove the outermost parentheses surrounding a return statement expression when inside a function/lambda that has the decltype(auto) return type. Fixed #67892. --- clang/lib/Format/UnwrappedLineParser.cpp | 24 clang/lib/Format/UnwrappedLineParser.h | 11 ++ clang/unittests/Format/FormatTest.cpp| 50 3 files changed, 85 insertions(+) diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index bf38ed73c4a0b4e..dda5fd077e590e5 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -173,10 +173,12 @@ void UnwrappedLineParser::reset() { CommentsBeforeNextToken.clear(); FormatTok = nullptr; MustBreakBeforeNextToken = false; + IsDecltypeAutoFunction = false; PreprocessorDirectives.clear(); CurrentLines = DeclarationScopeStack.clear(); NestedTooDeep.clear(); + NestedLambdas.clear(); PPStack.clear(); Line->FirstStartColumn = FirstStartColumn; @@ -1766,6 +1768,17 @@ void UnwrappedLineParser::parseStructuralElement( if (parseStructLike()) return; break; +case tok::kw_decltype: + nextToken(); + if (FormatTok->is(tok::l_paren)) { +parseParens(); +assert(FormatTok->Previous); +if (FormatTok->Previous->endsSequence(tok::r_paren, tok::kw_auto, + tok::l_paren)) { + Line->SeenDecltypeAuto = true; +} + } + break; case tok::period: nextToken(); // In Java, classes have an implicit static member "class". @@ -1827,6 +1840,7 @@ void UnwrappedLineParser::parseStructuralElement( if (InRequiresExpression) FormatTok->setFinalizedType(TT_BracedListLBrace); if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) { +IsDecltypeAutoFunction = Line->SeenDecltypeAuto; // A block outside of parentheses must be the last part of a // structural element. // FIXME: Figure out cases where this is not true, and add projections @@ -1844,6 +1858,7 @@ void UnwrappedLineParser::parseStructuralElement( } FormatTok->setFinalizedType(TT_FunctionLBrace); parseBlock(); +IsDecltypeAutoFunction = false; addUnwrappedLine(); return; } @@ -2249,9 +2264,15 @@ bool UnwrappedLineParser::tryToParseLambda() { return true; } } + FormatTok->setFinalizedType(TT_LambdaLBrace); LSquare.setFinalizedType(TT_LambdaLSquare); + + NestedLambdas.push_back(Line->SeenDecltypeAuto); parseChildBlock(); + assert(!NestedLambdas.empty()); + NestedLambdas.pop_back(); + return true; } @@ -2469,6 +2490,8 @@ bool UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) { PrevPrev->endsSequence(tok::kw_constexpr, tok::kw_if; const bool ReturnParens = Style.RemoveParentheses == FormatStyle::RPS_ReturnStatement && +((NestedLambdas.empty() && !IsDecltypeAutoFunction) || + (!NestedLambdas.empty() && !NestedLambdas.back())) && Prev && Prev->isOneOf(tok::kw_return, tok::kw_co_return) && Next && Next->is(tok::semi); if ((DoubleParens && !Blacklisted) || ReturnParens) { @@ -4379,6 +4402,7 @@ void UnwrappedLineParser::addUnwrappedLine(LineLevel AdjustLevel) { Line->MatchingOpeningBlockLineIndex = UnwrappedLine::kInvalidIndex; Line->FirstStartColumn = 0; Line->IsContinuation = false; + Line->SeenDecltypeAuto = false; if (ClosesWhitesmithsBlock && AdjustLevel == LineLevel::Remove) --Line->Level; diff --git a/clang/lib/Format/UnwrappedLineParser.h b/clang/lib/Format/UnwrappedLineParser.h index 4138baaabe2693d..a4f150d19571266 100644 --- a/clang/lib/Format/UnwrappedLineParser.h +++ b/clang/lib/Format/UnwrappedLineParser.h @@ -61,6 +61,9 @@ struct UnwrappedLine { bool MustBeDeclaration = false; + /// Whether the parser has seen \c decltype(auto) in this line. + bool SeenDecltypeAuto = false; + /// \c True if this line should be indented by ContinuationIndent in /// addition to the normal indention level. bool IsContinuation = false; @@ -335,6 +338,14 @@ class UnwrappedLineParser { // statement contains more than some predefined number of nested statements). SmallVector NestedTooDeep; + // Keeps a stack of the states of nested lambdas (true if the return type of + // the lambda is `decltype(auto)`). + SmallVector