web-dev-qa-db-fra.com

Comment désactiver les avertissements GCC pour quelques lignes de code

Dans Visual C++, il est possible d'utiliser #pragma warning (disable: ...) . Aussi, j'ai trouvé que dans GCC, vous pouvez remplacer par les drapeaux du compilateur de fichiers . Comment puis-je faire cela pour "next line", ou avec la sémantique Push/Pop autour des zones de code utilisant GCC?

192
Matt Joiner

Il semble que ceci peut être fait . Je ne suis pas en mesure de déterminer la version de GCC à laquelle elle a été ajoutée, mais c'était avant juin 2010.

Voici un exemple:

#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 */
199
Matt Joiner

Pour tout oublier, voici un exemple de désactivant temporairement un avertissement:

#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wunused-result"
    write(foo, bar, baz);
#pragma GCC diagnostic pop

Vous pouvez consulter le documentation de GCC sur les pragmas de diagnostic pour plus de détails.

94
Ian Pilcher

TL; DR : Si cela fonctionne, évitez ou utilisez des spécificateurs tels que __attribute__, sinon _Pragma.

Ceci est une version courte de mon article de blog Suppression des avertissements dans GCC et Clang .

Considérez ce qui suit Makefile

CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror

.PHONY: all
all: puts

pour construire le code source puts.c suivant

#include <stdio.h>

int main(int argc, const char *argv[])
{
    while (*++argv) puts(*argv);
    return 0;
}

Il ne compilera pas car argc n'est pas utilisé et les réglages sont hardcore (-W -Wall -pedantic -Werror).

Vous pouvez faire 5 choses:

  • Améliorer le code source, si possible
  • Utilisez un spécificateur de déclaration, comme __attribute__
  • Utilisez _Pragma
  • Utilisez #pragma
  • Utilisez une option de ligne de commande.

Améliorer la source

La première tentative devrait être de vérifier si le code source peut être amélioré pour se débarrasser de l'avertissement. Dans ce cas, nous ne souhaitons pas modifier l'algorithme à cause de cela, car argc est redondant avec !*argv (NULL après le dernier élément).

Utilisation d'un spécificateur de déclaration, tel que __attribute__

#include <stdio.h>

int main(__attribute__((unused)) int argc, const char *argv[])
{
    while (*++argv) puts(*argv);
    return 0;
}

Si vous êtes chanceux, la norme fournit un spécificateur pour votre situation, tel que _Noreturn.

__attribute__ est une extension propriétaire de GCC (prise en charge par Clang et d'autres compilateurs tels que armcc également) et ne sera pas comprise par de nombreux autres compilateurs. Mettez __attribute__((unused)) dans une macro si vous voulez du code portable.

_Pragma opérateur

_Pragma peut être utilisé comme alternative à #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") \

Le principal avantage de l'opérateur _Pragma est que vous pouvez l'insérer dans des macros, ce qui n'est pas possible avec la directive #pragma.

Inconvénient: il s’agit presque d’une arme nucléaire tactique, car elle fonctionne sur la base des lignes plutôt que sur celle des déclarations.

L'opérateur _Pragma a été introduit dans C99.

#pragma directive.

Nous pourrions changer le code source pour supprimer l'avertissement pour une région de code, généralement une fonction entière:

#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

Inconvénient: il s’agit presque d’une arme nucléaire tactique, car elle fonctionne sur la base des lignes plutôt que sur celle des déclarations.

Notez qu'une syntaxe similaire existe dans clang .

Suppression de l'avertissement sur la ligne de commande pour un seul fichier

Nous pourrions ajouter la ligne suivante à la variable Makefile pour supprimer l'avertissement spécifique aux options de vente:

CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror

.PHONY: all
all: puts

puts.o: CPPFLAGS+=-Wno-unused-parameter

Ce n'est probablement pas ce que vous voulez dans votre cas particulier, mais cela peut aider d'autres lecteurs qui se trouvent dans des situations similaires.

22
Christian Hujer
#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

Cela devrait faire l'affaire pour gcc, clang et msvc

Peut être appelé avec par exemple:

DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)

voir https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html , http://clang.llvm.org/docs/UsersManual.html#controlling-diagnostics- via-pragmas et https://msdn.Microsoft.com/de-DE/library/d9x1s805.aspx pour plus de détails

Vous devez avoir au moins la version 4.02 pour utiliser ce type de pragmas pour gcc, vous n'êtes pas sûr de msvc ni de clang à propos des versions.

Il semble que le traitement pragmatique Push pop pour gcc soit un peu cassé. Si vous activez à nouveau l'avertissement, vous obtenez toujours l'avertissement du bloc qui se trouvait à l'intérieur du bloc DISABLE_WARNING/ENABLE_WARNING. Cela fonctionne pour certaines versions de gcc, mais pas pour d'autres.

17
Martin Gerhardy
#pragma GCC diagnostic ignored "-Wformat"

Remplacez "-Wformat" par le nom de votre drapeau d'avertissement.

Autant que je sache, il n’ya aucun moyen d’utiliser la sémantique Push/pop pour cette option.

17
Joe D

J'ai eu le même problème avec les bibliothèques externes comme les en-têtes ROS. J'aime utiliser les options suivantes dans CMakeLists.txt pour une compilation plus stricte:

set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")

Cependant, cela provoque également toutes sortes d'erreurs pédantes dans les bibliothèques incluses à l'extérieur. La solution consiste à désactiver tous les avertissements pédants avant d'inclure des bibliothèques externes et de les réactiver comme ceci:

//save compiler switches
#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wpedantic"

//Bad headers with problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>

//restore compiler switches
#pragma GCC diagnostic pop
5
Shital Shah

Plutôt que de réduire les avertissements au silence, le style gcc consiste généralement à utiliser les constructions C standard ou l’extension __attribute__ pour informer le compilateur de votre intention. Par exemple, l'avertissement concernant l'affectation utilisée en tant que condition est supprimé en mettant l'affectation entre parenthèses, c'est-à-dire if ((p=malloc(cnt))) au lieu de if (p=malloc(cnt)). Les avertissements concernant les arguments de fonction inutilisés peuvent être supprimés par un étrange __attribute__ dont je ne me souviens jamais, ni par une auto-affectation, etc. .

3
R..

Pour ceux qui ont trouvé cette page cherchant un moyen de faire cela dans IAR, essayez ceci:

#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

Voir http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472m/chr1359124244797.html pour référence.

3
Keron

Je sais que la question concerne GCC, mais pour ceux qui cherchent comment le faire avec d’autres et/ou plusieurs compilateurs…

TL; DR

Vous voudrez peut-être jeter un oeil à Hedley , qui est un en-tête C/C++ à domaine public que j'ai écrit et qui fait un lot de ce matériel toi. Je mettrai une section rapide sur l'utilisation de Hedley pour tout cela à la fin de ce post.

Désactiver l'avertissement

#pragma warning (disable: …) a des équivalents dans la plupart des compilateurs:

  • MSVC: #pragma warning(disable:4996)
  • GCC: #pragma GCC diagnostic ignored "-W…" où Ellipsis est le nom de l'avertissement; par exemple , #pragma GCC diagnostic ignored "-Wdeprecated-declarations.
  • clang: #pragma clang diagnostic ignored "-W…". La syntaxe est fondamentalement la même que celle de GCC, et bon nombre des noms d'avertissement sont les mêmes (bien que beaucoup ne le soient pas).
  • Compilateur Intel C: Utilisez la syntaxe MSVC, mais gardez à l'esprit que les numéros d'avertissement sont totalement différents. Exemple: #pragma warning(disable:1478 1786).
  • PGI: Il y a un diag_suppress pragma: #pragma diag_suppress 1215,1444
  • TI: Il existe un pragma diag_suppress avec la même syntaxe (mais des numéros d’avertissement différents!) En tant que PGI: pragma diag_suppress 1291,1718
  • Oracle Developer Studio (suncc): il existe un pragma error_messages. Les avertissements sont différents pour les compilateurs C et C++. Ces deux désactivent essentiellement les mêmes avertissements:
    • C: #pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
    • C++: #pragma error_messages(off,symdeprecated,symdeprecated2)
  • IAR: utilise également diag_suppress comme PGI et TI, mais la syntaxe est différente. Certains des numéros d'avertissement sont les mêmes, mais d'autres ont divergé: #pragma diag_suppress=Pe1444,Pe1215
  • Pelles C: semblable à MSVC, encore que les chiffres soient différents #pragma warn(disable:2241)

Pour la plupart des compilateurs, il est souvent utile de vérifier la version du compilateur avant d'essayer de la désactiver, sinon vous finirez par déclencher un autre avertissement. Par exemple, GCC 7 a ajouté la prise en charge de l’avertissement -Wimplicit-fallthrough, donc si vous vous souciez de GCC avant 7, vous devriez faire quelque chose comme:

#if defined(__GNUC__) && (__GNUC__ >= 7)
#  pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif

Pour les compilateurs basés sur Clang, tels que les versions plus récentes de XL C/C++ et armclang, vous pouvez vérifier si le compilateur est informé d'un avertissement particulier à l'aide de la macro __has_warning().

#if __has_warning("-Wimplicit-fallthrough")
#  pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif

Bien sûr, vous devez également vérifier si la macro __has_warning() existe:

#if defined(__has_warning)
#  if __has_warning("-Wimplicit-fallthrough")
#    pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#  endif
#endif

Vous pourriez être tenté de faire quelque chose comme

#if !defined(__has_warning)
#  define __has_warning(warning)
#endif

Vous pouvez donc utiliser __has_warning un peu plus facilement. Clang suggère même quelque chose de similaire pour la macro __has_builtin() dans leur manuel. Ne faites pas cela . Un autre code peut rechercher __has_warning et retomber sur les versions du compilateur s’il n’existe pas. Si vous définissez __has_warning, vous casserez leur code. La bonne façon de faire est de créer une macro dans votre espace de noms. Par exemple:

#if defined(__has_warning)
#  define MY_HAS_WARNING(warning) __has_warning(warning)
#else
#  define MY_HAS_WARNING(warning) (0)
#endif

Ensuite, vous pouvez faire des choses comme

#if MY_HAS_WARNING(warning)
#  pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#Elif defined(__GNUC__) && (__GNUC__ >= 7)
#  pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif

Pousser et éclater

De nombreux compilateurs prennent également en charge un moyen de pousser et de placer des avertissements sur une pile. Par exemple, cela désactivera un avertissement sur GCC pour une ligne de code, puis le renverra à son état précédent:

#pragma GCC diagnostic Push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop

Bien sûr, il n’ya pas beaucoup d’accord entre les compilateurs sur la syntaxe:

  • GCC 4.6+: #pragma GCC diagnostic Push/#pragma GCC diagnostic pop
  • clang: #pragma clang diagnostic Push/#pragma diagnostic pop
  • Intel 13+ (et probablement plus tôt): #pragma warning(Push)/#pragma warning(pop)
  • MSVC 15+ (VS 9.0/2008): #pragma warning(Push)/#pragma warning(pop)
  • BRAS 5.6+: #pragma Push/#pragma pop
  • TI 8.1+: #pragma diag_Push/#pragma diag_pop
  • Pelles C 2.90+ (et probablement plus tôt): #pragma warning(Push)/#pragma warning(pop)

Si la mémoire est utile, pour certaines très anciennes versions de GCC (comme 3.x, IIRC), les pragmas Push/pop devaient être en dehors de la fonction.

Cacher les détails sanglants

Pour la plupart des compilateurs, il est possible de masquer la logique des macros à l'aide de _Pragma, introduit en C99. Même en mode non C99, la plupart des compilateurs prennent en charge _Pragma; La grande exception est MSVC, qui a son propre mot clé __pragma avec une syntaxe différente. La norme _Pragma prend une chaîne, la version de Microsoft ne:

#if defined(_MSC_VER)
#  define PRAGMA_FOO __pragma(foo)
#else
#  define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO

Est à peu près équivalent, une fois prétraité, à

#pragma foo

Cela nous permet de créer des macros pour pouvoir écrire du code comme

MY_DIAGNOSTIC_Push
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP

Et cacher toutes les vérifications de versions laides dans les définitions de macro.

Le moyen le plus simple: Hedley

Maintenant que vous comprenez comment faire de telles choses de manière portable tout en gardant votre code propre, vous comprenez ce que fait l'un de mes projets, Hedley . Au lieu de fouiller dans une tonne de documentation et/ou d'installer autant de versions de compilateurs que possible, vous pouvez simplement inclure Hedley (il s'agit d'un en-tête C/C++ du domaine public) et le faire. Par exemple:

#include "hedley.h"

HEDLEY_DIAGNOSTIC_Push
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP

Désactiver l'avertissement concernant l'appel d'une fonction obsolète sur GCC, Clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles et peut-être d'autres (je ne m'ennuierai probablement pas si je mets à jour Hedley). Et, sur les compilateurs qui ne fonctionnent pas, les macros seront prétraités sans rien, votre code continuera donc à fonctionner avec n’importe quel compilateur. Bien sûr, HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED n'est pas le seul avertissement dont Hedley a connaissance, ni la désactivation des avertissements que tout Hedley peut faire, mais nous espérons que vous comprendrez l'idée.

2
nemequ