Author: poiru Date: Wed Jul 15 14:11:58 2015 New Revision: 242316 URL: http://llvm.org/viewvc/llvm-project?rev=242316&view=rev Log: clang-format: Fix return type breaking with overloaded operator functions
Differential Revision: http://reviews.llvm.org/D11177 Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp cfe/trunk/lib/Format/TokenAnnotator.cpp cfe/trunk/unittests/Format/FormatTest.cpp Modified: cfe/trunk/lib/Format/ContinuationIndenter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/ContinuationIndenter.cpp?rev=242316&r1=242315&r2=242316&view=diff ============================================================================== --- cfe/trunk/lib/Format/ContinuationIndenter.cpp (original) +++ cfe/trunk/lib/Format/ContinuationIndenter.cpp Wed Jul 15 14:11:58 2015 @@ -225,7 +225,8 @@ bool ContinuationIndenter::mustBreak(con } // If the return type spans multiple lines, wrap before the function name. - if (Current.isOneOf(TT_FunctionDeclarationName, tok::kw_operator) && + if ((Current.is(TT_FunctionDeclarationName) || + (Current.is(tok::kw_operator) && !Previous.is(tok::coloncolon))) && State.Stack.back().BreakBeforeParameter) return true; Modified: cfe/trunk/lib/Format/TokenAnnotator.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Format/TokenAnnotator.cpp?rev=242316&r1=242315&r2=242316&view=diff ============================================================================== --- cfe/trunk/lib/Format/TokenAnnotator.cpp (original) +++ cfe/trunk/lib/Format/TokenAnnotator.cpp Wed Jul 15 14:11:58 2015 @@ -500,6 +500,19 @@ private: return false; break; case tok::l_paren: + // When faced with 'operator()()', the kw_operator handler incorrectly + // marks the first l_paren as a OverloadedOperatorLParen. Here, we make + // the first two parens OverloadedOperators and the second l_paren an + // OverloadedOperatorLParen. + if (Tok->Previous && + Tok->Previous->is(tok::r_paren) && + Tok->Previous->MatchingParen && + Tok->Previous->MatchingParen->is(TT_OverloadedOperatorLParen)) { + Tok->Previous->Type = TT_OverloadedOperator; + Tok->Previous->MatchingParen->Type = TT_OverloadedOperator; + Tok->Type = TT_OverloadedOperatorLParen; + } + if (!parseParens()) return false; if (Line.MustBeDeclaration && Contexts.size() == 1 && @@ -1460,25 +1473,56 @@ void TokenAnnotator::annotate(AnnotatedL // This function heuristically determines whether 'Current' starts the name of a // function declaration. static bool isFunctionDeclarationName(const FormatToken &Current) { - if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0) - return false; - const FormatToken *Next = Current.Next; - for (; Next; Next = Next->Next) { - if (Next->is(TT_TemplateOpener)) { - Next = Next->MatchingParen; - } else if (Next->is(tok::coloncolon)) { - Next = Next->Next; - if (!Next || !Next->is(tok::identifier)) - return false; - } else if (Next->is(tok::l_paren)) { + auto skipOperatorName = [](const FormatToken* Next) -> const FormatToken* { + for (; Next; Next = Next->Next) { + if (Next->is(TT_OverloadedOperatorLParen)) + return Next; + if (Next->is(TT_OverloadedOperator)) + continue; + if (Next->isOneOf(tok::kw_new, tok::kw_delete)) { + // For 'new[]' and 'delete[]'. + if (Next->Next && Next->Next->is(tok::l_square) && + Next->Next->Next && Next->Next->Next->is(tok::r_square)) + Next = Next->Next->Next; + continue; + } + break; - } else { + } + return nullptr; + }; + + const FormatToken *Next = Current.Next; + if (Current.is(tok::kw_operator)) { + if (Current.Previous && Current.Previous->is(tok::coloncolon)) + return false; + Next = skipOperatorName(Next); + } else { + if (!Current.is(TT_StartOfName) || Current.NestingLevel != 0) return false; + for (; Next; Next = Next->Next) { + if (Next->is(TT_TemplateOpener)) { + Next = Next->MatchingParen; + } else if (Next->is(tok::coloncolon)) { + Next = Next->Next; + if (!Next) + return false; + if (Next->is(tok::kw_operator)) { + Next = skipOperatorName(Next->Next); + break; + } + if (!Next->is(tok::identifier)) + return false; + } else if (Next->is(tok::l_paren)) { + break; + } else { + return false; + } } } - if (!Next) + + if (!Next || !Next->is(tok::l_paren)) return false; - assert(Next->is(tok::l_paren)); if (Next->Next == Next->MatchingParen) return true; for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen; Modified: cfe/trunk/unittests/Format/FormatTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Format/FormatTest.cpp?rev=242316&r1=242315&r2=242316&view=diff ============================================================================== --- cfe/trunk/unittests/Format/FormatTest.cpp (original) +++ cfe/trunk/unittests/Format/FormatTest.cpp Wed Jul 15 14:11:58 2015 @@ -4678,6 +4678,32 @@ TEST_F(FormatTest, DefinitionReturnTypeB "}\n" "template <class T> T *f(T &c);\n", // No break here. Style); + verifyFormat("class C {\n" + " int\n" + " operator+() {\n" + " return 1;\n" + " }\n" + " int\n" + " operator()() {\n" + " return 1;\n" + " }\n" + "};\n", + Style); + verifyFormat("void\n" + "A::operator()() {}\n" + "void\n" + "A::operator>>() {}\n" + "void\n" + "A::operator+() {}\n", + Style); + verifyFormat("void *operator new(std::size_t s);", // No break here. + Style); + verifyFormat("void *\n" + "operator new(std::size_t s) {}", + Style); + verifyFormat("void *\n" + "operator delete[](void *ptr) {}", + Style); Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup; verifyFormat("const char *\n" "f(void)\n" // Break here. _______________________________________________ cfe-commits mailing list cfe-commits@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits