C/C++ no curly brace after if/for, how to lint it out?
Asked Answered
D

3

6

Is there way to get rid or find by linting (or maybe seding/regexping) these nasty situations when your have just one line of code after if/for statement, without curly braces? Like this one:

if(condition)
    return;

For reference why would I want to get rid of that - there are lots of reasons given in this thread:

What's the purpose of using braces (i.e. {}) for a single-line if or loop?

I maintain some legacy code, and deal with some not-really-finished code from other people, and from time to time stumble on situation when this code-style works like a trip wire when debugging:

if(condition_for_early_return)
    LOG("Im here")   // surprise surprise, I just broke control logic
    return;

Also, I've seen code like that:

if(condition)
<tabs>   do_smth();
<spaces> do_smth_else();

Of course if contains only first do_smth(), compiler is not confused. But because the do_ functions are visually aligned, I wonder - is this intended behaviour or is it a bug that was never found in this legacy code.

I know cppcheck does not catch these situation - already tried that. Do you have any way of finding these traps automatically?

Disillusionize answered 27/1, 2023 at 8:4 Comment(1)
But because the do_ functions are visually alligned ANOTHER reason to never use tabs for indentation: obfuscation of actual intent.Tame
O
12

GCC has:

-Wmisleading-indentation (C and C++ only)

Warn when the indentation of the code does not reflect the block structure. Specifically, a warning is issued for if, else, while, and for clauses with a guarded statement that does not use braces, followed by an unguarded statement with the same indentation.

In the following example, the call to “bar” is misleadingly indented as if it were guarded by the “if” conditional.

  if (some_condition ())
    foo ();
    bar ();  /* Gotcha: this is not guarded by the "if".  */

In the case of mixed tabs and spaces, the warning uses the -ftabstop= option to determine if the statements line up (defaulting to 8).

The warning is not issued for code involving multiline preprocessor logic such as the following example.

  if (flagA)
    foo (0);
#if SOME_CONDITION_THAT_DOES_NOT_HOLD
  if (flagB)
#endif
    foo (1);

The warning is not issued after a #line directive, since this typically indicates autogenerated code, and no assumptions can be made about the layout of the file that the directive references.

Note that this warning is enabled by -Wall in C and C++.


Alternatively, clang-format provides:

-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.

But also issues a 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.

Ocasio answered 27/1, 2023 at 8:21 Comment(0)
S
4

A quick google showed that SonarSource's linter has a rule for this: https://rules.sonarsource.com/cpp/RSPEC-121

I believe there's a way to use this tool for free to some extent, so it should work.

Alternatively, clang-format supports the option to just add them since v15: https://clang.llvm.org/docs/ClangFormatStyleOptions.html#insertbraces

Sextain answered 27/1, 2023 at 8:6 Comment(0)
U
2

Clang-tidy actually has a check for that, and if I remember correctly, it can also fix things automatically for you (you should of course then manually go through all the changes and make sure they're correct)

Unclassified answered 27/1, 2023 at 8:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.