diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 10a716c551be..91bc64b2b8b4 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -329,7 +329,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, State.Column > getNewLineColumn(State)) State.Stack.back().ContainsUnwrappedBuilder = true; - if (Current.is(TT_LambdaArrow)) + if (Current.is(TT_LambdaArrow) && Style.Language == FormatStyle::LK_Java) State.Stack.back().NoLineBreak = true; if (Current.isMemberAccess() && Previous.is(tok::r_paren) && (Previous.MatchingParen && diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index a717a96eab1f..6565ed2b7b31 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -754,8 +754,8 @@ private: // recovered from an error (e.g. failure to find the matching >). if (!CurrentToken->isOneOf(TT_LambdaLSquare, TT_ForEachMacro, TT_FunctionLBrace, TT_ImplicitStringLiteral, - TT_InlineASMBrace, TT_JsFatArrow, - TT_RegexLiteral, TT_TrailingReturnArrow)) + TT_InlineASMBrace, TT_JsFatArrow, TT_LambdaArrow, + TT_RegexLiteral)) CurrentToken->Type = TT_Unknown; CurrentToken->Role.reset(); CurrentToken->MatchingParen = nullptr; @@ -844,6 +844,8 @@ private: Contexts.back().IsExpression = true; } else if (Current.is(TT_TrailingReturnArrow)) { Contexts.back().IsExpression = false; + } else if (Current.is(TT_LambdaArrow)) { + Contexts.back().IsExpression = Style.Language == FormatStyle::LK_Java; } else if (Current.is(tok::l_paren) && !Line.MustBeDeclaration && !Line.InPPDirective && (!Current.Previous || @@ -1646,7 +1648,7 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, } if (Right.is(TT_PointerOrReference)) return 190; - if (Right.is(TT_TrailingReturnArrow)) + if (Right.is(TT_LambdaArrow)) return 110; if (Left.is(tok::equal) && Right.is(tok::l_brace)) return 150; @@ -1901,8 +1903,6 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, } else if (Style.Language == FormatStyle::LK_Java) { if (Left.is(tok::r_square) && Right.is(tok::l_brace)) return true; - if (Left.is(TT_LambdaArrow) || Right.is(TT_LambdaArrow)) - return true; if (Left.is(Keywords.kw_synchronized) && Right.is(tok::l_paren)) return Style.SpaceBeforeParens != FormatStyle::SBPO_Never; if ((Left.isOneOf(tok::kw_static, tok::kw_public, tok::kw_private, @@ -1927,7 +1927,8 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, (Right.is(tok::equal) || Left.is(tok::equal))) return false; - if (Right.is(TT_TrailingReturnArrow) || Left.is(TT_TrailingReturnArrow)) + if (Right.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow) || + Left.isOneOf(TT_TrailingReturnArrow, TT_LambdaArrow)) return true; if (Left.is(tok::comma)) return true; diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 826b40d3f831..6ad43294ca97 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -953,7 +953,7 @@ bool UnwrappedLineParser::tryToParseLambda() { nextToken(); break; case tok::arrow: - FormatTok->Type = TT_TrailingReturnArrow; + FormatTok->Type = TT_LambdaArrow; nextToken(); break; default: diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 69d6cee7dea0..0760530672b5 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -3956,6 +3956,9 @@ TEST_F(FormatTest, TrailingReturnType) { verifyFormat("auto SomeFunction(A aaaaaaaaaaaaaaaaaaaaa) const\n" " -> decltype(f(aaaaaaaaaaaaaaaaaaaaa)) {}"); verifyFormat("auto doSomething(Aaaaaa *aaaaaa) -> decltype(aaaaaa->f()) {}"); + verifyFormat("template \n" + "auto aaaaaaaaaaaaaaaaaaaaaa(T t)\n" + " -> decltype(eaaaaaaaaaaaaaaa(t.a).aaaaaaaa());"); // Not trailing return types. verifyFormat("void f() { auto a = b->c(); }"); @@ -6606,6 +6609,7 @@ TEST_F(FormatTest, UnderstandContextOfRecordTypeKeywords) { // FIXME: This is still incorrectly handled at the formatter side. verifyFormat("template <> struct X < 15, i<3 && 42 < 50 && 33 < 28> {};"); + verifyFormat("int i = SomeFunction(a b);"); // FIXME: // This now gets parsed incorrectly as class definition.