diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -113,13 +113,14 @@ } else if (RootToken.isObjCAccessSpecifier()) { return true; } - // Handle Qt signals. - else if ((RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && - RootToken.Next && RootToken.Next->is(tok::colon))) { + // Handle Qt signals and custom attributes. + else if (RootToken.isOneOf(Keywords.kw_signals, Keywords.kw_qsignals) && + RootToken.Next && RootToken.Next->is(tok::colon)) { return true; - } else if (RootToken.Next && - RootToken.Next->isOneOf(Keywords.kw_slots, - Keywords.kw_qslots) && + } else if (RootToken.isAccessSpecifier(/*colonRequired=*/false) && + RootToken.Next && + RootToken.Next->isOneOf(Keywords.kw_slots, Keywords.kw_qslots, + tok::identifier) && RootToken.Next->Next && RootToken.Next->Next->is(tok::colon)) { return true; } diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -3087,6 +3087,10 @@ // Understand Qt's slots. if (FormatTok->isOneOf(Keywords.kw_slots, Keywords.kw_qslots)) nextToken(); + // Handle custom attributes. + if (FormatTok->is(tok::identifier) && Tokens->peekNextToken()->is(tok::colon)) + nextToken(); + // Otherwise, we don't know what it is, and we'd better keep the next token. if (FormatTok->is(tok::colon)) { nextToken(); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -3300,8 +3300,19 @@ "Q_SIGNALS:\n" " void g2();\n" "};"); + verifyFormat("class A {\n" + "public ATTR:\n" + " void f1() {}\n" + "protected ATTR:\n" + " void f2() {}\n" + "private ATTR:\n" + " void f3() {}\n" + "};"); // Don't interpret 'signals' the wrong way. + verifyFormat("struct Bitfields {\n" + " unsigned signals : 1;\n" + "};"); verifyFormat("signals.set();"); verifyFormat("for (Signals signals : f()) {\n}"); verifyFormat("{\n" @@ -3311,6 +3322,21 @@ "label:\n" " signals.baz();\n" "}"); + + // Don't interpret 'slots' the wrong way. + verifyFormat("struct Bitfields {\n" + " unsigned slots : 1;\n" + "};"); + verifyFormat("slots.set();"); + verifyFormat("for (Signals slots : f()) {\n}"); + verifyFormat("{\n" + " slots.set(); // This needs indentation.\n" + "}"); + verifyFormat("void f() {\n" + "label:\n" + " slots.baz();\n" + "}"); + verifyFormat("private[1];"); verifyFormat("testArray[public] = 1;"); verifyFormat("public();");