From c40345368252e600c43281438c4ca7ce5aa92d56 Mon Sep 17 00:00:00 2001 From: Ilya Biryukov Date: Fri, 27 Sep 2019 09:24:58 +0000 Subject: [PATCH] [clang-format] Reference qualifiers in member templates causing extra indentation The following code ``` struct f { template void bar() && noexcept {} }; ``` will be formatted to the following with LLVM style, and `AlwaysBreakTemplateDeclarations: Yes` ``` struct f { template void bar() && noexcept {} }; ``` The indentation of the `void bar()` line is wrong. Patch by Andreas Wass (AndWass)! Differential Revision: https://reviews.llvm.org/D68072 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@373056 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Format/TokenAnnotator.cpp | 16 +++++++++++---- unittests/Format/FormatTest.cpp | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/lib/Format/TokenAnnotator.cpp b/lib/Format/TokenAnnotator.cpp index e584eec368..918d5d3588 100644 --- a/lib/Format/TokenAnnotator.cpp +++ b/lib/Format/TokenAnnotator.cpp @@ -65,7 +65,7 @@ public: AnnotatingParser(const FormatStyle &Style, AnnotatedLine &Line, const AdditionalKeywords &Keywords) : Style(Style), Line(Line), CurrentToken(Line.First), AutoFound(false), - Keywords(Keywords) { + TrailingReturnFound(false), Keywords(Keywords) { Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false)); resetTokenMetadata(CurrentToken); } @@ -1389,7 +1389,10 @@ private: } else if (Current.is(tok::arrow) && AutoFound && Line.MustBeDeclaration && Current.NestingLevel == 0) { Current.Type = TT_TrailingReturnArrow; - } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) { + TrailingReturnFound = true; + } else if (Current.is(tok::star) || + (Current.isOneOf(tok::amp, tok::ampamp) && + (!Line.MightBeFunctionDecl || TrailingReturnFound))) { Current.Type = determineStarAmpUsage(Current, Contexts.back().CanBeExpression && Contexts.back().IsExpression, @@ -1412,6 +1415,8 @@ private: Current.Type = TT_ConditionalExpr; } } else if (Current.isBinaryOperator() && + !(Line.MightBeFunctionDecl && + Current.isOneOf(tok::amp, tok::ampamp)) && (!Current.Previous || Current.Previous->isNot(tok::l_square)) && (!Current.is(tok::greater) && Style.Language != FormatStyle::LK_TextProto)) { @@ -1486,10 +1491,12 @@ private: // colon after this, this is the only place which annotates the identifier // as a selector.) Current.Type = TT_SelectorName; - } else if (Current.isOneOf(tok::identifier, tok::kw_const) && + } else if (Current.isOneOf(tok::identifier, tok::kw_const, tok::amp, + tok::ampamp) && Current.Previous && !Current.Previous->isOneOf(tok::equal, tok::at) && - Line.MightBeFunctionDecl && Contexts.size() == 1) { + Line.MightBeFunctionDecl && !TrailingReturnFound && + Contexts.size() == 1) { // Line.MightBeFunctionDecl can only be true after the parentheses of a // function declaration have been found. Current.Type = TT_TrailingAnnotation; @@ -1767,6 +1774,7 @@ private: AnnotatedLine &Line; FormatToken *CurrentToken; bool AutoFound; + bool TrailingReturnFound; const AdditionalKeywords &Keywords; // Set of "<" tokens that do not open a template parameter list. If parseAngle diff --git a/unittests/Format/FormatTest.cpp b/unittests/Format/FormatTest.cpp index 581d15672b..ecb3dddfdf 100644 --- a/unittests/Format/FormatTest.cpp +++ b/unittests/Format/FormatTest.cpp @@ -14373,6 +14373,41 @@ TEST_F(FormatTest, AmbersandInLamda) { verifyFormat("auto lambda = [&a = a]() { a = 2; };", AlignStyle); } +TEST_F(FormatTest, RefQualifiedTemplateMember) { + FormatStyle AlignStyle = getLLVMStyle(); + AlignStyle.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes; + + verifyFormat("struct f {\n" + " template \n" + " int &foo() & noexcept {}\n" + "};", + AlignStyle); + + verifyFormat("struct f {\n" + " template \n" + " int &foo() && noexcept {}\n" + "};", + AlignStyle); + + verifyFormat("struct f {\n" + " template \n" + " int &foo() const & noexcept {}\n" + "};", + AlignStyle); + + verifyFormat("struct f {\n" + " template \n" + " int &foo() const & noexcept {}\n" + "};", + AlignStyle); + + verifyFormat("struct f {\n" + " template \n" + " auto foo() && noexcept -> int & {}\n" + "};", + AlignStyle); +} + } // end namespace } // end namespace format } // end namespace clang -- 2.40.0