I'm looking at a project in which some if
and for
statements do not have their associated brackets, like so:
if(condition)
single_line_statement;
for(int i=0;i<10;i++)
single_line_statement;
I want to find these statements!
However, this is made challenging by the existence of code with two different bracketing styles:
if(condition){
stuff;
}
and
if(condition(a) && condition(b))
{
stuff;
}
as well as by complex statements such as (note the nested brackets):
for (auto const &x : y)
{
for (auto const &m : ted.bob())
{
if (m.n(o) != 0)
{
p[q] = true;
}
r["s"].push_back(rn.t(u));
}
}
How can I find the if
and for
statements without brackets?
To solve this problem, I created a handy dandy script:
#!/bin/bash
find . -name '*.h' -o -name '*.cpp' | #Find all C++ files
xargs pcregrep -A 1 -nHM '\b(?:if|for)\s*(\(([^()]++|(?1))*\))(?!.*{|.*\n.*{)'
This finds all the C++ files and then examines the contents of each file as a single, long line using a Perl Compatible Regular Expression. This expression uses recursion (?1)
to extract the (condition)
following the if
and for
statements and the .
character to match characters which are not newlines and the \n
constant to match new lines. Negative-lookahead (?!...)
is used to find the lines without braces.
The regular expression can be tested online here.
The output looks like this:
./dir1/file1.cpp:845: if (!a)
./dir1/file1.cpp-846- std::cout << "a not found!" << std::endl;
--
./dir2/file2.cpp:20: if (b == NULL)
./dir2/file2.cpp-21- throw std::runtime_error("b was NULL");
Since the script does not, in fact, parse C++, there are situations where it will misbehave. For instance, it will miss this:
if (condition) // An example {
statement;
This answer leverages clang-tidy
to provide a complete check, at the cost of having to incorporate clang-tidy
into one's build system.
I use vera++
to validate that code in my project conforms to specific style rules.
Vera: https://bitbucket.org/verateam/vera/wiki/Rules
Rule: T019 Control structures should have complete curly-braced block of code