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?
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 */
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.
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:
__attribute__
_Pragma
#pragma
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).
__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 .
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.
#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.
#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.
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
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. .
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.
Je sais que la question concerne GCC, mais pour ceux qui cherchent comment le faire avec d’autres et/ou plusieurs compilateurs…
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.
#pragma warning (disable: …)
a des équivalents dans la plupart des compilateurs:
#pragma warning(disable:4996)
#pragma GCC diagnostic ignored "-W…"
où Ellipsis est le nom de l'avertissement; par exemple , #pragma GCC diagnostic ignored "-Wdeprecated-declarations
.#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).#pragma warning(disable:1478 1786)
.diag_suppress
pragma: #pragma diag_suppress 1215,1444
diag_suppress
avec la même syntaxe (mais des numéros d’avertissement différents!) En tant que PGI: pragma diag_suppress 1291,1718
error_messages
. Les avertissements sont différents pour les compilateurs C et C++. Ces deux désactivent essentiellement les mêmes avertissements: #pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
#pragma error_messages(off,symdeprecated,symdeprecated2)
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
#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
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:
#pragma GCC diagnostic Push
/#pragma GCC diagnostic pop
#pragma clang diagnostic Push
/#pragma diagnostic pop
#pragma warning(Push)
/#pragma warning(pop)
#pragma warning(Push)
/#pragma warning(pop)
#pragma Push
/#pragma pop
#pragma diag_Push
/#pragma diag_pop
#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.
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.
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.