Is there any static checking tool to check buggy code like this - c++

I wrote the some buggy code like this:
#include "stdafx.h"
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string some_file = "afdfadf";
if(true)
{
string some_file = "/"+ some_file;
}
return 0;
}
It will throw an exception when calling std::operator+.
I guess this is because in the if statement the second some_file is an uninitialized string.
Is there any static checking tool that can help find this kind of bug?

I just tried, clang can help find the bug:
[~]$ clang bug.cpp
bug.cpp:11:29: warning: variable 'some_file' is uninitialized when used within
its own initialization [-Wuninitialized]
string some_file = "/"+ some_file;
~~~~~~~~~ ^~~~~~~~~

GCC has a warning for that case:
$ g++ t.cc -Wshadow
t.cc: In function ‘int main(int, char**)’:
t.cc:11:16: warning: declaration of ‘some_file’ shadows a previous local [-Wshadow]
t.cc:7:12: warning: shadowed declaration is here [-Wshadow]

Compilers can warn you about using a variable in its own initialization.
In GCC and CLANG, you can use -Winit-self
I am not sure about MSVC, but compiling with /W4 might give you a warning about those, too.

I was quit happy with using pclint. It will find this type of errors but it might take some time to configure it when used with an existing, larger code base.

Related

How to get the compiler to warn that this is an invalid bool?

We just got burnt by a typo: "constexpr bool maxDistance=10000;"
Both gcc and clang compile this with no warning.
The real error here is that the variable shouldn't have been of type bool, but should have been an integer type instead.
How can we ensure we get a compiler warning in future?
#include <iostream>
constexpr bool number = 1234;
int main(int argc, char* argv[])
{
std::cout << number + 10000 << std::endl; // prints 10001.
return number;
}
The error here is that the variable is declared with the wrong type, however neither clang nor gcc give a warning.
gcc -Wall -std=c++14 test.cpp -lstdc++
clang -Wall -std=c++14 test.cpp -lstdc++
(using gcc 5.4.0 and clang 3.8.0)
Note: I've since learnt about a possible compile flag: -Wint-in-bool-context however this doesn't appear to be implemented in the version I'm using (5.4.0) nor in clang (3.8.0).
Is this the right way to go?
You should use direct list initialization syntax, it prohibits narrowing:
constexpr bool number{1234}; // error: narrowing conversion of '1234' from 'int' to 'bool' [-Wnarrowing]
I've discovered that gcc has a flag '-Wint-in-bool-context' however this doesn't appear to be implemented in the version I'm using (5.4.0) nor in clang (3.8.0).
Is this the right way to go?

std::byte is not member of 'std'

I'm trying to learn new features/gimmicks of c++17, but then I got to std::byte and for some unknown reason I can't seem to be able to compile even most basic "hello world" type program with the type.
entire program:
#include <cstddef>
int main(int argc, char* argv[])
{
std::byte byte;
return 0;
}
compilation command:
g++ ./main.cpp
But the output is always:
./main.cpp: In function ‘int main(int, char**)’:
./main.cpp:4:10: error: ‘byte’ is not a member of ‘std’
std::byte byte;
I work on Ubuntu 18.04 with gcc 7.4.0. I have checked "/usr/include/c++/7.4.0/" and header file cstddef is there and byte seems to be defined.
I have also tried to use clang:
clang++ ./main.cpp
But the result was same. At this point I can only think that cstddef is corrupted/bugged. Are there any solutions to this?
As πάντα ῥεῖ pointed out in comment I was missing c++17 compile flag. Right compilation command:
g++ -std=c++17 ./main.cpp
If you use clang 5.0 (even with -std=c++17 flag) the same error occur.
In that case, to solve this you need to upgrade to clang 6.
A temporay and quick workaround is possible (but not recommanded since it plays with std namespace), it could be something like:
#if defined(__clang__) && __cplusplus >= 201703L && __clang_major__ < 6
// This is a minimal workaround for clang 5.0 with missing std::byte type
namespace std {
enum class byte : unsigned char {};
}
#endif

Missing "missing sentinel" warning for exec in C++11

GCC will helpfully warn you if you forget to include the NULL sentinel at the end of a call to one of the exec(3) functions:
#include <unistd.h>
int main(int argc, char **argv)
{
execlp("test", "test", "arg1");
}
Sample compiler output for GCC 4.8:
$ g++ test.cc -Wformat
test.cc: In function ‘int main(int, char**)’:
test.cc:4:32: warning: missing sentinel in function call [-Wformat=]
execlp("test", "test", "arg1");
^
$
However, if you compile in C++11 mode, no diagnostic is printed:
$ g++ test.cc -std=c++11 -Wformat
$
Why is this warning not available in C++11? Is there any way to get it back?
execlp is not a standard C function. For the compiler to recognize it as a "standard" function, for which it knows what the arguments should look like, you need -std=gnu++11 instead of -std=c++11. Note that the default is -std=gnu++98. Glibc could improve the situation by specifying the sentinel attribute on the declaration of execlp.

Code compiles in ideone but not with gcc

I wrote the following code:
#include <iostream>
using namespace std;
int main()
{
int v()
return 0;
}
I ran it in ideone, and it compiled successfully. I have the same code in file test1.cpp on my computer, I ran g++ test1.cpp and I got the following error:
./test1.cpp: In function ‘int main()’:
./test1.cpp:7:2: error: a function-definition is not allowed here before ‘return’
Why dose this happen? is this a bug?
I'm using linux mint, gcc version 4.7.
You are missing a semi-colon here:
int v()
^
should be:
int v() ;
which is a function declaration, not clear that was what was intended though. If you want to initialize v then the following would work:
int v(0) ;
or in C++11:
int v{0} ;
This is commonly known as C++'s most vexing parse. When you do something like
int f();
the compiler reads this as a function prototype, declaring a function f that returns an int. If you're using C++11, you should instead do
int f{}; // f initialized to 0
if you're not using C++11, make sure to initialize the variable right away.
You forgot the semicolon after
int v();
Ideone is using gcc 4.8.1 for your code (as you can see in your own link) while you are using 4.7
There are several difference regarding C++ 11 implementation, and apparently it is affected by the line that looks like a function delcaration.

Overkilling "crosses initialization of variable" error in C++?

I noticed that g++ complain a bit too strictly about crossed initialization and I wonder why these false-positive errors could not be removed just by looking at the SSA form of the program while compiling.
Let me give a very simple example:
#include <cstdlib>
int main ()
{
goto end;
int i = 0; // unused variable declaration
end:
return EXIT_SUCCESS;
}
When compiled with g++ -Wall -Wextra -o example1 example1.cc (g++ 4.8.1), the compiler gives the following error message:
example1.cc: In function ‘int main()’:
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive]
end:
^
example1.cc:6:8: error: from here [-fpermissive]
goto end;
^
example1.cc:8:7: error: crosses initialization of ‘int i’
int i = 0;
^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable]
So, it will raise an error where there is actually no risk because the variable is unused (the compiler obviously has both information and cannot combine it to deduce that the error is a false-positive).
More strange, I hoped that LLVM was more efficient at analyzing a program. So, I tried clang++ (LLVM) on this simple example with clang++ -Wall -Wextra -o example1 example1.cc (clang++ 3.4). And, I got about the same error message:
example1.cc:8:7: warning: unused variable 'i' [-Wunused-variable]
int i = 0;
^
example1.cc:6:3: error: goto into protected scope
goto end;
^
example1.cc:8:7: note: jump bypasses variable initialization
int i = 0;
^
1 warning and 1 error generated.
So, I am pretty sure that I am missing something important here, a problem that make the detection of this false-positive harder than I though. But, I do not know what is it. Or maybe, the C++ specification specifically says that it must be like this.
If somebody has an idea, feel free to share !
Edit: I also compiled the exact same code in C (gcc or clang), and it went fine just with the warning about i being an unused variable. So, it reinforce the fact that this is more likely linked to the specification of C++ and not a problem detecting this issue at compile time.
There is nothing wrong with the compilers. Your code is ill-formed according to the standard.
In your particular case, the requirement of the standard may not be necessary and the jump could be allowed and the compiler could create valid code. However, this is only because the initialisation of the variable int i has no side effects.
You can make your code valid by simply enclosing the jumped section in its own scope:
#include <cstdlib>
int main ()
{
goto end;
{
int i = 0; // unused variable declaration
}
end:
// cannot use i here, as it's not defined.
return EXIT_SUCCESS;
}
This is disallowed because potentially you'd call destructors for objects that aren't properly constructed. Admittedly, int doesn't have constructor or destructor, but it's making it "fair" for all types of objects. And technically, something at label end: could be using i, and by making the rule strict, it prevents the machine having to check every single code-path (which becomes a "halting problem").