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

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.

Related

Configure clang-check for c++ standard libraries

I am trying to run Ale as my linter, which in turn uses clang-check to lint my code.
$ clang-check FeatureManager.h
Error while trying to load a compilation database:
Could not auto-detect compilation database for file "FeatureManager.h"
No compilation database found in /home/babbleshack/ or any parent directory
json-compilation-database: Error while opening JSON database: No such file or directory
Running without flags.
/home/babbleshack/FeatureManager.h:6:10: fatal error: 'unordered_map' file not found
#include <unordered_map>
^~~~~~~~~~~~~~~
1 error generated.
Error while processing /home/babbleshack/FeatureManager.h.
Whereas compiling with clang++ returns only a warning.
$ clang++ -std=c++11 -Wall FeatureManager.cxx FeatureManager.h
clang-5.0: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated [-Wdeprecated]
There are no flags to clang-check allowing me to set compilation flags.
Took a while to figure this out, but you can do
clang-check file.cxx -- -Wall -std=c++11 -x c++
or if you are using clang-tidy
clang-tidy file.cxx -- -Wall -std=c++11 -x c++
To get both working with ALE, I added the following to my vimrc
let g:ale_cpp_clangtidy_options = '-Wall -std=c++11 -x c++'
let g:ale_cpp_clangcheck_options = '-- -Wall -std=c++11 -x c++'
If you want ALE to work for C as well, you will have to do the same for g:ale_c_clangtidy_options and g:ale_c_clangcheck_options.
I was getting stumped by a similar error message for far too long:
/my/project/src/util.h:4:10: error: 'string' file not found [clang-diagnostic-error]
#include <string>
^
I saw other questions suggesting that I was missing some critical package, but everything already seemed to be installed (and my code built just fine, it was only clang-tidy that was getting upset).
Passing -v showed that my .h file was being handled differently:
$ clang-tidy ... src/*.{h,cc} -- ... -v
...
clang-tool ... -main-file-name util.cc ... -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9 ... -x c++ ... /tmp/copy/src/util_test.cc
...
clang-tool ... -main-file-name util.h ... -x c-header /my/project/src/util.h
...
As Kris notes the key distinction is the -x c-header flag, which is because clang assumes a .h file contains C, not C++, and this in turn means that the system C++ includes weren't being used to process util.h.
But the -main-file-name flag also stood out to me as odd; why would a header file ever be the main file? While digging around I also came across this short but insightful answer that header files shouldn't be directly compiled in the first place! Using src/*.cc instead of src/*.{h,cc} avoids the problem entirely by never asking Clang to try to process a .h on its own in the first place!
This does introduce one more wrinkle, though. Errors in these header files won't be reported by default, since they're not the files you asked clang-tidy to look at. This is where the "Use -header-filter=. to display errors from all non-system headers.*" message clang-tidy prints comes in. If I pass -header-filter=src/.* (to only include my src headers and not any other header files I'm including with -I) I see the expected errors in my header files. Phew!
I'm not sure whether to prefer -x c++ or -header-filter=.* generally. A downside of -header-filter is you have to tune the filter regex, rather than just passing in the files you want to check. But on the other hand processing header files in isolation is essentially wasteful work (that I expect would add up quickly in a larger project).

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.

Suppress unused variable warning in gfortran using -Wextra and -Wall fortran

I'm debugging a large code with the flags -Wall and -Wextra, but I'm getting hundreds of Unused parameter warnings which I'm not interested in. Is there a way to suppress only these warnings?
Simply append -Wno-unused-parameter... See here for details.
From the docs:
Each of these specific warning options also has a negative form
beginning -Wno- to turn off warnings; for example, -Wno-implicit.

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

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.

Meaning of -DHAVE_CONFIG_H in makefiles

I am starting to learn about makefiles. Looking at the output I see a lot of occurrences of:
g++ -DHAVE_CONFIG_H -I ...
what is -DHAVE_CONFIG_H exactly? What is the function of this compilation option?
All that -DHAVE_CONFIG_H does is to define the pre-processor token HAVE_CONFIG_H exactly as if you had #define HAVE_CONFIG_H right at the start of each of your source files.
As to what it's used for, that depends entirely upon the rest of your source file (and everything that it includes as well). That's where you should be looking for to work out its effect.
It looks like it may mean that a header file config.h is available and should be included, in which case you'll probably find the following sequence somewhere in you source files:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
which will include the header file when you say it's available. However that's supposition on my part and by no means the exact effect, just what I would use such a preprocessor symbol for.

Resources