Désactiver l'erreur d'avertissement unique

115

Existe-t-il un moyen de désactiver une seule ligne d'avertissement dans un fichier cpp avec Visual Studio?

Par exemple, si j'attrape une exception et que je ne la gère pas, j'obtiens l'erreur 4101 (variable locale non référencée). Existe-t-il un moyen d'ignorer cela uniquement dans cette fonction, mais sinon de le signaler dans l'unité de compilation? Pour le moment, je mets #pragma warning (disable : 4101)en haut du fichier, mais cela l'éteint évidemment pour l'ensemble de l'unité.

Biscuit
la source
19
si vous ne mentionnez que le type et ne nommez pas l'exception, il n'y aura pas d'avertissement. Par exemple catch (const std::exception& /* unnamed */) {.... }. Cela ne répond pas à votre question, mais pourrait résoudre votre problème.
Sjoerd

Réponses:

182
#pragma warning( push )
#pragma warning( disable : 4101)
// Your function
#pragma warning( pop ) 
Andreas Brinck
la source
1
@Cookie: oui, cela fonctionne pour n'importe quel morceau de code qui passe par le compilateur.
Matteo Italia
Pour une réponse plus récente et concise, voir la réponse de Daniel Seither, ci-dessous.
Dan Nissenbaum
4
clangne semble pas soutenir cette pragma, mais vous pouvez obtenir le même effet avec #pragma clang diagnostic push, #pragma clang diagnostic ignored "-Wunused-variable"et #pragma clang diagnostic pop. Voir "Contrôle des diagnostics via Pragmas" dans le manuel de l'utilisateur Clang
rampion
Étant donné que j'utilise rarement cette fonctionnalité, lorsque je le fais, je me retrouve généralement sur cette page pour me souvenir de la syntaxe. Je viens de le mettre autour d'un appel à une fonction obsolète qui peut ne jamais être mise à jour, afin que l'avertissement ne m'ennuie pas dans les listes de compilateurs, que je scanne religieusement.
David A. Gray
Pour Visual Studio, l'argument de ligne de commande est /wd4101. Notez qu'il n'y a pas la normale :entre l'indicateur et le nombre, et vous ne pouvez pas faire une liste de nombres séparés par des virgules. Pour les autres compilateurs, cela pourrait être à la /nowarn:4101place.
Jesse Chisholm
89

Si vous ne souhaitez supprimer un avertissement que sur une seule ligne de code, vous pouvez utiliser le suppress spécificateur d'avertissement :

#pragma warning(suppress: 4101)
// here goes your single line of code where the warning occurs

Pour une seule ligne de code, cela fonctionne de la même manière que l'écriture de ce qui suit:

#pragma warning(push)
#pragma warning(disable: 4101)
// here goes your code where the warning occurs
#pragma warning(pop)
Daniel Seither
la source
8
Très utile! Malheureusement, cela ne fonctionne pas pour une seule ligne qui comprend un en-tête qui génère l'avertissement.
Marko Popovic
2
@MarkoPopovic: Le suppressspécificateur fonctionne sur une seule ligne de code pré-traitée . Si la ligne qui suit#pragma warning(suppress: ...) est une #includedirective (qui étend le fichier référencé par son paramètre dans l'unité de compilation actuelle), l'effet s'applique uniquement à la première ligne de ce fichier. Cela devrait être évident, car les avertissements sont générés par le compilateur. Le compilateur fonctionne sur du code pré-traité.
IInspectable
@IInspectable Dans ce cas, je l'appellerais un ligne de code post-traitée . pré-traité signifie qu'il n'a pas encore été traduit par le préprocesseur.
void.pointer
2
@voi: La terminaison "-ed" signifie le participe passé . Il est utilisé pour exprimer que quelque chose s'est terminé dans le passé. Une ligne "prétraitée" est une ligne qui a été entièrement traitée.
IInspectable
29

#pragma push / pop sont souvent une solution à ce genre de problèmes, mais dans ce cas, pourquoi ne supprimez-vous pas simplement la variable non référencée?

try
{
    // ...
}
catch(const your_exception_type &) // type specified but no variable declared
{
    // ...
}
Matteo Italia
la source
6
Ce n'est pas une réponse à la question. Certes, cela pourrait résoudre le problème d'OP, mais n'aidera pas les futurs lecteurs avec une question similaire: "Comment désactiver un avertissement spécifique pour une partie spécifique de mon code?"
Sjoerd
1
@Sjoerd: trois personnes ont déjà répondu à la "question officielle" que d'autres personnes peuvent rechercher, j'ai donc essayé de lire entre les lignes et de résoudre son problème réel (en arrivant une minute après votre commentaire :P).
Matteo Italia
11
@Sjoerd en tant que futur lecteur, j'atteste que cette réponse m'a en fait aidé.
Mołot
2
@ Mołot: en tant qu'ancien écrivain, je suis heureux que cela ait aidé. =)
Matteo Italia
9

Utilisez #pragma warning ( push ), puis #pragma warning ( disable ), puis mettez votre code, puis utilisez #pragma warning ( pop )comme décrit ici :

#pragma warning( push )
#pragma warning( disable : WarningCode)
// code with warning
#pragma warning( pop ) 
dents acérées
la source
8

Exemple:

#pragma warning(suppress:0000)  // (suppress one error in the next line)

Ce pragma est valide pour C ++ à partir de Visual Studio 2005.
https://msdn.microsoft.com/en-us/library/2c8f766e(v=vs.80).aspx

Le pragma n'est PAS valide pour C # via Visual Studio 2005 via Visual Studio 2015.
Erreur: «Désactivation ou restauration attendue».
(Je suppose qu'ils n'ont jamais réussi à mettre en œuvre suppress...)
https://msdn.microsoft.com/en-us/library/441722ys(v=vs.140).aspx

C # a besoin d'un format différent. Cela ressemblerait à ceci (mais ne fonctionnerait pas):

#pragma warning suppress 0642  // (suppress one error in the next line)

Au lieu de suppress, vous devez disableet enable:

if (condition)
#pragma warning disable 0642
    ;  // Empty statement HERE provokes Warning: "Possible mistaken empty statement" (CS0642)
#pragma warning restore 0642
else

C'est tellement moche, je pense qu'il est plus intelligent de simplement le remodeler:

if (condition)
{
    // Do nothing (because blah blah blah).
}
else
A876
la source
5

Au lieu de le placer au-dessus du fichier (ou même d'un fichier d'en-tête), enveloppez simplement le code en question avec #pragma warning (push), #pragma warning (disable)et une correspondance #pragma warning (pop), comme indiqué ici .

Bien qu'il existe d'autres options, notamment #pramga warning (once).

Christian.K
la source
5

On peut également utiliser UNREFERENCED_PARAMETERdéfini dans WinNT.H. La définition est juste:

#define UNREFERENCED_PARAMETER(P)          (P)

Et utilisez-le comme:

void OnMessage(WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(wParam);
    UNREFERENCED_PARAMETER(lParam);
}

Pourquoi l'utiliseriez-vous, vous pourriez dire que vous pouvez simplement omettre le nom de la variable lui-même. Eh bien, il y a des cas (configuration de projet différente, versions Debug / Release) où la variable peut être utilisée. Dans une autre configuration, cette variable reste inutilisée (et donc l'avertissement).

Certaines analyses de code statique peuvent toujours donner un avertissement pour cette instruction non-absurde ( wParam;). Dans ce cas, vous pouvez utiliser DBG_UNREFERENCED_PARAMETERce qui est le même que UNREFERENCED_PARAMETERdans les versions de débogage et qui le fait P=Pdans la version de version.

#define DBG_UNREFERENCED_PARAMETER(P)      (P) = (P)
Ajay
la source
1
notez que depuis C ++ 11, nous avons l' [[maybe_unused]]attribut
metablaster
2

Si vous souhaitez désactiver l' unreferenced local variableécriture dans un en-tête

template<class T>
void ignore (const T & ) {}

et utilise

catch(const Except & excpt) {
    ignore(excpt); // No warning
    // ...  
} 
Alexey Malistov
la source
2
Un appel de fonction, juste pour supprimer l'avertissement? Pourquoi ne faites-vous pas cela à la place (void)unusedVar;:?
Nawaz
@Nawaz: Je pense que ce (void)unusedVar;?n'est pas conforme à la norme C ++.
Alexey Malistov
2
C'est une expression dont la valeur n'est rien. En C ++, vous pouvez même le faire static_cast<void>(unusedVar).
Nawaz
2
@Nawaz. Explication Herb Sutter: herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings
Alexey Malistov
2
§5.2.9 / 4 dit, Any expression can be explicitly converted to type “cv void.” The expression value is discardedselon lequel vous pouvez écrire static_cast<void>(unusedVar)et static_cast<const void>(unusedVar)et static_cast<volatile void>(unusedVar). Tous les formulaires sont valides. J'espère que cela clarifie votre doute.
Nawaz
2

Dans certaines situations, vous devez avoir un paramètre nommé mais vous ne l'utilisez pas directement.
Par exemple, je l'ai rencontré sur VS2010, lorsque 'e' est utilisé uniquement dans une decltypeinstruction, le compilateur se plaint mais vous devez avoir la variable nomméee .

Toutes les non- #pragmasuggestions ci-dessus se résument toutes à l'ajout d'une seule déclaration:

bool f(int e)
{ 
   // code not using e
   return true;
   e; // use without doing anything
}
Adi Shavit
la source
1
maintenant (dans le compilateur MS VS2015) cela provoque le code inaccessible C4702
Cee McSharpface
2

comme @rampion l'a mentionné, si vous êtes dans clang gcc, les avertissements sont par nom, pas par numéro, et vous devrez faire:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-variable"
// ..your code..
#pragma clang diagnostic pop

cette information vient d' ici

orion elenzil
la source