ICC compile options for evaluating macros in GDB while debugging - c++

I would like to evaluate and print the macro while debugging using GDB. While the GDB documentation has steps to do that by compiling using -g3 flag in gcc compiler, I am using Intel Icc compiler. Their debugging compilation options seem to have no information about macros. Is it possible to do that using icc? If yes what are the compilation options.

icc --help prints almost 2000 lines of output, among which there's
-debug [keyword]
Control the emission of debug information.
Valid [keyword] values:
[snip]
[no]macros
Controls output of debug information for preprocessor macros.
but passing -debug macros results in an error:
icc: command line error: Unrecognized keyword 'macros' for option '-debug'
It's unclear what happened here, perhaps the option was available in the past, and removed since then. You can report this to Intel.
The new LLVM-based Intel compiler, ICX, can emit macro definitions to debug info under the same option as Clang, -fdebug-macro.

Related

Ninja Build System + gcc/clang doesn't output diagnostic colors

When invoking ninja on a C or C++ (hence both tags) project, with the clang or gcc compiler, the output is not colored with ANSI colors.
For example:
error should be red, but isn't.
warning should be yellow/orange, but isn't.
Everything is the same color, and it's really hard to tell what's going on!
Why this happens
This happens because ninja internally creates a pipe(), which stdout and stderr from the compiler (gcc or clang in this case) is re-routed. This makes the check inside gcc and clang, which checks for terminals (which may support color), fail.
A check such as isatty(stdout) does not return true for a pipe, even though that pipe is then forwarded to stdout once again.
It's documented
Ninja's FAQ talks about this on GitHub.com, but this FAQ is not included with the software, not mentioned in the --help, there are no ninja manpages, and common search engines (ddg, google) do not seem to find that FAQ for common search queries relating to color.
Hence, this post, since SO has good SSO.
The fix
Add -fdiagnostics-color=always to your C or CXX flags. For example, with cmake, you can append -DCMAKE_CXX_FLAGS=-fdiagnostics-color=always (or CMAKE_C_FLAGS for C) (or, if you are using CMake 3.24 or later, you can use the CMAKE_COLOR_DIAGNOSTICS variable or environment variable).
This works for gcc (as documented in its manpage) and clang (clang's manpages do not mention this option, but it is included in their command line reference on llvm.org.
As a permanent fix, you could append the following to your .zshrc, .bashrc, or similar:
# force C colored diagnostic output
export CFLAGS="${CFLAGS} -fdiagnostics-color=always"
# force C++ colored diagnostic output
export CXXFLAGS="${CXXFLAGS} -fdiagnostics-color=always"
export CCFLAGS="${CCFLAGS} -fdiagnostics-color=always"
# force C, C++, Cpp (pre-processor) colored diagnostic output
export CPPFLAGS="${CPPFLAGS} -fdiagnostics-color=always"
You should only do this if you KNOW you will never need to pipe your compiler's output anywhere else. Also, this will only work with clang and gcc, and other compilers which support this - so make sure you dont use compilers that choke on this flag.

#pragma(* diagnostic) when mixing Clang analyzers with a GCC compiler

I'm compiling on with GCC on Linux, but CMake is kind enough to produce a Clang compatible compilation database. This means that I can run fancy, modern Clang based tools on my codebase and those tools have perfect knowledge of how each file is to be built (flags, defines, include paths, etc.) So far so good.
But today the Clang based static analysis in my IDE started showing a Clang specific warning. I don't think it particularly matters for my question which warning it is, but it was warning: disabled expansion of recursive macro, generated by -Wdisabled-macro-expansion. This particular macro is provided by a third party, so fixing the warning isn't an option, but I would like to suppress it as it occurs several times in the file in question.
What I'm struggling with is how to suppress the warning in Clang based analysis tools without causing new warnings in the GCC build.
Adding #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" suppresses the warning for Clang tools, but causes GCC to issue warning: ignoring #pragma clang diagnostic [-Wunknown-pragmas].
Similarly, adding #pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" suppresses the Clang warning (because Clang tries to be compatible with GCC diagnostics), but causes GCC to issue warning: unknown option after ‘#pragma GCC diagnostic’ kind [-Wpragmas].
Wrapping either of the above with #ifdef __clang__ makes GCC happy, but doesn't suppress the Clang warning because the tooling is smart enough to know that the code isn't compiled with __clang__, but with __GNUC__ instead.
Is there a way to make a diagnostic #pragma visible to Clang tooling, but not to GCC?
the tooling is smart enough to know that the code isn't compiled with __clang__, but with __GNUC__ instead
If it's reporting a clang-only warning, but does not think that __clang__ is defined, that sounds like a problem with the tooling. If it's trying to be that clever about misrepresenting itself, you may be up a creek... but also you should be complaining to the tool author for creating this situation in the first place.
That said, you could try:
#if defined(__has_warning)
# if __has_warning("-Wdisabled-macro-expansion")
# pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
# endif
#endif
I'm not sure if this will work... it depends on how hard the tooling is pretending to not be clang (__has_warning is a clang-only extension).

G++ ignores _Pragma diagnostic ignored

I am trying to disable g++ warnings in code expanded from macros. By my understanding, _Pragma should follow macro usage and this should not trigger Wparentheses when being compiled with g++:
#include <stdio.h>
#define TEST(expr) \
int a = 1; \
_Pragma( "GCC diagnostic push" ) \
_Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) \
if (a <= expr) { \
printf("filler\n"); \
} \
_Pragma( "GCC diagnostic pop" )
int main(){
int b = 2, c = 3;
TEST(b == c);
}
When I compile this with g++, I get Wparentheses warning, which I am trying to disable.
xarn#DESKTOP-B2A3CNC:/mnt/c/ubuntu$ g++ -Wall -Wextra test3.c
test3.c: In function ‘int main()’:
test3.c:8:11: warning: suggest parentheses around comparison in operand of ‘==’ [-Wparentheses]
if (a <= expr) { \
^
test3.c:15:5: note: in expansion of macro ‘TEST’
TEST(b == c);
^
However it works as expected when using gcc:
xarn#DESKTOP-B2A3CNC:/mnt/c/ubuntu$ gcc -Wall -Wextra test3.c
test3.c: In function ‘main’:
test3.c:16:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
I am using g++ version 4.8.5.
There are long-standing bugs in g++ handling of _Pragmas, that are not present when using the gcc front-end. The only solution is to either go forward to a sufficiently modern version of g++ (IIRC 6+), or to disable the warning for the entire TU.
Xarn's answer was very helpful in working out why we were hitting the same issues with our macros when compiling with g++ < 9.0, but fortunately I'm stubborn and don't take "the only solution" for an answer. Some more digging revealed that there is a workaround for affected versions of GCC.
One of the original 2012 reports for this issue at GNU's bugzilla included an offhand mention from the reporter, that _Pragma() would be processed as expected if they added either -save-temps or -no-integrated-cpp to the compile command.
Turns out, either of those options cause g++ NOT to run in its default streamlined mode, which folds the preprocessing and compiling stages together into a single pass. From the man page for g++ 9.1.1:
-no-integrated-cpp
Perform preprocessing as a separate pass before compilation. By
default, GCC performs preprocessing as an integrated part of input
tokenization and parsing. If this option is provided, the
appropriate language front end (cc1, cc1plus, or cc1obj for C, C++,
and Objective-C, respectively) is instead invoked twice, once for
preprocessing only and once for actual compilation of the
preprocessed input. This option may be useful in conjunction with
the -B or -wrapper options to specify an alternate preprocessor or
perform additional processing of the program source between normal
preprocessing and compilation.
Which means that adding -no-integrated-cpp does indeed work around the _Pragma() bug in every affected version of GCC we've tested — so far that's 5.4, 7.3, and I believe 8.1 — but otherwise has no effect on the final results of the build. (One can deduce from this that the _Pragma() bug was introduced with and by that single-pass streamlining.)
The only real tradeoff is that compilation is indeed a bit slower, if you build with that option enabled. While that's certainly worth it when your GCC is one of the affected versions, we're using a conditional in our CMake build setup to ensure -no-integrated-cpp is only set when necessary:
#### Work around a GCC < 9 bug with handling of _Pragma() in macros
#### See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
if ((${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") AND
(${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS "9.0.0"))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-integrated-cpp")
endif()
(Substitute appropriately modern calls to target_compile_options() for the ugly brute-forcing of CMAKE_CXX_FLAGS, if your CMake setup is better than ours.)
Typically you use warning suppression only to deal with unavoidable warning coming from third-party code so they won't clutter compilation logs. In your case it would be better to
1) use regular function because macros are evil
2) deal with warning by adding round brackets around potentially broken expression
if (a <= (expr)) {

Assembler Messages: no such instruction when Compiling C++

I am attempting to compile a C++ code using gcc/5.3 on Scientific Linux release 6.7. I keep getting the following errors whenever I run my Makefile though:
/tmp/ccjZqIED.s: Assembler messages:
/tmp/ccjZqIED.s:768: Error: no such instruction: `shlx %rax,%rdx,%rdx'
/tmp/ccjZqIED.s:1067: Error: no such instruction: `shlx %rax,%rdx,%rdx'
/tmp/ccjZqIED.s: Assembler messages:
/tmp/ccjZqIED.s:6229: Error: no such instruction: `mulx %r10,%rcx,%rbx'
/tmp/ccjZqIED.s:6248: Error: no such instruction: `mulx %r13,%rcx,%rbx'
/tmp/ccjZqIED.s:7109: Error: no such instruction: `mulx %r10,%rcx,%rbx'
/tmp/ccjZqIED.s:7128: Error: no such instruction: `mulx %r13,%rcx,%rbx'
I've attmpted to follow the advice from this question with no change to my output:
Compile errors with Assembler messages
My compiler options are currently:
CXXFLAGS = -g -Wall -O0 -pg -std=c++11
Does anyone have any idea what could be causing this?
This means that GCC is outputting an instruction that your assembler doesn't support. Either that's coming from inline asm in the source code, or that shouldn't happen, and suggests that you have compiled GCC on a different machine with a newer assembler, then copied it to another machine where it doesn't work properly.
Assuming those instructions aren't used explicitly in an asm statement you should be able to tell GCC not to emit those instructions with a suitable flag such as -mno-avx (or whatever flag is appropriate to disable use of those particular instructions).
#jonathan-wakely's answer is correct in that the assembler, which your compiler invokes, does not understand the assembly code, which your compiler generates.
As to why that happens, there are multiple possibilities:
You installed the newer compiler by hand without also updating your assembler
Your compiler generates 64-bit instructions, but assembler is limited to 32-bit ones for some reason
Disabling AVX (-mno-avx) is unlikely to help, because it is not explicitly requested either -- there is no -march in the quoted CXXFLAGS. If it did help, then you did not show us all of the compiler flags -- it would've been best, if you simply included the entire compiler command-line.
If my suspicion is correct in 1. above, then you should build and/or install the latest binutils package, which will provide as aware of AVX instructions, among other things. You would then need to rebuild the compiler with the --with-as=/path/to/the/updated/as flag passed to configure.
If your Linux installation is 32-bit only (suspicion 2.), then you should not be generating 64-bit binaries at all. It is possible, but not trivial...
Do post the output of uname -a and your entire compiler command-line leading to the above error-messages.

how can I check a particular gcc feature in configure.ac

For example, gcc 4.7 has a new feature -Wnarrowing. In configure.ac, how can I test where a feature is supported by the current gcc or not?
There's a file in gnulibc, but doesn't make much sense to me.
Both gcc and clang support -W[no-]narrowing and -W[no-]error=narrowing options.
With -std=c++11, gcc emits a warning by default, and clang emits an error by default. Even though you only mention gcc, I think you could extend the functionality check to compilers like clang that attempt to provide the same options and extensions. That might include Intel's icc too.
Let's assume you've selected the C++ compiler with AC_PROG_CXX, and have ensured that it's using the C++11 standard.
ac_save_CXXFLAGS="$CXXFLAGS"
CXXFLAGS="$CXXFLAGS -Werror -Wno-error=narrowing"
AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],
[[int i {1.0}; (void) i;]])],
[ac_cxx_warn_narrowing=1], [ac_cxx_warn_narrowing=0])
AS_IF([test $ac_cxx_warn_narrowing -ne 0],
[AC_MSG_RESULT(['$CXX' supports -Wnarrowing])])
AC_LANG_POP([C++])
CXXFLAGS="$ac_save_CXXFLAGS"
Compilation will only succeed if: 1) the compiler supports -Wnarrowing related options, which implies it supports -Werror, and: 2) recognizes C++11 initialization syntax.
Normally, configure.ac scripts and flags passed to configure should avoid -Werror, as it breaks too many internal tests. In this context, we ensure there are no other warnings besides the narrowing, which is why (void) i; is needed to prevent a warning about unused variables.
The logic behind this should probably be:
Create a correct file that should get a warning with -Wnarrowing. Verify that it gets compiled correctly. This is a sanity check.
Then compile that same file with -Wnarrowing, and verify that it still gets compiled correctly. This makes sure you detect compilers that don't support -Wnarrowing as an option, and don't attempt to pass bogus options to them.
Finally, compile that same file with -Werror=narrowing, and verify that it now does not get compiled correctly. If it now fails, you can be fairly certain that the compiler does indeed support -Wnarrowing. This last check is useful to detect compilers that do accept -Wnarrowing/-Werror=narrowing, but spit out a warning "ignoring unknown option -Wnarrowing". In that case, you shouldn't be passing -Wnarrowing.
Optionally, you may also want to compile a file that shouldn't get a warning with -Wnarrowing with -Werror=narrowing, in case you find a compiler where -Wnarrowing is useless and -Werror=narrowing is a hard error. I cannot think of a compiler where this would be required, though.
Translating this to a configure check should be trivial.
See http://code.google.com/p/opendoom/source/browse/trunk/VisualC8/autotools/ac_c_compile_flags.m4 for an example test of this sort - this tries to compile a trivial program with the given compiler flag, and adds it to CFLAGS if it works.