fail compile if required flags aren't present - c++

I have some legacy code that needs certain gcc flags passed in. Can I add pre-processor checks for these flags?
For example, let's say I need -fno-strict-aliasing, can I do something like this:
#ifndef _FNO_STRICT_ALIASING
#error -fno-strict-aliasing is required!
#endif

You can use
#pragma GCC optimize "no-strict-aliasing"
to compile the file with that flag (overriding what was specified on the command line).
You can also use
__attribute__((optimize("no-strict-aliasing")))
to apply the flag to a single function within a source file...

There is definitely no #define for it, at least on my version of GCC.
To see all predefined preprocessor symbols:
g++ -dM -E - < /dev/null
I do not think there is any way to test these options. However, if you are using GCC 4.4 or later, you can use the "optimize" function attribute or the "optimize" #pragma to enable specific options on a per-function or per-file basis.
For example, if you add this to a common header file:
#if defined(__GNUC__)
#pragma GCC optimize ("no-strict-aliasing")
#else
#error "You are not using GCC"
#endif
...it should enable the option for every file that includes the header.
[update]
OK so it took me about 10 minutes too long to compose this answer. I am going to leave it here anyway for the links to the GCC docs.

Related

Distinguish between Clang CL and MSVC CL

There is CLang-CL which is a drop-in replacement for MSVC's CL.
Does anyone know how to distinguish if my code is currently compiled by clang-cl or msvc's cl? Without passing any extra defined macros on command line.
Using
#ifdef _MSC_VER
//.....
#endif
doesn't work, both compilers define _MSC_VER.
Also in regular CLang on Linux (Windows too) it was possible to do clang -dM -E - < /dev/null which dumps all defined macros. But clang-cl and msvc-cl both don't have such option to dump all defined macros as far as I know, so I don't know of a way to see a difference in list of defined macros for both compilers to figure out which macro to use to distinguish between these compilers.
The macro you're looking for is __clang__.
Note that the regular Clang (not only Clang-CL) also defines it, so you want to check for both __clang__ and _MSC_VER at the same time.

How to enable -fpermissive for a section of code

I have a C single-header library that I would like to use in my C++ project. Normally, I would just include the file and that would be fine because C++ is almost a superset of C. However, this library has a goto that jumps over an initialization, violating the C++ standard.
I can get around this be enabling the -fpermissive compiler flag on GCC, but I want the errors to trigger properly for the rest of my code.
Is there a way I can enable it just for this one header file (perhaps similar to #pragma GCC diagnostic XXX).
There's #pragma GCC optimize "blah" or the function attribute __attribute__((optimize("blah"))) that act like the argument -fblah was given for the rest of that file/that specific function, but it doesn't seem to work with -fpermissive:
$ cat foo.cpp
#pragma GCC optimize "permissive"
void foo(int x) {
}
$ g++-8 -c -Wall -Wextra foo.cpp
foo.cpp:1:22: warning: bad option ‘-fpermissive’ to pragma ‘optimize’ [-Wpragmas]
#pragma GCC optimize "permissive"
^~~~~~~~~~~~
foo.cpp:3:16: warning: bad option ‘-fpermissive’ to attribute ‘optimize’ [-Wattributes]
void foo(int x) {
One option would be to put the function that needs this in a file by itself, and configure your build system to compile just that file with -fpermissive, though that breaks the header-only model. Or fix the code so it doesn't need that option at all.
Per gcc man page:
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive allows some nonconforming code to compile.
So in theory, one can allow a section to compile as permissive using a sequence of gcc warning pragmas:
// Start permissive code
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wuninitialized"
// .. Other #pragmas
// Permissive Code here.
// Restore normal processing.
#pragma GCC diagnostic pop
One challenge is that there is no published list of errors that will be ignored with -fpermissive (At least I could not find it). One possible approach will be to compile the code, and enter the '#pragma's one at at a time, until the code compiles cleanly.
If one can identify all (or most) of the rules, possible to put them into #include file.
#pragma GCC diagostic push
#include "permissive.h"
// Permissive Code here
#pragma GCC diagostic pop

Is it possible to determine or set compiler options from within the source code in gcc?

I have some code that requires a certain gcc compiler option (otherwise it won't compile). Of course, I can make sure in the makefile that for this particular source file the required option is set. However, it would much more helpful, if this option could be set for the respective compilation unit (or part of it) from within the source_file.cpp.
I know that warning messages can be switched on or off using #pragma GCC diagnostic, but what about the -fsomething type of options? I take it from this question that this is impossible.
But perhaps there is at least a way to check from within the code whether a certain -f option is on or not?
Note I'm not interested in finding the compiler flags from the binary, as was asked previously, nor from the command line.
In my experience, no. This is not the way you go about this. Instead, you put compiler/platform/OS specific code in your source, and wrap it with the appropriate ifdef statements. These include:
#ifdef __GNUC__
/*code for GNU C compiler */
#elif _MSC_VER
/*usually has the version number in _MSC_VER*/
/*code specific to MSVC compiler*/
#elif __BORLANDC__
/*code specific to borland compilers*/
#elif __MINGW32__
/*code specific to mingw compilers*/
#endif
Within this, you can have version-specific requirements and code:
#ifdef __GNUC__
# include <features.h>
# if __GNUC_PREREQ(4,0)
// If gcc_version >= 4.0
# elif __GNUC_PREREQ(3,2)
// If gcc_version >= 3.2
# else
// Else
# endif
#else
// If not gcc
#endif
From there, you have your makefile pass the appropriate compiler flags based on the compiler type, version, etc, and you're all set.
You can try using some #pragma. See GCC diagnostic pragmas & GCC function specific pragmas.
Otherwise, develop your GCC plugin or your MELT extension and have it provide a pragma which sets the appropriate variables or compiler state inside GCC (actually cc1plus)

Temporarily disable warnings on specific versions of GCC

I have the following situation -
I need to compile my code with two different versions of GCC (3.2 and 4.4) and wish to see all warnings and treat them as errors (it's a slippery slope otherwise). I must include header files I cannot change that include some code. This code makes the newer GCC throw warnings (like unused parameter).
If I add something like
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <bad_header.hpp>
#pragma GCC diagnostic error "-Wunused-parameter"
it solves the issue with the newer GCC but the older one is not familiar with this pragma and issues a warning (which becomes an error).
What can I do?
Stop treating warning as errors
Surround my pragma with some sort of version checking macro
I don't like both solutions, is there anything else I can do?
Update following Sander De Dycker's answer
My build system does not allow me to use -isystem flag with gcc
Since you only want to suppress warnings from headers you don't control, you can mark those headers as system headers by using -isystem instead of -I, and gcc will no longer generate warnings for them (how gcc treats system headers).
The solution I'm going to use for now (until I'll see a better one) is to wrap the GCC diagnostic pragmas with macros to check GCC version, something like
#if (defined __GNUC__) && (__GNUC__ > 3)
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#include <bad_header.hpp>
#if (defined __GNUC__) && (__GNUC__ > 3)
#pragma GCC diagnostic error "-Wunused-parameter"
#endif

How to find out cl.exe's built-in macros

Does anyone know how could I find out which are cl.exe's builtin/predefined macros?
For example for gcc the following command line will list all the compiler's builtin macros
gcc -dM -E - </dev/null
EDIT: I'm interested in a way similar to gcc's that is "ask the actual compiler".
Thanks
This method does amount to asking the compiler for the list of predefined macros, but it uses undocumented features and provides only a partial list. I include it here for completeness.
The Microsoft C/C++ compiler allows an alternative compiler front-end to be invoked using the /B1 and /Bx command line switches for .c and .cpp files respectively. The command-line interface module CL.exe passes a list of options to the replacement compiler front-end via the MSC_CMD_FLAGS environment variable. This list of options includes -D macro definitions for some of the predefined macros.
The following trivial replacement compiler front-end prints out the list of options passed to it:
/* MyC1.c */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *p;
if ((p = getenv("MSC_CMD_FLAGS")) != NULL)
printf("MSC_CMD_FLAGS:\n%s\n", p);
if ((p = getenv("MSC_IDE_FLAGS")) != NULL)
printf("MSC_IDE_FLAGS:\n%s\n", p);
return EXIT_FAILURE;
}
Compile this to an executable named, for example, "MyC1.exe", ensure it is visible in the PATH and tell CL.exe to invoke it as the compiler front-end using one of the following:
cl /B1MyC1.exe AnyNameHere.c
cl /BxMyC1.exe AnyNameHere.cpp
Include other command-line options as required to see which macros are predefined for that set of options.
In the resulting output look for the -D options. An example list is given below. In the actual output the list will be space-separated, with each macro definition preceded by -D, and other options also present.
_MSC_EXTENSIONS
_INTEGRAL_MAX_BITS=64
_MSC_VER=1600
_MSC_FULL_VER=160030319
_MSC_BUILD=1
_WIN32
_M_IX86=600
_M_IX86_FP=0
_MT
This technique seems to include most macros that depend on command-line options, but excludes those that are always defined such as __FILE__ and __DATE__.
/P preprocessor flag will emit the currently active macros based on the project build settings. I am not sure if it is exactly the equivalent of gcc command you have shown. The output is in .I file.
Try the predef project. They maintain a database of predefined macros for many target platforms, host platforms and compiler toolchains.
They also have a script that attempts to discover all of the predefined names whether documented or not. It works by running the strings utility over the compiler, processing that to get plausible candidate tokens, and trying test compilations for each token. Not fast, but pretty good at discovering lots of macros.
I don't know in what version this was made available.
/PD print all macro definitions
Example use:
Create an empty file foo.cpp (e.g. echo // > foo.cpp)
cl /Zc:preprocessor /PD foo.cpp
Get information at the source!
http://msdn.microsoft.com/en-us/library/b0084kay%28v=VS.90%29.aspx
The available pre-defined C/C++ macros in MSVC, when using cl for compilation, depends (of course) on what you are compiling (C vs C++) and the variants for that, including architecture and other cl options. (Check your options with cl /help for additional info.)
Then the powershell (one-liner) commands are:
# For C++
echo // > foo.cpp; cl /nologo /Zc:preprocessor /PD /EHs /TP foo.cpp |sort; rm foo.cpp, foo.obj
# For C
echo // > foo.cpp; cl /nologo /Zc:preprocessor /PD /EHs /TC foo.cpp |sort; rm foo.cpp, foo.obj
For example, the output for C is:
#define __STDC_HOSTED__ 1
#define _INTEGRAL_MAX_BITS 64
#define _IS_ASSIGNABLE_NOCHECK_SUPPORTED 1
#define _M_AMD64 100
#define _M_X64 100
#define _MSC_BUILD 0
#define _MSC_EXTENSIONS 1
#define _MSC_FULL_VER 192930147
#define _MSC_VER 1929
#define _MSVC_EXECUTION_CHARACTER_SET 1252
#define _MSVC_TRADITIONAL 0
#define _MSVC_WARNING_LEVEL 1L
#define _MT 1
#define _WIN32 1
#define _WIN64 1
foo.cpp
LINK : fatal error LNK1561: entry point must be defined
If you wanna do the same trickery for using gcc in powershell, you need to use something like this:
echo `EOF` | gcc -E -dM -xc++ - |sort
As of Visual C++ 16.8.0, there is such an option. See https://developercommunity.visualstudio.com/t/provide-the-ability-to-list-predefined-macros-and/934925. Pass /EP /Zc:preprocessor /PD to the compiler along with an empty (or non-empty) source file. The option requires use of the "new" preprocessor.