How to check compiler at compile time? - visual-c++

If I'm going to disable warnings specific to compiler say VC++ and run this:
#pragma warning( disable : xxxx )
on comeau or g++, how do i make sure the preprocessor won't be executed it?

To detect the MSVC compiler you can see if _MSC_VER is defined so you could do something like
#ifdef _MSC_VER
#pragma warning( disable : xxxx )
#endif
Predefined Macros gives information about predefined VS macros

See this resource for a list of macros to identify which compiler is being used. Use them as follows (for MS VC):
#ifdef _MSC_VER
#pragma warning( disable : xxxx )
#endif

Related

Improper code for _byteswap_uint64() with clang-cl

If I use the _byteswap_uint64() intrinsic of MSVC with the mostly MSVC compatible compiler clang-cl the code generates a call to the external library function _byteswap_uint64() which does the well known mask and shift orgy. Whith MSVC I simply get a x86 BSWAP instruction which is there since the 486 so there shouldn't be any processor optimization level relevant here. clang-cl understands a lot of command line options MSVC doesn't understand, even -march=native. So if I have -march=native the code is still a call to the mentioned function.
I use clang-cl 13 through the IDE (installed from the Visual Studio installer).
Is there a way to get proper code like with MSVC ?
I've got it. Simply use the clang specific intrinsics with conditional compilation:
#include <cstdint>
#include <intrin.h>
uint64_t swapThis( uint64_t value )
{
#if defined(__llvm__)
return __builtin_bswap64( value );
#elif defined(_MSC_VER)
return _byteswap_uint64( value );
#endif
}
clang_ isn't defined with clang-cl under Windows but only with clang++ under Windows, so I had to use _llvm.

How to suppress warnings in external headers in Visual C++

I'm starting a new BREW project, and I'd like to compile with Warning Level 4 (/W4) to keep the application code nice and clean. The problem is that the BREW headers themselves don't compile cleanly with /W4.
In gcc you can differentiate between application and system headers by using -I and -isystem, and then by default gcc doesn't report any compilation warnings in system headers. Is there an equivalent mechanism in Visual C++?
Use this method around (a) header(s) that you cannot or don't want to change, but which you need to include.
You can selectively, and temporarily disable all warnings like this:
#pragma warning(push, 0)
// Some include(s) with unfixable warnings
#pragma warning(pop)
Instead of 0 you can optionally pass in the warning number to disable, so something like:
#pragma warning(push)
#pragma warning(disable : 4081)
#pragma warning(disable : 4706)
// Some code
#pragma warning(pop)
Visual C++ team has just added support for warning levels in external headers. You can find the details in their blog post: Broken Warnings Theory.
In essence it does automatically what the suggestions here were recommending to do manually: pushes new warning level right before #include directive and pops it up right after. There are additional flags to specify locations of external headers, flag to treat all <> includes as external, #pragma system_header and a feature not available in Clang or GCC (as of this writing) to see warnings in external headers across template instantiation stack when the template was instantiated in the user code.
Besides the comments under that post, you can also find some useful discussion in a reddit announcement for that post.
I don't believe Visual C++ lets you differentiate. You can fake it by using #pragma warning around the include:
#pragma warning(push, 0)
#include "mywarningheader.h"
#pragma warning(pop)
It seems like there is an answer to this.
this post talks about /external:I that can be used to include headers with a special set of warnings.
I have not tested it myself, but the blog post is from 2017.
The /external:anglebrackets /external:W0 compiler flags disable warnings on the headers imported with #include <...>.
You can change the W0 to W1, W2, W3, or W4, to set a different warning level for those.

Compiler #defines for g++ and cl

I am writing a program that is cross platform. There are a few spots where I have to specify an operating system dependent call.
#ifdef WINDOWS
..do windows only stuff
#endif
#ifdef LINUX
..do linux only stuff
#endif
Are there any preprocesser directives that get defined by the compiler so I don't have to explicitly define them when I use the command line compiler. ie.
cl -DWINDOWS program.cpp
or
g++ -DLINUX program.cpp
I realize I could easily write a makefile or have a shell/batch script that will do this automatically. But I would prefer to use the same ones as the compiler (if they exist) by default.
I found a complete list for all g++'s on this website.
#define __HAVE_BUILTIN_SETJMP__ 1
#define __unix__ 1
#define unix 1
#define __i386__ 1
#define __SIZE_TYPE__ unsigned int
#define __ELF__ 1
#define __GNUC_PATCHLEVEL__ 3
#define __linux 1
#define __unix 1
#define __linux__ 1
#define __USER_LABEL_PREFIX__
#define linux 1
#define __STDC_HOSTED__ 1
#define __EXCEPTIONS 1
#define __GXX_WEAK__ 1
#define __WCHAR_TYPE__ long int
#define __gnu_linux__ 1
#define __WINT_TYPE__ unsigned int
#define __GNUC__ 3
#define __cplusplus 1
#define __DEPRECATED 1
#define __GNUG__ 3
#define __GXX_ABI_VERSION 102
#define i386 1
#define __GNUC_MINOR__ 2
#define __STDC__ 1
#define __PTRDIFF_TYPE__ int
#define __tune_i386__ 1
#define __REGISTER_PREFIX__
#define __NO_INLINE__ 1
#define _GNU_SOURCE 1
#define __i386 1
#define __VERSION__ "3.2.3 20030502 (Red Hat Linux 3.2.3-47.3)"
And Visual C++ already has Win32 defined to use for any Widnows version.
Yes, there are such pre-defined symbols but I don't recommend you use them unless you never, ever, forsee supporting more platforms, compilers or operating system versions. Here's the logic.
First, you're better off with your own minimal set of defined compilation constants for use within your code. Because you might start with things like this:
#if defined(_WIN32)
// do windows stuff
#endif
#if defined(_linux)
// linux stuff
#endif
Suppose you allow compilation under a new compiler for windows that doesn't define _WIN32 automatically? You can change every _WIN32 line to something like:
#if defined(_WIN32) || defined(ming)
Which is a real pain in the butt if you have more than one of those to change. You could put something like this at a high level:
#if defined(ming)
#define _WIN32
#endif
But you'll likely discover that some system or library header file freaks out because they happen to use _WIN32. Better you had abstracted it in a common header file:
#if defined(_WIN32) || defined(ming)
#define PLAT_WINDOWS
#endif
And then simply use #if defined(PLAT_WINDOWS) where needed.
But what about that common header file? Well, when a new compiler/OS/whatever comes along you have to start tweaking it to make sure it says the right things. Pretty soon it is a comical hairball of condition that can only be understood if you know about every version of every compiler on every operating system on the planet. And gee, who doesn't but nevertheless any changes made have to be tested everywhere and that is painful.
So, better you just have some high level setting inside the makefile or even outside it that says "if you're on windows, -DPLAT_WINDOWS" and be done with it.
Of course, all this is minimized if you use the most commonly available functions and features in your code.
All of these answers were very good. The solution that worked for me was the following.
#ifdef _WIN32
#endif
#ifdef linux
#endif
WIN32 was not defined by cl but _WIN32 was.
linux was defined by g++.
Yes. I believe WIN32 is, but I'm not on a windows right now to test it :D
See:
http://en.wikipedia.org/wiki/C_preprocessor (it mentions WIN32)
Instead of having two macros for specific platforms, you may have the code in #ifndef #else block. For example:
#ifndef _WIN32
// linux specific code
#else
// windows specific code
#endif
With this solution, the ifndef-else block will make sure that you don't accidentally add code in between the two #ifdef blocks (which supposedly be handling the program execution flow in same manner).
The above code will also give you independence of compiling this code not just for linux but any unix platform, provided it supports the call, without changing the macro label from linux to unix or something else.

suppress gcc warnings : "warning: this is the location of the previous definition"

I need a set of wrappers around the standard system calls-open,listen,etc.
For these i have a few "#define" as in:
#define open(a,b,c) JCL_Open(a,b,c)
But when i compile the header and associated .c files, i am getting the following warning:
/jcl_wrappers.h:114:1: warning: "open" redefined
/jcl_wrappers.h:113:1: warning: this is the location of the previous definition
How can i suppress these warnings?
Put include guards in your header file.
Basically you need to put these two lines at the beginning of your header file
#ifndef _yourincludefilename_h_
#define _yourincludefilename_h_
and
#endif /* _yourincludefilename_h_ */
at the end of you include file.
Edit:
rascher is right, that open is not a good name for a macro, as it will conflict with a library function. Usually it is good C convention to make macros all uppercase, so I would suggest to change your macro to
#define OPEN(a,b,c) JCL_Open(a,b,c)
or even better
#define XYZ_OPEN(a,b,c) JCL_Open(a,b,c)
where XYZ is a prefix specific to your code.
Leave the standard functions alone and rename the function:
#define myopen(a,b,c) JCL_Open(a,b,c)
Someone will thank you later.
You might try using compile guards. Like:
my_headers.h:
#ifndef __MY_HEADERS
#define __MY_HEADERS
#define open(a,b,c) JCL_Open(a,b,c)
#endif
This will only do do what is between the #ifndef and #endif if the '__MY_HEADERS' macro has been defined. So, everything in your .h file will only be declared once.
You could use the same construct to see if the "open" macro is already defined.
Also be aware that there is already a C function called open(): http://www.manpagez.com/man/2/open/ . May not be a great idea to use the same name for your macro!
Wrap the define in:
#ifndef JCL_WRAPPERS_H
#define JCL_WRAPPERS_H
... your macro's
#endif
This makes sure your macro's are only defined once if you including your header in multiple places.
It's generally a smart thing to do for all prototypes in headers also.

fopen deprecated warning

With the Visual Studio 2005 C++ compiler, I get the following warning when my code uses the fopen() and such calls:
1>foo.cpp(5) : warning C4996: 'fopen' was declared deprecated
1> c:\program files\microsoft visual studio 8\vc\include\stdio.h(234) : see declaration of 'fopen'
1> Message: 'This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_DEPRECATE. See online help for details.'
How do I prevent this?
It looks like Microsoft has deprecated lots of calls which use buffers to improve code security. However, the solutions they're providing aren't portable. Anyway, if you aren't interested in using the secure version of their calls (like fopen_s), you need to place a definition of _CRT_SECURE_NO_DEPRECATE before your included header files. For example:
#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
The preprocessor directive can also be added to your project settings to effect it on all the files under the project. To do this add _CRT_SECURE_NO_DEPRECATE to Project Properties -> Configuration Properties -> C/C++ -> Preprocessor -> Preprocessor Definitions.
Well you could add a:
#pragma warning (disable : 4996)
before you use fopen, but have you considered using fopen_s as the warning suggests? It returns an error code allowing you to check the result of the function call.
The problem with just disabling deprecated function warnings is that Microsoft may remove the function in question in a later version of the CRT, breaking your code (as stated below in the comments, this won't happen in this instance with fopen because it's part of the C & C++ ISO standards).
This is just Microsoft being cheeky. "Deprecated" implies a language feature that may not be provided in future versions of the standard language / standard libraries, as decreed by the standards committee. It does not, or should not mean, "we, unilaterally, don't think you should use it", no matter how well-founded that advice is.
If you code is intended for a different OS (like Mac OS X, Linux) you may use following:
#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE
#endif
I'am using VisualStdio 2008.
In this case I often set Preprocessor Definitions
Menu \ Project \ [ProjectName] Properties... Alt+F7
If click this menu or press Alt + F7 in project window, you can see "Property Pages" window.
Then see menu on left of window.
Configuration Properties \ C/C++ \ Preprocessor
Then add _CRT_SECURE_NO_WARNINGS to \ Preprocessor Definitions.
Consider using a portability library like glib or the apache portable runtime. These usually provide safe, portable alternatives to calls like these. It's a good thing too, because these insecure calls are deprecated in most modern environments.
If you want it to be used on many platforms, you could as commented use defines like:
#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
|| defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
errno_t err = fopen_s(&stream,name, "w");
#endif
#if defined(unix) || defined(__unix) || defined(__unix__) \
|| defined(linux) || defined(__linux) || defined(__linux__) \
|| defined(sun) || defined(__sun) \
|| defined(BSD) || defined(__OpenBSD__) || defined(__NetBSD__) \
|| defined(__FreeBSD__) || defined __DragonFly__ \
|| defined(sgi) || defined(__sgi) \
|| defined(__MACOSX__) || defined(__APPLE__) \
|| defined(__CYGWIN__)
stream = fopen(name, "w");
#endif
For those who are using Visual Studio 2017 version, it seems like the preprocessor definition required to run unsafe operations has changed. Use instead:
#define _CRT_SECURE_NO_WARNINGS
It will compile then.
Many of Microsoft's secure functions, including fopen_s(), are part of C11, so they should be portable now. You should realize that the secure functions differ in exception behaviors and sometimes in return values. Additionally you need to be aware that while these functions are standardized, it's an optional part of the standard (Annex K) that at least glibc (default on Linux) and FreeBSD's libc don't implement.
However, I fought this problem for a few years. I posted a larger set of conversion macros here., For your immediate problem, put the following code in an include file, and include it in your source code:
#pragma once
#if !defined(FCN_S_MACROS_H)
#define FCN_S_MACROS_H
#include <cstdio>
#include <string> // Need this for _stricmp
using namespace std;
// _MSC_VER = 1400 is MSVC 2005. _MSC_VER = 1600 (MSVC 2010) was the current
// value when I wrote (some of) these macros.
#if (defined(_MSC_VER) && (_MSC_VER >= 1400) )
inline extern
FILE* fcnSMacro_fopen_s(char *fname, char *mode)
{ FILE *fptr;
fopen_s(&fptr, fname, mode);
return fptr;
}
#define fopen(fname, mode) fcnSMacro_fopen_s((fname), (mode))
#else
#define fopen_s(fp, fmt, mode) *(fp)=fopen( (fmt), (mode))
#endif //_MSC_VER
#endif // FCN_S_MACROS_H
Of course this approach does not implement the expected exception behavior.
I also got the same problem. When I try to add the opencv library
#include <opencv\cv.h>
I got not a warning but an error.
error C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. c:\program files (x86)\opencv\build\include\opencv2\flann\logger.h
I also used the preprocessor directives as mentioned. But that didn't solve the problem.
I solved it by doing as follows:
Go to Properties -> C/C++ -> Precompiled Headers -> Choose Not Using Precompiled Headers in Precompiled Header.

Resources