Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -1350,6 +1350,38 @@ } } + static bool isDeductionGuide(FormatToken &Current) { + // Look for a deduction guide A()...) -> A<...>; + if (Current.Previous && Current.Previous->is(tok::r_paren) && + Current.startsSequence(tok::arrow, tok::identifier, tok::less)) { + // Find the TemplateCloser. + FormatToken *TemplateCloser = Current.Next->Next; + int NestingLevel = 1; + while (TemplateCloser && NestingLevel > 0) { + TemplateCloser = TemplateCloser->Next; + if (TemplateCloser->is(tok::less)) + NestingLevel++; + if (TemplateCloser->is(tok::greater)) + NestingLevel--; + if (TemplateCloser->is(tok::kw_decltype)) + return false; + } + // Assuming we have found the end of the template ensure its followed + // with a ; + if (TemplateCloser && TemplateCloser->Next && + TemplateCloser->Next->is(tok::semi) && + Current.Previous->MatchingParen) { + // Determine if the identifier `A` prior to the A<..>; is the same as + // prior to the A(..) + FormatToken *LeadingIdentifier = + Current.Previous->MatchingParen->Previous; + return (LeadingIdentifier && + LeadingIdentifier->TokenText == Current.Next->TokenText); + } + } + return false; + } + void determineTokenType(FormatToken &Current) { if (!Current.is(TT_Unknown)) // The token type is already known. @@ -1397,6 +1429,10 @@ !Current.Previous->is(tok::kw_operator)) { // not auto operator->() -> xxx; Current.Type = TT_TrailingReturnArrow; + + } else if (isDeductionGuide(Current)) { + // Deduction guides trailing arrow "...) -> A;". + Current.Type = TT_TrailingReturnArrow; } else if (Current.isOneOf(tok::star, tok::amp, tok::ampamp)) { Current.Type = determineStarAmpUsage(Current, Contexts.back().CanBeExpression && Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -4977,6 +4977,21 @@ verifyFormat("void f() { auto a = b->c(); }"); } +TEST_F(FormatTest, DeductionGuides) { + verifyFormat("template A(const T &, const T &) -> A;"); + verifyFormat("template explicit A(T &, T &&) -> A;"); + verifyFormat("template S(Ts...) -> S;"); + verifyFormat( + "template \n" + "array(T &&... t) -> array, sizeof...(T)>;"); + + // Ensure not deduction guides. + verifyFormat("c()->f();"); + verifyFormat("x()->foo<1>;"); + verifyFormat("x = p->foo<3>();"); + verifyFormat("A()->Afoo<3>())>;"); +} + TEST_F(FormatTest, BreaksFunctionDeclarationsWithTrailingTokens) { // Avoid breaking before trailing 'const' or other trailing annotations, if // they are not function-like.