Portability of #warning preprocessor directive - c++

I know that the #warning directive is not standard C/C++, but several compilers support it, including gcc/g++. But for those that don't support it, will they silently ignore it or will it result in a compile failure? In other words, can I safely use it in my project without breaking the build for compilers that don't support it?

It should be noted that MSVC uses the syntax:
#pragma message ( "your warning text here" )
The usual #warning syntax generates a fatal error
C1021: invalid preprocessor command 'warning'
so it is not portable to those compilers.

It is likely that if a compiler doesn't support #warning, then it will issue an error. Unlike #pragma, there is no recommendation that the preprocessor ignore directives it doesn't understand.
Having said that, I've used compilers on various different (reasonably common) platforms and they have all supported #warning.

You are likely to get at least an unrecognized directive warning from compilers that don't recognize #warning, even if the code block is not included in your compilation. That might or might not be treated as an error - the compiler could legitimately treat it as an error, but many would be more lax.
Are you aware of (can you name) a compiler other than GCC/G++ that provides #warning?
[Edited: Sun Solaris 10 (Sparc) and the Studio 11 C/C++ compilers both accept #warning.]

When switching from mingw to visual studio, I added such lines to my global config header. (include it in stdafx.h)
#ifdef __GNUC__
//from https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
//Instead of put such pragma in code:
//#pragma GCC diagnostic ignored "-Wformat"
//use:
//PRAGMA_GCC(diagnostic ignored "-Wformat")
#define DO_PRAGMA(x) _Pragma (#x)
#define PRAGMA_GCC(x) DO_PRAGMA(GCC #x)
#define PRAGMA_MESSAGE(x) DO_PRAGMA(message #x)
#define PRAGMA_WARNING(x) DO_PRAGMA(warning #x)
#endif //__GNUC__
#ifdef _MSC_VER
/*
#define PRAGMA_OPTIMIZE_OFF __pragma(optimize("", off))
// These two lines are equivalent
#pragma optimize("", off)
PRAGMA_OPTIMIZE_OFF
*/
#define PRAGMA_GCC(x)
// https://support2.microsoft.com/kb/155196?wa=wsignin1.0
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
#define __PRAGMA_LOC__ __FILE__ "("__STR1__(__LINE__)") "
#define PRAGMA_WARNING(x) __pragma(message(__PRAGMA_LOC__ ": warning: " #x))
#define PRAGMA_MESSAGE(x) __pragma(message(__PRAGMA_LOC__ ": message : " #x))
#endif
//#pragma message "message quoted"
//#pragma message message unquoted
//#warning warning unquoted
//#warning "warning quoted"
PRAGMA_MESSAGE(PRAGMA_MESSAGE unquoted)
PRAGMA_MESSAGE("PRAGMA_MESSAGE quoted")
#warning "#pragma warning quoted"
PRAGMA_WARNING(PRAGMA_WARNING unquoted)
PRAGMA_WARNING("PRAGMA_WARNING quoted")
Now I use PRAGMA_WARNING(this need to be fixed)
Sadly there is no #pragma warning in gcc, so it warns unspecified pragma.
I doubt that gcc will add #pragma warning" rather than microsoft adding #warning.

I had this problem once with a compiler for an Atmel processor. And it did generate preprocessor errors due to the unknown #warning token.
Unfortunately the solution seemed to be to convert the whole source tree to use the #pragma equivalent and accept that the build behavior was going to differ if using gcc.

Actually most compilers that I know about ignore unknown #pragma directives, and output a warning message - so in the worst case, you'll still get a warning.

Related

Make gcc to skip "-Werror=unused-parameter" for a specific .cpp file [duplicate]

In Visual C++, it's possible to use #pragma warning (disable: ...). Also I found that in GCC you can override per file compiler flags. How can I do this for "next line", or with push/pop semantics around areas of code using GCC?
It appears this can be done. I'm unable to determine the version of GCC that it was added, but it was sometime before June 2010.
Here's an example:
#pragma GCC diagnostic error "-Wuninitialized"
foo(a); /* error is given for this one */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
foo(b); /* no diagnostic for this one */
#pragma GCC diagnostic pop
foo(c); /* error is given for this one */
#pragma GCC diagnostic pop
foo(d); /* depends on command line options */
To net everything out, this is an example of temporarily disabling a warning:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(foo, bar, baz);
#pragma GCC diagnostic pop
You can check the GCC documentation on diagnostic pragmas for more details.
TL;DR: If it works, avoid, or use specifiers like _Noreturn, [[nodiscard]], __attribute__, otherwise _Pragma.
This is a short version of my blog article
Suppressing Warnings in GCC and Clang.
Consider the following Makefile,
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
for building the following puts.c source code:
#include <stdio.h>
int main(int argc, const char *argv[])
{
while (*++argv)
puts(*argv);
return 0;
}
It will not compile because argc is unused, and the settings are hardcore (-W -Wall -pedantic -Werror).
There are five things you could do:
Improve the source code, if possible
Use an attribute, like [[maybe_unused]]
Use a declaration specifier, like __attribute__
Use _Pragma
Use #pragma
Use a command line option.
Improving the source
The first attempt should be checking if the source code can be improved to get rid of the warning. In this case we don't want to change the algorithm just because of that, as argc is redundant with !*argv (NULL after last element).
Using an attribute, like [[maybe_unused]]
#include <stdio.h>
int main([[maybe_unused]] int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
If you're lucky, the standard provides an attribute for your situation, like [[maybe_unused]]. Attributes are a new feature of C2x. So far, C2x defines four attributes, [[deprecated]], [[fallthrough]], [[maybe_unused]], and [[nodiscard]].
Using a declaration specifier, like __attribute__
#include <stdio.h>
int main(__attribute__((unused)) int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
If you're lucky, the standard provides a specifier for your situation, like _Noreturn.
__attribute__ is proprietary GCC extension (supported by Clang and some other compilers like armcc as well) and will not be understood by many other compilers. Put __attribute__((unused)) inside a macro if you want portable code.
_Pragma operator
_Pragma can be used as an alternative to #pragma.
#include <stdio.h>
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
int main(int argc, const char *argv[])
{
while (*++argv)
puts(*argv);
return 0;
}
_Pragma("GCC diagnostic pop")
The main advantage of the _Pragma operator is that you could put it inside macros, which is not possible with the #pragma directive.
Downside: It's almost a tactical nuke, as it works line-based instead of declaration-based.
The _Pragma operator was introduced in C99.
#pragma directive.
We could change the source code to suppress the warning for a region of code, typically an entire function:
#include <stdio.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
int main(int argc, const char *argv[])
{
while (*++argc) puts(*argv);
return 0;
}
#pragma GCC diagnostic pop
Downside: It's almost a tactical nuke, as it works line-based instead of declaration-based.
Note that a similar syntax exists in Clang.
Suppressing the warning on the command line for a single file
We could add the following line to the Makefile to suppress the warning specifically for puts:
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
puts.o: CPPFLAGS+=-Wno-unused-parameter
This is probably not want you want in your particular case, but it may help other readers who are in similar situations.
I know the question is about GCC, but for people looking for how to do this in other and/or multiple compilers…
TL;DR
You might want to take a look at Hedley, which is a public-domain single C/C++ header I wrote which does a lot of this stuff for you. I'll put a quick section about how to use Hedley for all this at the end of this post.
Disabling the warning
#pragma warning (disable: …) has equivalents in most compilers:
MSVC: #pragma warning(disable:4996)
GCC: #pragma GCC diagnostic ignored "-W…" where the ellipsis is the name of the warning; e.g., #pragma GCC diagnostic ignored "-Wdeprecated-declarations.
Clang: #pragma clang diagnostic ignored "-W…". The syntax is basically the same as GCC's, and many of the warning names are the same (though many aren't).
Intel C++ Compiler (ICC): Use the MSVC syntax, but keep in mind that warning numbers are totally different. Example: #pragma warning(disable:1478 1786).
PGI/Nvidia: There is a diag_suppress pragma: #pragma diag_suppress 1215,1444. Note that all warning numbers increased by one in 20.7 (the first Nvidia HPC release).
TI (CCS): There is a diag_suppress pragma with the same syntax (but different warning numbers!) as PGI: pragma diag_suppress 1291,1718
Oracle Developer Studio (ODS) (suncc): there is an error_messages pragma. Annoyingly, the warnings are different for the C and C++ compilers. Both of these disable basically the same warnings:
C: #pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
C++: #pragma error_messages(off,symdeprecated,symdeprecated2)
IAR: also uses diag_suppress like PGI and TI, but the syntax is different. Some of the warning numbers are the same, but I others have diverged: #pragma diag_suppress=Pe1444,Pe1215
Pelles C: similar to MSVC, though again the numbers are different #pragma warn(disable:2241)
For most compilers it is often a good idea to check the compiler version before trying to disable it, otherwise you'll just end up triggering another warning. For example, GCC 7 added support for the -Wimplicit-fallthrough warning, so if you care about GCC before 7 you should do something like
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
For Clang and compilers based on Clang, such as newer versions of XL C/C++ and armclang, you can check to see if the compiler knows about a particular warning using the __has_warning() macro.
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Of course you also have to check to see if the __has_warning() macro exists:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
You may be tempted to do something like
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
So you can use __has_warning a bit more easily. Clang even suggests something similar for the __has_builtin() macro in their manual. Do not do this. Other code may check for __has_warning and fall back on checking compiler versions if it doesn't exist, and if you define __has_warning you'll break their code. The right way to do this is to create a macro in your namespace. For example:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
Then you can do stuff like
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Pushing and popping
Many compilers also support a way to push and pop warnings onto a stack. For example, this will disable a warning on GCC for one line of code, then return it to its previous state:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
Of course there isn't a lot of agreement across compilers about the syntax:
GCC 4.6+: #pragma GCC diagnostic push / #pragma GCC diagnostic pop
Clang: #pragma clang diagnostic push / #pragma clang diagnostic pop
Intel 13+ (and probably earlier): #pragma warning(push) / #pragma warning(pop)
MSVC 15+ (Visual Studio 9.0 / 2008): #pragma warning(push) / #pragma warning(pop)
ARM 5.6+: #pragma push / #pragma pop
TI 8.1+: #pragma diag_push / #pragma diag_pop
Pelles C 2.90+ (and probably earlier): #pragma warning(push) / #pragma warning(pop)
If memory serves, for some very old versions of GCC (like 3.x, IIRC) the push/pop pragmas had to be outside of the function.
Hiding the gory details
For most compilers it's possible to hide the logic behind macros using _Pragma, which was introduced in C99. Even in non-C99 mode, most compilers support _Pragma; the big exception is MSVC, which has its own __pragma keyword with a different syntax. The standard _Pragma takes a string, Microsoft's version doesn't:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
Is roughly equivalent, once preprocessed, to
#pragma foo
This let’s us create macros so we can write code like
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
And hide away all the ugly version checks in the macro definitions.
The easy way: Hedley
Now that you understand the mechanics of how to do stuff like this portably while keeping your code clean, you understand what one of my projects, Hedley does. Instead of digging through tons of documentation and/or installing as many versions of as many compilers as you can to test with, you can just include Hedley (it is a single public domain C/C++ header) and be done with it. For example:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Will disable the warning about calling a deprecated function on GCC, Clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles C, and possibly others (I probably won't bother updating this answer as I update Hedley). And, on compilers which aren't known to work, the macros will be preprocessed away to nothing, so your code will continue to work with any compiler. Of course HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED isn't the only warning Hedley knows about, nor is disabling warnings all Hedley can do, but hopefully you get the idea.
#pragma GCC diagnostic ignored "-Wformat"
Replace "-Wformat" with the name of your warning flag.
AFAIK there is no way to use push/pop semantics for this option.
Use:
#define DIAG_STR(s) #s
#define DIAG_JOINSTR(x,y) DIAG_STR(x ## y)
#ifdef _MSC_VER
#define DIAG_DO_PRAGMA(x) __pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(warning(x))
#else
#define DIAG_DO_PRAGMA(x) _Pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(compiler diagnostic x)
#endif
#if defined(__clang__)
# define DISABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,push) DIAG_PRAGMA(clang,ignored DIAG_JOINSTR(-W,clang_option))
# define ENABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,pop)
#elif defined(_MSC_VER)
# define DISABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,push) DIAG_DO_PRAGMA(warning(disable:##msvc_errorcode))
# define ENABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,pop)
#elif defined(__GNUC__)
#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,push) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,pop)
#else
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_option,msvc_unused) DIAG_PRAGMA(GCC,warning DIAG_JOINSTR(-W,gcc_option))
#endif
#endif
This should do the trick for GCC, Clang and MSVC.
It can be called with e.g.:
DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)
See 7 Pragmas, Controlling Diagnostics via Pragmas and Pragma directives and the __pragma and _Pragma keywords for more details.
You need at least version 4.02 to use these kind of pragmas for GCC, and I am not sure about MSVC and Clang about the versions.
It looks like the push pop pragma handling for GCC is a little bit broken. If you enable the warning again, you still get the warning for the block that was inside the DISABLE_WARNING/ENABLE_WARNING block. For some versions of GCC it works, and for some it doesn't.
I had same issue with external libraries like ROS headers. I like to use following options in CMakeLists.txt for stricter compilation:
set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")
However, doing this causes all kind of pedantic errors in externally included libraries as well. The solution is to disable all pedantic warnings before you include external libraries and re-enable them like this:
// Save compiler switches
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
// Bad headers with a problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
// Restore compiler switches
#pragma GCC diagnostic pop
Rather than silencing the warnings, GCC style is usually to use either standard C constructs or the __attribute__ extension to tell the compiler more about your intention.
For instance, the warning about assignment used as a condition is suppressed by putting the assignment in parentheses, i.e. if ((p=malloc(cnt))) instead of if (p=malloc(cnt)).
Warnings about unused function arguments can be suppressed by some odd __attribute__ I can never remember, or by self-assignment, etc.
But generally I prefer just globally disabling any warning option that generates warnings for things that will occur in correct code.
Here is a way to do this in IAR. Try this:
#pragma diag_suppress=Pe177
void foo1(void)
{
/* The following line of code would normally provoke diagnostic
message #177-D: variable "x" was declared but never referenced.
Instead, we have suppressed this warning throughout the entire
scope of foo1().
*/
int x;
}
#pragma diag_default=Pe177
See official documentation for reference.

cross platform macro for silencing unused variables warning

In porting a large piece of C++ code from Visual Studio (2008) to Xcode (4.4+), I encounter lines such as:
UNUSED_ALWAYS(someVar);
the UNUSED_ALWAYS(x) (through UNUSED(x)) macro expands to x which seems to silence Visual C++ just fine. It's not enough for Clang however.
With Clang, I usually use the #pragma unused x directive.
The UNUSED_ALWAYS and UNUSED macros are defined in an artificial windows.h header which I control that contains a number of utilities to help Xcode compile Windows stuff.
Is there a way to define UNUSED(x) to expand to #pragma unused x? I tried this, which Clang fails to accept:
#define UNUSED(x) #pragma unused(x)
I also tried:
#define UNUSED(x) (void)(x)
Which seems to work. Did I miss anything?
(void)x;
is fine; has always worked for me. You can't usually expand a macro to a #pragma, although there is usually a slightly different pragma syntax that can be generated from a macro (_Pragma on gcc and clang, __pragma on VisualC++).
Still, I don't actually need the (void)x anymore in C++, since you can simply not give a name to a function parameter to indicate that you don't use it:
int Example(int, int b, int)
{
... /* only uses b */
}
works perfectly fine.
Yup - you can use this approach for GCC and Clang:
#define MON_Internal_UnusedStringify(macro_arg_string_literal) #macro_arg_string_literal
#define MONUnusedParameter(macro_arg_parameter) _Pragma(MON_Internal_UnusedStringify(unused(macro_arg_parameter)))
although mine did have the (void) approach defined for clang, it appears that Clang now supports the stringify and _Pragma approach above. _Pragma is C99.
#define and #pragma both are preprocessor directives. You cannot define one macro to expand as preprocessor directive. Following would be incorrect:
#define MY_MACRO #if _WIN32
MY_MACRO cannot expand to #if _WIN32 for the compiler.
Your best bet is to define your own macro:
#define UNUSED(_var) _var

#warning and macro evaluation

I have the following code :
#define LIMIT_DATE \"01-03-2010\"
#ifdef LIMIT_DATE
#if _MSC_VER
#pragma message ("Warning : this release will expire on " LIMIT_DATE)
#elif __GNUC__
#warning ("Warning : this release will expire on " LIMIT_DATE)
#endif
#endif
The problem is that LIMIT_DATE is not evaluated when printing the warning.
I searched on Google, but didn't found yet the solution.
Thanks for help.
From gcc preprocessor documentation
Neither #error nor #warning
macro-expands its argument. Internal
whitespace sequences are each replaced
with a single space. The line must
consist of complete tokens. It is
wisest to make the argument of these
directives be a single string
constant; this avoids problems with
apostrophes and the like.
So it's not possible at least in gcc.
According to MSDN this should work for MSVC althrough I don't have access to Visual Studio currently to test this

#warning in Visual Studio

In gcc I can do compile-time warnings like this:
#if !defined(_SOME_FEATURE_)
#warning _SOME_FEATURE_ not defined-- be careful!
#endif
But in Visual Studio this doesn't work. Is there an alternative syntax for #warning?
About the closest equivalent would be #pragma message, or possibly #error (the latter stops compilation, the former just prints out the specified error message).
Use #pragma message("Some message")
There is a good article here on how to achieve a similar effect to #warning in visual studio:
http://goodliffe.blogspot.co.uk/2009/07/c-how-to-say-warning-to-visual-studio-c.html
Edit: Here is the relevant section from the above link, however I do recommend reading the article.
#define STRINGIZE_HELPER(x) #x
#define STRINGIZE(x) STRINGIZE_HELPER(x)
#define WARNING(desc) message(__FILE__ "(" STRINGIZE(__LINE__) ") : Warning: " #desc)
// usage:
#pragma WARNING(FIXME: Code removed because...)
#pragma WEIRD_VALUES_HERE
is the way I've always seen it done. M$ probably has the pragmas on their site somewhere.
Another thought is template style compile time asserts. Boost has a whole selection of these if you are wanting to check compile time code errors.

How can I disable #pragma warnings?

While developing a C++ application, I had to use a third-party library which produced a huge amount of warnings related with a harmless #pragma directive being used.
../File.hpp:1: warning: ignoring #pragma ident
In file included from ../File2.hpp:47,
from ../File3.hpp:57,
from File4.h:49,
Is it possible to disable this kind of warnings, when using the GNU C++ compiler?
I believe you can compile with
-Wno-unknown-pragmas
to suppress these.
In GCC, compile with -Wno-unknown-pragmas
In MS Visual Studio 2005 (this question isn't tagged with gcc, so I'm adding this for reference), you can disable globally in Project Settings->C/C++->Advanced. Enter 4068 in "Disable Specific Warnings"
or you can add this to any file to disable warnings locally
#pragma warning (disable : 4068 ) /* disable unknown pragma warnings */
Perhaps see GCC Diagnostic Pragmas? Alternatively in this case you could use the combination of options that -Wall enables, excluding -Wunknown-pragmas.
I know the question is about GCC, but for people wanting to do this as portably as possible:
Most compilers which can emit this warning have a way to disable the warning from either the command line (exception: PGI) or in code (exception: DMC):
GCC: -Wno-unknown-pragmas / #pragma GCC diagnostic ignored "-Wunknown-pragmas"
Clang: -Wno-unknown-pragmas / #pragma clang diagnostic ignored "-Wunknown-pragmas"
Intel C/C++ Compiler: -diag-disable 161 / #pragma warning(disable:161)
PGI: #pragma diag_suppress 1675
MSVC: -wd4068 / #pragma warning(disable:4068)
TI: --diag_suppress,-pds=163 / #pragma diag_suppress 163
IAR C/C++ Compiler: --diag_suppress Pe161 / #pragma diag_suppress=Pe161
Digital Mars C/C++ Compiler: -w17
Cray: -h nomessage=1234
You can combine most of this into a single macro to use in your code, which is what I did for the HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS macro in Hedley
#if HEDLEY_HAS_WARNING("-Wunknown-pragmas")
# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
#elif HEDLEY_INTEL_VERSION_CHECK(16,0,0)
# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
#elif HEDLEY_PGI_VERSION_CHECK(17,10,0)
# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
#elif HEDLEY_GNUC_VERSION_CHECK(4,3,0)
# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
#elif HEDLEY_MSVC_VERSION_CHECK(15,0,0)
# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
#elif HEDLEY_TI_VERSION_CHECK(8,0,0)
# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
#elif HEDLEY_IAR_VERSION_CHECK(8,0,0)
# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
#else
# define HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
#endif
Note that Hedley may have more complete information than this answer since I'll probably forget to update this answer, so if you don't want to just use Hedley (it's a single public domain C/C++ header you can easily drop into you project) you might want to use Hedley as a guide instead of the information above.
The version checks are probably overly pessimistic, but sometimes it's hard to get good info about obsolete versions of proprietary compilers, and I'd rather be safe than sorry. Again, Hedley's information may be better.
Many compilers can also push/pop warnings onto a stack, so you can push, then disable them before including code you don't control, then pop so your code will still trigger the warning in question (so you can clean it up). There are macros for that in Hedley, too: HEDLEY_DIAGNOSTIC_PUSH / HEDLEY_DIAGNOSTIC_POP.
In my case, I work with Qt under MinGW. I need to set the flag another way, in my .PRO file:
QMAKE_CXXFLAGS_WARN_ON += -Wno-unknown-pragmas