78

Is there an option for clang-format to add braces to all if()/do/while statements etc?

eg

if( i == 42 )
   std::cout << "You found the meaning of life\n";
else
   std::cout << "Wrong!\n";

to

if( i == 42 )
{
   std::cout << "You found the meaning of life\n";
}
else
{
   std::cout << "Wrong!\n";
}

Using

$ clang-format --version
clang-format version 3.6.0
Adrian Cornish
  • 23,227
  • 13
  • 61
  • 77
  • 2
    I did not find any option for this in a quick scan of the [Clang-Format Style Options.](http://clang.llvm.org/docs/ClangFormatStyleOptions.html) – Baum mit Augen Sep 30 '14 at 01:13
  • 2
    @BaummitAugen I could not either - but the description of what some of the options do is very vague IMHO – Adrian Cornish Sep 30 '14 at 01:16
  • See [this answer](https://stackoverflow.com/a/57318252/752843) for a way of searching for common occurrences of single-lines without braces. – Richard Aug 02 '19 at 00:13
  • 1
    You just could't make this up. They format everything...... except this – user997112 Jul 08 '20 at 10:39

2 Answers2

45

clang-tidy can make syntactic changes to your code using FIXITS

clang-tidy YOUR_FILE.cpp -fix -checks="readability-braces-around-statements" -- COMPILE_OPTIONS

Updated:

clang-tidy is a bit of a heavyweight tool for this as it needs compile options to parse the file, sadly clang-format (as of v3.9) won't add braces.

COMPILE_OPTIONS would be the include paths etc that you use to compile the file with, ie -std=c++14 -stdlib=libc++ -O2 -I.

If you have a compile_options.json file from CMake then you can pass the path of the directory it is contained in to clang-tidy and it will look up the appropriate compile options for the file:

clang-tidy YOUR_FILE.cpp -fix -checks="readability-braces-around-statements" -p COMPILE_OPTIONS_DIR
jbcoe
  • 3,611
  • 1
  • 30
  • 45
  • 2
    Is it possible to run this without making a compilation database? Say I purely only wanted to run the readability check, without looking for compile errors. I ask because I want to edit individual files independent of the entire project. When I try to do this I get `Error while trying to load a compilation database` and `Running without flags.` Which I think is to say that it ignores the readability check, since it does not add the braces as I'd wished. – Novice C Sep 02 '16 at 19:14
  • To give a concrete example, say my file has `#include "../header.h"` but I am editing the file in a directory with no `header.h` in the parent directory. Is it possible to still use clang-tidy in this scenario? – Novice C Sep 02 '16 at 19:19
  • I've updated my answer with extra info as it won't neatly fit in a comment. – jbcoe Sep 03 '16 at 15:36
  • I'm not sure I can think of compiler flags that would get your particular example, with a file referenced by a relative include, working. – jbcoe Sep 04 '16 at 23:59
  • clang-tidy is just really a front-end for the static analyzer. It really needs to be part of your build process. – Droopycom May 11 '18 at 22:51
  • @jbcoe Checking in, as of version clang-format 7.0, is it still impossible for it to add braces? – Tyler Shellberg Nov 25 '19 at 18:12
  • @TylerShellberg Have you found anything out about this? – dovedevic Feb 11 '20 at 03:19
22

Starting clang-format-15 (currently trunk), the answer is yes - using the new InsertBraces option, which landed just today:
https://github.com/llvm/llvm-project/commit/77e60bc42c48e16d646488d43210b1630cd4db49 https://reviews.llvm.org/D120217

From the clang-format documentation:

InsertBraces (Boolean) clang-format 15

Insert braces after control statements (if, else, for, do, and while) in C++ unless the control statements are inside macro definitions or the braces would enclose preprocessor directives.

Warning:

Setting this option to true could lead to incorrect code formatting due to clang-format’s lack of complete semantic information. As such, extra care should be taken to review code changes made by this option.

false:                                    true:

if (isa<FunctionDecl>(D))        vs.      if (isa<FunctionDecl>(D)) {
  handleFunctionDecl(D);                    handleFunctionDecl(D);
else if (isa<VarDecl>(D))                 } else if (isa<VarDecl>(D)) {
  handleVarDecl(D);                         handleVarDecl(D);
else                                      } else {
  return;                                   return;
                                          }

while (i--)                      vs.      while (i--) {
  for (auto *A : D.attrs())                 for (auto *A : D.attrs()) {
    handleAttr(A);                            handleAttr(A);
                                            }
                                          }

do                               vs.      do {
  --i;                                      --i;
while (i);                                } while (i);
valiano
  • 16,433
  • 7
  • 64
  • 79
  • 1
    Interesting - I think I'll pull and build it to try it out - I wonder if it handles `#defines` better than clang-tidy does. clang-tidy always makes a mess of `if(x==y) #ifdef OS1 z=103 #else z=-23 #endif` Only 8 years after I asked ;-) – Adrian Cornish Feb 22 '22 at 11:51