GCC 4.5: Why no compiler warning on no-effect statement? - gcc

I am using gcc 4.5 to compile a Linux kernel module. I just noticed that I have some code that looks like this:
#define NODE_ID "string_here"
int foot(int a) {
/* snip */
NODE_ID;
NODE_ID;
/* snip */
return 0;
}
I have these two no-effect statements, and the compiler never generates a warning telling me about them. Why is this? I wonder if there's other statements like this floating in my project that I haven't found.

It does warn you, you just weren't listening -- as #Mat said in the comments, you need to enable the -Wall option, and it will warn you:
$ gcc test.c -c -Wall
test.c: In function ‘foot’:
test.c:5:5: warning: statement with no effect
test.c:6:5: warning: statement with no effect
Or, you can just enable the -Wunused-value option for just this warning, but I highly recommend using -Wall, which includes this and many other useful warnings. You can also enable -Wextra and -pedantic for even more, but these sometimes give false positives for code which is perfectly fine, adding extra noise to your build process. So use them judiciously.

Related

why does main() compile in g++ compiler, but not in Visual studio IDE

Why does the following code works perfectly on a g++ compiler, but gives error on Visual Studio IDE?
#include<iostream>
using namespace std;
main()
{
cout <<"this is a test"<<
return 0;
}
In visual studio, I have to change code to the following:
#include<iostream>
using namespace std;
int main()
{
cout <<"this is a test"<<
return 0;
}
Default configuration of GCC compiler is notorious for allowing non-standard features (kept for misguided "backward compatibility" with anscient code) to leak into C and even into C++ code.
If you prefer to write your code in standard C or C++ language, make sure to use such compiler settings as -pedantic or, better, -pedantic-errors as well as the appropriate -std=... setting. These options are not perfect, but they will make the compiler to catch the majority of basic errors.
The first program is invalid C++, but since this style of function definition (with no explicit return type) was once common in C, g++ lets you get away with it by default for sake of backwards compatibility. Visual Studio doesn't do this.
If you want g++ to keep strict standard compliance (you should), use
g++ -pedantic -std=c++11 (or -std=c++14)
This should flag your program as invalid with a warning message. It is not enough to use just -std=c++xx. Always use both options.
It is also advisable to enable various additional warning messages, for example:
g++ -Wall -Wextra -Weffc++
-Weffc++ can give you false positives, see discussion in comments
Warnings should never be ignored, but if you want the compiler to enforce this, the following recommended option makes it treat all warnings as errors:
g++ -Werror

Passing multiple -std switches to g++

Is it safe to assume that running g++ with
g++ -std=c++98 -std=c++11 ...
will compile using C++11? I haven't found an explicit confirmation in the documentation, but I see the -O flags behave this way.
The GCC manual doesn't state that the
last of any mutually exclusive -std=... options specified takes effect. The first occurrence
or the last occurrence are the only alternatives. There are numerous
GCC flags that take mutually exclusive alternative values from a finite set - mutually
exclusive, at least modulo the language of a translation unit. Let's call them mutex options for short.
It is a seemingly random rarity for it to be documented that the last setting takes effect. It is
documented for the -O options as you've noted, and in general terms for mutually exclusive warning options, perhaps
others. It's never documented that the first of multiple setting takes effect, because
it's never true.
The documentation leans - with imperfect consistency - on the historical conventions
of command usage in unix-likes OSes. If a command accepts a mutex option
then the last occurrence of the option takes effect. If the command were - unusually -
to act only on the first occurrence of the option then it would be a bug for
the command to accept subsequent occurrences at all: it should give a usage error.
This is custom and practice. The custom facilitates scripting with tools that
respect it, e.g. a script can invoke a tool passing a default setting of some
mutex option but enable the user to override that setting via a parameter of the script,
whose value can simply be appended to the default invocation.
In the absence of official GCC documentation to the effect you want, you might get
reassurance by attempting to find any GCC mutex option for which it is not
the case that the last occurrence takes effect. Here's one stab:
I'll compile and link this program:
main.cpp
#include <cstdio>
#if __cplusplus >= 201103L
static const char * str = "C++11";
#else
static const char * str = "Not C++11";
#endif
int main()
{
printf("%s\n%d\n",str,str); // Format `%d` for `str` mismatch
return 0;
}
with the commandline:
g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp
which requests contradictory option pairs:
-std=c++98 -std=c++11: Conform to C++98. Conform to C++11.
-m32 -m64: Produce 32-bit code. Produce 64-bit code.
-O0 -O1: Do not optimise at all. Optimize to level 1.
-g3 -g0: Emit maximum debugging info. Emit no debugging info.
-Wformat -Wno-format. Sanity-check printf arguments. Don't sanity check them.
-o wrong -o right. Output program wrong. Output program right
It builds successfully with no diagnostics:
$ echo "[$(g++ -std=c++98 -std=c++11 -m32 -m64 -O0 -O1 -g3 -g0 \
-Wformat -Wno-format -o wrong -o right main.cpp 2>&1)]"
[]
It outputs no program wrong:
$ ./wrong
bash: ./wrong: No such file or directory
It does output a program right:
$ ./right
C++11
-1713064076
which tells us it was compiled to C++11, not C++98.
The bug exposed by the garbage -1713064076 was not diagnosed because
-Wno-format, not -Wformat, took effect.
It is a 64-bit, not 32-bit executable:
$ file right
right: ELF 64-bit LSB shared object, x86-64 ...
It was optimized -O1, not -O0, because:
$ "[$(nm -C right | grep str)]"
[]
shows that the local symbol str is not in the symbol table.
And it contains no debugging information:
echo "[$(readelf --debug-dump right)]"
[]
as per -g0, not -g3.
Since GCC is open-source software, another way of resolving doubts
about its behaviour that is available to C programmers, at least,
is to inspect the relevant source code, available via git source-control at
https://github.com/gcc-mirror/gcc.
The relevant source code for your question is in file gcc/gcc/c-family/c-opts.c,
function,
/* Handle switch SCODE with argument ARG. VALUE is true, unless no-
form of an -f or -W option was given. Returns false if the switch was
invalid, true if valid. Use HANDLERS in recursive handle_option calls. */
bool
c_common_handle_option (size_t scode, const char *arg, int value,
int kind, location_t loc,
const struct cl_option_handlers *handlers);
It is essentially a simple switch ladder over option settings enumerated by scode - which
is OPT_std_c__11 for option -std=c++11 - and leaves no doubt that it
puts an -std option setting into effect regardless of what setting was in effect previously. You can look at branches other than master
(gcc-{5|6|7}-branch) with the same conclusion.
It's not uncommon to find GCC build system scripts that rely on the validity of
overriding an option setting by appending a new setting. Legalistically, this
is usually counting on undocumented behaviour, but there's a better
chance of Russia joining NATO than of GCC ceasing to take the last setting that
it parses for a mutex option.

Disabling -Werror for -Wimplicit-interface

What is the right flag or order of flags to disable treating particular warning as error in GCC? I want to do that for -Wimplicit-interface.
>cat test.f90
call s
end
> gfortran -c -Werror -Wimplicit-interface -Wno-error=implicit-interface test.f90 -o test.o
test.f90:1.7:
call s
1
Warning: Procedure 's' called with an implicit interface at (1)
>ls test*
test.f90
No test.o was generated.
Without -Werror it works
> gfortran -c -Wimplicit-interface -Wno-error=implicit-interface test.f90 -o test.o
test.f90:1.7:
call s
1
Warning: Procedure 's' called with an implicit interface at (1)
> ls test*
test.f90 test.o
GCC version is gcc version 4.9.2 20141030 (Cray Inc.) (GCC).
This is not an explicit answer to the question. I found it educative enough and too long to be put as comment.
As you just found, you might not be able to achieve what you want if you combine -Werror and -Wno-error=implicit-interface. Let me explain: as opposed to what we have in the doc, especially the following sentence,
The combined effect of positive and negative forms is that more specific options have priority over less specific ones, independently of their position in the command-line.
It seems that it is not the case in the actual implementation. I had a similar problem recently, and by googling, I found this which contains this sentence:
'-w' permanently sets all warnings off no matter what specific warning is set on
It actually suggests that by using some non specific options, the actual implementation does not allow you to change specific option included in the non specific one.
As #innoSPG points out, the actual behaviour does not conform to what is claimed in the manual.
The comment by #MarkGlisse revealed that this have changed with GCC 5. Therefore it was probably a bug.
The solution is therefore to use the recent version, or to not use one of the -Werror and -Wimplicit-interface.
Or to really provide explicit interfaces everywhere, but that can be problematic, as MPI libraries differ in the amount of explicit interfaces provided in the mpi modules.

How can i generate a simple linker warning in the Linux kernel?

I have turned on the ld option --fatal-warning in the linux kernel. How can I generate a simple linker warning to test this feature?
#include<stdio.h>
int main()
{
printf("Run !!");
static const char warning[] __attribute__((section(".gnu.warning.printf")))="My sweet linker warning";
return 0;
}
Save this as test.c
If you build this using:
gcc -Wl,--fatal-warnings test.c -o my_exe
You should receive your linker warning and it would not prepare "my_exe"
Now try:
gcc -Wl,--no-fatal-warnings test.c -o my_exe
In this case, warning will be reported as it is but it wont be treated as error and it will prepare "my_exe" for you.
I am not sure what exactly you meant by "turned on", but if you are seeing above behavior then I guess you are good.
If you are doing something with kernel source then you will need to replace printf with any function name you already have in source( also change .gnu.warning section name )
Thank you all for your suggestions. I went through the makefile, and found some linker flags that were suppressing warnings. I just removed them to generate ld warnings.

Suppressing "extra ';'" error in GCC when -pedantic is on

I'm building my program with -pedantic flag, which causes an extra ';' error (because of a third-party header using a few macros inconsistently; the error is not shown when -pedantic is off). I don't really feel like turning -pedantic off, and neither do I want to edit the header. Is there any way to suppress this exact error? Like a -Wno-annoying-semicolon-error compiler switch or something?
You can suppress pedantic warnings for external headers like this:
//save compiler switches
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
//Bad headers with problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
//restore compiler switches
#pragma GCC diagnostic pop
Use -isystem rather then -I when passing include paths, then GCC won't warn you about system headers.
For any headers you maintain, just edit them.
The workaround is to remove -pedantic. Nothing else will work on that case.

Resources