From f81e5c0e50424f65ed60ba8de9578f6edc79dd5d Mon Sep 17 00:00:00 2001 From: Manuel Klimek Date: Thu, 27 Mar 2014 11:17:36 +0000 Subject: [PATCH] Fix bool expression special case. Clang-format now correctly formats: some_type v; template typename enabled_if::type f() {} llvm-svn: 204913 --- clang/lib/Format/TokenAnnotator.cpp | 21 +++++++++++++++++---- clang/unittests/Format/FormatTest.cpp | 8 ++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 19bc5a6a96b0..ee68afe7dcc7 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -44,6 +44,11 @@ private: ScopedContextCreator ContextCreator(*this, tok::less, 10); FormatToken *Left = CurrentToken->Previous; Contexts.back().IsExpression = false; + // If there's a template keyword before the opening angle bracket, this is a + // template parameter, not an argument. + Contexts.back().InTemplateArgument = + Left->Previous != NULL && Left->Previous->Tok.isNot(tok::kw_template); + while (CurrentToken != NULL) { if (CurrentToken->is(tok::greater)) { Left->MatchingParen = CurrentToken; @@ -615,7 +620,8 @@ private: ColonIsForRangeExpr(false), ColonIsDictLiteral(false), ColonIsObjCMethodExpr(false), FirstObjCSelectorName(NULL), FirstStartOfName(NULL), IsExpression(IsExpression), - CanBeExpression(true), InCtorInitializer(false), CaretFound(false) {} + CanBeExpression(true), InTemplateArgument(false), + InCtorInitializer(false), CaretFound(false) {} tok::TokenKind ContextKind; unsigned BindingStrength; @@ -628,6 +634,7 @@ private: FormatToken *FirstStartOfName; bool IsExpression; bool CanBeExpression; + bool InTemplateArgument; bool InCtorInitializer; bool CaretFound; }; @@ -705,7 +712,8 @@ private: } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) { Current.Type = determineStarAmpUsage(Current, Contexts.back().CanBeExpression && - Contexts.back().IsExpression); + Contexts.back().IsExpression, + Contexts.back().InTemplateArgument); } else if (Current.isOneOf(tok::minus, tok::plus, tok::caret)) { Current.Type = determinePlusMinusCaretUsage(Current); if (Current.Type == TT_UnaryOperator) { @@ -821,7 +829,8 @@ private: } /// \brief Return the type of the given token assuming it is * or &. - TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression) { + TokenType determineStarAmpUsage(const FormatToken &Tok, bool IsExpression, + bool InTemplateArgument) { const FormatToken *PrevToken = Tok.getPreviousNonComment(); if (PrevToken == NULL) return TT_UnaryOperator; @@ -851,7 +860,11 @@ private: if (PrevToken->Tok.isLiteral() || PrevToken->isOneOf(tok::r_paren, tok::r_square) || - NextToken->Tok.isLiteral() || NextToken->isUnaryOperator()) + NextToken->Tok.isLiteral() || NextToken->isUnaryOperator() || + // If we know we're in a template argument, there are no named + // declarations. Thus, having an identifier on the right-hand side + // indicates a binary operator. + (InTemplateArgument && NextToken->Tok.isAnyIdentifier())) return TT_BinaryOperator; // It is very unlikely that we are going to find a pointer or reference type diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index fa8ed3828d40..949167c8f566 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -4529,6 +4529,14 @@ TEST_F(FormatTest, UnderstandsUsesOfStarAndAmp) { verifyFormat("delete *x;", PointerLeft); verifyFormat("STATIC_ASSERT((a & b) == 0);"); verifyFormat("STATIC_ASSERT(0 == (a & b));"); + verifyFormat("template " + "typename t::if::type f() {};"); + verifyFormat("template f() {};"); + verifyFormat("vector v;"); + verifyFormat("vector v;"); + verifyFormat("vector v;"); + verifyFormat("vector v;"); + verifyFormat("vector v;"); } TEST_F(FormatTest, UnderstandsAttributes) {