Index: lib/Format/ContinuationIndenter.cpp =================================================================== --- lib/Format/ContinuationIndenter.cpp +++ lib/Format/ContinuationIndenter.cpp @@ -225,7 +225,8 @@ } // 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; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -500,6 +500,17 @@ return false; break; case tok::l_paren: + // Special case for 'operator()()'. + if (Tok->Previous && + Tok->Previous->is(tok::r_paren) && + Tok->Previous->MatchingParen && + Tok->Previous->MatchingParen->is(TT_OverloadedOperatorLParen) && + Tok->Previous->MatchingParen->Previous && + Tok->Previous->MatchingParen->Previous->is(tok::kw_operator)) { + Tok->Previous->MatchingParen->Type = TT_OverloadedOperator; + Tok->Type = TT_OverloadedOperatorLParen; + } + if (!parseParens()) return false; if (Line.MustBeDeclaration && Contexts.size() == 1 && @@ -1460,25 +1471,40 @@ // 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)) { + if (Current.is(tok::kw_operator)) { + if (Current.Previous && Current.Previous->is(tok::coloncolon)) + return false; + while (Next && !Next->is(TT_OverloadedOperatorLParen)) Next = Next->Next; - if (!Next || !Next->is(tok::identifier)) - return false; - } else if (Next->is(tok::l_paren)) { - break; - } else { + } 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 = Next->Next; + while (Next && !Next->is(TT_OverloadedOperatorLParen)) + Next = Next->Next; + break; + } else 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; @@ -2156,9 +2182,10 @@ return Line.IsMultiVariableDeclStmt || (Style.PointerAlignment == FormatStyle::PAS_Right && (!Right.Next || Right.Next->isNot(TT_FunctionDeclarationName))); - if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName) || - Right.is(tok::kw_operator)) + if (Right.isOneOf(TT_StartOfName, TT_FunctionDeclarationName)) return true; + if (Right.is(tok::kw_operator)) + return !Left.is(tok::coloncolon); if (Left.is(TT_PointerOrReference)) return false; if (Right.isTrailingComment()) Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -4678,6 +4678,29 @@ "}\n" "template 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); Style.BreakBeforeBraces = FormatStyle::BS_Stroustrup; verifyFormat("const char *\n" "f(void)\n" // Break here.