Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -2040,6 +2040,7 @@ if (Next->MatchingParen->Next && Next->MatchingParen->Next->is(TT_PointerOrReference)) return true; + int TemplateOpenerLevel = 0; for (const FormatToken *Tok = Next->Next; Tok && Tok != Next->MatchingParen; Tok = Tok->Next) { if (Tok->is(tok::l_paren) && Tok->MatchingParen) { @@ -2049,6 +2050,15 @@ if (Tok->is(tok::kw_const) || Tok->isSimpleTypeSpecifier() || Tok->isOneOf(TT_PointerOrReference, TT_StartOfName, tok::ellipsis)) return true; + // Keep a track of how deep inside nested templates chevrons we are. + if (Tok->is(TT_TemplateOpener)) + TemplateOpenerLevel++; + if (Tok->is(TT_TemplateCloser)) + TemplateOpenerLevel--; + // We need to see a numeric_constant in a template argument e.g. <8> + // for it to be an argument that suggests a function decl. + if (Tok->is(tok::numeric_constant) && TemplateOpenerLevel > 0) + return true; if (Tok->isOneOf(tok::l_brace, tok::string_literal, TT_ObjCMethodExpr) || Tok->Tok.isLiteral()) return false; Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -5419,6 +5419,42 @@ "}\n" "template T *f(T &c);\n", // No break here. Style); + verifyFormat("int\n" + "foo(A a)\n" + "{\n" + " return a;\n" + "}\n", + Style); + verifyFormat("int\n" + "foo(A<8> a)\n" + "{\n" + " return a;\n" + "}\n", + Style); + verifyFormat("int\n" + "foo(A, 8> a)\n" + "{\n" + " return a;\n" + "}\n", + Style); + verifyFormat("int\n" + "foo(A, bool> a)\n" + "{\n" + " return a;\n" + "}\n", + Style); + verifyFormat("int\n" + "foo(A, bool> a)\n" + "{\n" + " return a;\n" + "}\n", + Style); + verifyFormat("int\n" + "foo(A, 8> a)\n" + "{\n" + " return a;\n" + "}\n", + Style); } TEST_F(FormatTest, AlwaysBreakBeforeMultilineStrings) {