相关文章推荐
不拘小节的领带  ·  Use Vim macros to ...·  9 月前    · 
一身肌肉的泡面  ·  java - how to fix ...·  1 年前    · 
成熟的椰子  ·  python下载pdf文件-掘金·  1 年前    · 
打篮球的煎饼  ·  Python Forum·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am trying to apply clang-format to an existing code base and came across the following issue:

Simplified (and formatted) sample code:

#define QUERY_BEGIN()
#define QUERY_NORESULT()
#define QUERY_END()
void foo()
   int a = 0;
   QUERY_BEGIN()
      a = 1;
      QUERY_NORESULT()
      a = 2;
   QUERY_END()

I set the following options:

MacroBlockEnd:   'QUERY_END'
MacroBlockBegin: 'QUERY_BEGIN'

What I want to achieve is the following formatting of the macro part:

   QUERY_BEGIN()
      a = 1;
   QUERY_NORESULT()
      a = 2;
   QUERY_END()

My first guess was to set QUERY_NORESULT as MacroBlockEnd and MacroBlockBegin but that didn't help. It results in the following formatting:

   QUERY_BEGIN()
      a = 1;
      QUERY_NORESULT
         a = 2;
      QUERY_END()

Is there currently a way to achieve the indentation as shown above?

  • Bad news: Sorry, this is not available in the current release version of clang-format(7).
  • Good news: There is a StatementMacros option, which is available since clang-format 8(not release yet, but you can build from source).
  • See this commit:

    Summary: Some macros are used in the body of function, and actually contain the trailing semicolon: they should thus be automatically followed by a new line, and not get merged with the next line. This is for example the case with Qt's Q_UNUSED macro:

      void foo(int a, int b) {
        Q_UNUSED(a)
        return b;
      

    This patch deals with these cases by introducing a new option to specify list of statement macros. This re-uses the system already in place for foreach macros, to ensure there is no impact on performance.

    Document:

    ◆ StatementMacros

    std::vector clang::format::FormatStyle::StatementMacros A vector of macros that should be interpreted as complete statements.

    Typical macros are expressions, and require a semi-colon to be added; sometimes this is not the case, and this allows to make clang-format aware of such cases.

    For example: Q_UNUSED

    Definition at line 1061 of file Format.h.

    Referenced by clang::format::FormatTokenLexer::FormatTokenLexer(), clang::format::getLLVMStyle(), llvm::yaml::MappingTraits< FormatStyle >::mapping(), and operator==().

    Solution:

    build clang from source/wait for llvm/clang8 release, then put StatementMacros ['QUERY_BEGIN()', 'QUERY_NORESULT()', 'QUERY_END()'] into your .clang-format.

    Workaround for old clang-format

    // clang-format off
        void    unformatted_code  ;
    // clang-format on
    

    Turn off clang-format in this macro statements.

    The documentation cited seems to suggest the "StatementMacros" setting does not impact indentation, but that it avoids adding a semicolon. – Robert Boehne Dec 7, 2018 at 16:41

    clang-format 3.7 added support for this under the names MacroBlockBegin and MacroBlockEnd. These config options are weirder than the newer-style (Attribute|Statement|If|Foreach)Macros options (which take lists); the older-style MacroBlock(Begin|End) options take regular expressions, which means that if you have multiple begin/end macros, you must glue them together like this:

    MacroBlockBegin: '(FIRST_MACRO|SECOND_MACRO)'
    

    Anyway, for your exact input, and this .clang-format file:

    $ cat .clang-format 
    Language: Cpp
    BasedOnStyle: LLVM
    MacroBlockBegin: 'QUERY_BEGIN'
    MacroBlockEnd: 'QUERY_END'
    

    clang-format 14.0.6 produces this formatted output:

    #define QUERY_BEGIN()
    #define QUERY_NORESULT()
    #define QUERY_END()
    void foo() {
      int a = 0;
      QUERY_BEGIN()
        a = 1;
        QUERY_NORESULT()
        a = 2;
      QUERY_END()
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.