From 6cdec7cf0558797ece82be6e7a1ca76791cf2672 Mon Sep 17 00:00:00 2001 From: Daniel Jasper Date: Tue, 9 Jul 2013 14:36:48 +0000 Subject: [PATCH] Initial support for formatting trailing return types. This fixes llvm.org/PR15170. For now, the basic formatting rules are (based on the C++11 standard): * Surround the "->" with spaces. * Break before "->". Also fix typo. llvm-svn: 185938 --- clang/lib/Format/Format.cpp | 2 +- clang/lib/Format/FormatToken.h | 1 + clang/lib/Format/TokenAnnotator.cpp | 13 +++++++++++-- clang/unittests/Format/FormatTest.cpp | 10 ++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index fb931490dc79..b6b726cfb215 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -674,7 +674,7 @@ private: State.Stack.back().Indent = State.Column; else if (Previous.opensScope()) { // If a function has multiple parameters (including a single parameter - // that is a binary expression) or a trailing call, indented all + // that is a binary expression) or a trailing call, indent all // parameters from the opening parenthesis. This avoids confusing // indents like: // OuterFunction(InnerFunctionCall( diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index e77ac016be0a..1de4b8964fe3 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -51,6 +51,7 @@ enum TokenType { TT_StartOfName, TT_TemplateCloser, TT_TemplateOpener, + TT_TrailingReturnArrow, TT_TrailingUnaryOperator, TT_UnaryOperator, TT_Unknown diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index c7034734d498..ce2db6d9c0bf 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -31,7 +31,7 @@ class AnnotatingParser { public: AnnotatingParser(AnnotatedLine &Line, IdentifierInfo &Ident_in) : Line(Line), CurrentToken(Line.First), KeywordVirtualFound(false), - NameFound(false), Ident_in(Ident_in) { + NameFound(false), AutoFound(false), Ident_in(Ident_in) { Contexts.push_back(Context(tok::unknown, 1, /*IsExpression=*/false)); } @@ -589,6 +589,10 @@ private: Contexts.back().FirstStartOfName = &Current; Current.Type = TT_StartOfName; NameFound = true; + } else if (Current.is(tok::kw_auto)) { + AutoFound = true; + } else if (Current.is(tok::arrow) && AutoFound) { + Current.Type = TT_TrailingReturnArrow; } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) { Current.Type = determineStarAmpUsage(Current, Contexts.back().CanBeExpression && @@ -792,6 +796,7 @@ private: FormatToken *CurrentToken; bool KeywordVirtualFound; bool NameFound; + bool AutoFound; IdentifierInfo &Ident_in; }; @@ -1165,6 +1170,9 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, (Tok.is(tok::equal) || Tok.Previous->is(tok::equal))) return false; + if (Tok.Type == TT_TrailingReturnArrow || + Tok.Previous->Type == TT_TrailingReturnArrow) + return true; if (Tok.Previous->is(tok::comma)) return true; if (Tok.is(tok::comma)) @@ -1234,7 +1242,8 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, if (Left.is(tok::l_paren) && Right.is(tok::l_paren) && Left.Previous->is(tok::kw___attribute)) return false; - if (Left.is(tok::l_paren) && Left.Previous->Type == TT_BinaryOperator) + if (Left.is(tok::l_paren) && (Left.Previous->Type == TT_BinaryOperator || + Left.Previous->is(tok::r_paren))) return false; } diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index dda16c52494b..0192a0718b37 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -2465,6 +2465,16 @@ TEST_F(FormatTest, BreaksFunctionDeclarations) { " const SomeLooooooooogType &a, const SomeLooooooooogType &b);"); } +TEST_F(FormatTest, TrailingReturnType) { + verifyFormat("auto foo() -> int;\n"); + verifyFormat("struct S {\n" + " auto bar() const -> int;\n" + "};"); + verifyFormat("template \n" + "auto load_img(const std::string &filename)\n" + " -> alias::tensor {}"); +} + TEST_F(FormatTest, BreaksFunctionDeclarationsWithTrailingTokens) { verifyFormat("void someLongFunction(\n" " int someLongParameter) const {}",