How to disable GCC warnings for a few lines of code

后端 未结 9 917
我寻月下人不归
我寻月下人不归 2020-11-22 08:32

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\",

9条回答
  •  不知归路
    2020-11-22 09:16

    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: Use the MSVC syntax, but keep in mind that warning numbers are totally different. Example: #pragma warning(disable:1478 1786).
    • PGI: There is a diag_suppress pragma: #pragma diag_suppress 1215,1444
    • TI: There is a diag_suppress pragma with the same syntax (but different warning numbers!) as PGI: pragma diag_suppress 1291,1718
    • Oracle Developer Studio (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 diagnostic pop
    • Intel 13+ (and probably earlier): #pragma warning(push) / #pragma warning(pop)
    • MSVC 15+ (VS 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 lets 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, 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.

提交回复
热议问题