Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -3549,6 +3549,19 @@ For example: Q_UNUSED + Cases in switch block can be defined as StatementMacros. The behavior is + the same as 'case' in switch block. + + .. code-block:: c + switch (x) { + FOO: + break; + case 0: + break; + BAR(var) : + break; + } + **TabWidth** (``unsigned``) The number of columns used for tab stops. Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -2018,6 +2018,19 @@ /// clang-format aware of such cases. /// /// For example: Q_UNUSED + /// + /// Cases in switch block can be defined as StatementMacros. The behavior is + /// the same as 'case' in switch block. + /// + /// .. code-block:: c + /// switch (x) { + /// FOO: + /// break; + /// case 0: + /// break; + /// BAR(var) : + /// break; + /// } std::vector StatementMacros; /// A vector of macros which are used to open namespace blocks. Index: clang/lib/Format/UnwrappedLineParser.h =================================================================== --- clang/lib/Format/UnwrappedLineParser.h +++ clang/lib/Format/UnwrappedLineParser.h @@ -97,7 +97,7 @@ void parsePPEndIf(); void parsePPUnknown(); void readTokenWithJavaScriptASI(); - void parseStructuralElement(); + void parseStructuralElement(bool InLevelParsing = false); bool tryToParseBracedList(); bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false, tok::TokenKind ClosingBraceKind = tok::r_brace); @@ -130,7 +130,7 @@ void parseObjCInterfaceOrImplementation(); bool parseObjCProtocol(); void parseJavaScriptEs6ImportExport(); - void parseStatementMacro(); + void parseStatementMacro(bool InLevelParsing = false); void parseCSharpAttribute(); // Parse a C# generic type constraint: `where T : IComparable`. // See: Index: clang/lib/Format/UnwrappedLineParser.cpp =================================================================== --- clang/lib/Format/UnwrappedLineParser.cpp +++ clang/lib/Format/UnwrappedLineParser.cpp @@ -374,7 +374,8 @@ } else if (FormatTok->getType() == TT_MacroBlockEnd) { kind = tok::r_brace; } - + if (FormatTok->is(TT_StatementMacro)) + parseStructuralElement(/*InLevelParsing=*/true); switch (kind) { case tok::comment: nextToken(); @@ -1040,7 +1041,7 @@ return addUnwrappedLine(); } -void UnwrappedLineParser::parseStructuralElement() { +void UnwrappedLineParser::parseStructuralElement(bool InLevelParsing) { assert(!FormatTok->is(tok::l_brace)); if (Style.Language == FormatStyle::LK_TableGen && FormatTok->is(tok::pp_include)) { @@ -1205,7 +1206,7 @@ } } if (Style.isCpp() && FormatTok->is(TT_StatementMacro)) { - parseStatementMacro(); + parseStatementMacro(InLevelParsing); return; } if (Style.isCpp() && FormatTok->is(TT_NamespaceMacro)) { @@ -2916,10 +2917,12 @@ } } -void UnwrappedLineParser::parseStatementMacro() { +void UnwrappedLineParser::parseStatementMacro(bool InLevelParsing) { nextToken(); if (FormatTok->is(tok::l_paren)) parseParens(); + if (InLevelParsing && FormatTok->is(tok::colon)) + parseLabel(); if (FormatTok->is(tok::semi)) nextToken(); addUnwrappedLine(); Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -3496,6 +3496,44 @@ getLLVMStyleWithColumns(11)); } +TEST_F(FormatTest, StatementMacroInSwitchBlock) { + FormatStyle Style = getLLVMStyle(); + Style.StatementMacros.push_back("FOO"); + verifyFormat("switch (x) {\n" + "FOO:\n" + " break;\n" + "case 0:\n" + " break;\n" + "FOO(var) :\n" + " break;\n" + "case 1:\n" + " break;\n" + "}", + Style); + /* Check the class cases behavior */ + verifyFormat("switch (x) {\n" + " class S1 {};\n" + " class S2 : S1 {};\n" + "case 0:\n" + " class S3 {};\n" + " class S4 : public S3 {};\n" + "}", + Style); + /* This option removes the space before the StatementMacro colon */ + Style.SpaceBeforeCtorInitializerColon = false; + verifyFormat("switch (x) {\n" + "FOO:\n" + " break;\n" + "case 0:\n" + " break;\n" + "FOO(var):\n" + " break;\n" + "case 1:\n" + " break;\n" + "}", + Style); +} + TEST_F(FormatTest, IndentPreprocessorDirectives) { FormatStyle Style = getLLVMStyle(); Style.IndentPPDirectives = FormatStyle::PPDIS_None;