开发者

-Werror causes compiler to stop on #warning. What can I do to prevent this?

First off, I want it to stop on warnings. But I also want to print out some informative messages (like "Come back and implement this!").

Unfortunately, my compiler doesn't support #info, #message, #pragma message(), etc.

I know there's -Wno-error=<something>开发者_JAVA技巧;, but my google-foo is weak, and I can't seem to find out the <something> for #warning. I've tried -Wno-error=warning, and that just says "there's no -Wwarning". Same with "warn".

Any suggestions?

For what its worth, I'm using the Tensilica Xtensa compiler, xt-xcc, which appears to be a GNU derivative, or at least uses the GNU front end. It's version 8.0.0.


I am not familiar with the Tensilica Xtensa compiler (xt-xcc), but with standard GCC you can use

  #pragma GCC diagnostic warning "-Wcpp"

to make #warning a matter of simple warning (not an error because of -Werror). To make the effect temporary, you can embrace this #pragma and the #warning between #pragma GCC diagnostic push and #pragma GCC diagnostic pop.

When I compile a file containing the following

    #pragma GCC diagnostic push
    #pragma GCC diagnostic warning "-Wcpp"
    #warning one
    #pragma GCC diagnostic pop

    #warning two

with -Werror using GCC 4.6.1 (command gcc -c -Werror warning-test.c), I get the following output:

```lang-none
warning-test.c:3:2: warning: #warning one [-Wcpp]
warning-test.c:6:2: error: #warning two [-Werror=cpp]
cc1: all warnings being treated as errors
```

When I remove the second #warning, the compilation is not interrupted by an error.

You can also replace your -Werror compiler options with -Werror -Wno-error=cpp. I am not aware what other effects the cpp category of warnings include (and you might have a legitimate #warning in some other place that you want to catch as error), so temporarily disabling the error for a specific #warning and restoring the settings immediately after seems more accurate method of meeting your requirements.

Using GCC versions 4.8.4 and 4.9.2 gives pretty much the same behavior (only the source line is printed out additionally). But using GCC version 5.0.1 (prerelease version included in Ubuntu 15.04 (Vivid Vervet)) will give two warnings unless option -Werror=cpp is included as well. So it seems that -Werror with a newer GCC does not anymore imply -Werror=cpp like before and it needs to be provided separately if desired.


What's wrong with:

#warning "Come back and implement this"
#warning "Do not do that!"
#warning "Must fix this before release"

Normally, the compiler will include the argument(s) to - or material after - #warning in the error or warning message.

And, normally, if the compiler detects something that warrants a warning, it reports it fairly clearly.


Given the requirements, I think the only way to deal with this is to protect the #warning directives...

#ifdef DO_WARNINGS
#warning "Some warning"
#endif /* DO_WARNINGS */

Most of the time, you compile without -DDO_WARNINGS; when you need to check on the #warning warnings (with -Werror), then you include -DDO_WARNINGS after all, accepting that the compilation will fail. Remember that make -k will do as much as possible even in the presence of individual compilation errors.


Section 5.52.9 of the GCC 4.4.1 manual says (in part):

5.52.9 Diagnostic Pragmas

GCC allows the user to selectively enable or disable certain types of diagnostics, and change the kind of the diagnostic. For example, a project’s policy might require that all sources compile with ‘-Werror’ but certain files might have exceptions allowing specific types of warnings. Or, a project might selectively enable diagnostics and treat them as errors depending on which preprocessor macros are defined.

#pragma GCC diagnostic kind option

Modifies the disposition of a diagnostic. Note that not all diagnostics are modifiable; at the moment only warnings (normally controlled by ‘-W...’) can be controlled, and not all of them. Use ‘-fdiagnostics-show-option’ to determine which diagnostics are controllable and which option controls them. kind is ‘error’ to treat this diagnostic as an error, ‘warning’ to treat it like a warning (even if ‘-Werror’ is in effect), or ‘ignored’ if the diagnostic is to be ignored. option is a double quoted string which matches the command line option.

#pragma GCC diagnostic warning "-Wformat"
#pragma GCC diagnostic error "-Wformat"
#pragma GCC diagnostic ignored "-Wformat"

Note that these pragmas override any command line options. Also, while it is syntactically valid to put these pragmas anywhere in your sources, the only supported location for them is before any data or functions are defined. Doing otherwise may result in unpredictable results depending on how the optimizer manages your sources. If the same option is listed multiple times, the last one specified is the one that is in effect. This pragma is not intended to be a general purpose replacement for command line options, but for implementing strict control over project policies.

GCC also offers a simple mechanism for printing messages during compilation.

#pragma message string

Prints string as a compiler message on compilation. The message is informational only, and is neither a compilation warning nor an error.

#pragma message "Compiling " __FILE__ "..."

string may be parenthesized, and is printed with location information.

I'm not sure whether you feel like editing your #warning lines into #pragma message lines. It would get you around the problem - and is only worse than adding conditional compilation around the #warning in that #pragma message might be supported by fewer compilers. It depends on what your portability requirements are.


Given that #warning is presumably processed by the pre-processor, you could run the pre-processor separately without -Werror, then run the compiler with pre-processing inhibited on the pro-processor output.

To do this run the .c file through the preprocessor with all the normal options except -Werror, and generate the output as a .i file (.ii for C++). The compiler recognises these files as not to be pre-processed so you can compile them with -Werror, and assuming that the pre-processor drops the #warning and it is not processed by the compiler itself, this may resolve your problem.

I have not tested this; when I encountered the same problem I just chose to live with it and not use -Werror. The solution seemed more complex than the problem!


Unfortunately, there is no answer for my specific toolchain, or so says the engineers at Tensilica. They don't support #message, or #pragma message(), or know of how to suppress #warning as error in the presence of -Werror.

The GCC toolchain allows the use of -Wno-error=[code] to say "this warning is not an error", but I haven't found a list that corresponds #warning to any code this would take (or even a list of codes this could be).

I may try to find the time to delve into the standard GCC command lines and pre-processor source code to try to find a list of what -Wno-error= can be equal to, or whether or not there's a -Werror= code that corresponds to #warning.


Ten years later, the proper way to issue warnings and avoid these additional messages/errors from -Wpedantic is to use #pragma message. GCC supports this syntax since at least GCC 4.5, and Clang since at least Clang 6.

Modern versions of these compilers even support #pragma GCC error "message" and #pragma GCC warning "message" (GCC 9, already supported in Clang 6).


If your compiler supports it, you can try using the constructor function attribute to define a function that runs at program start (before main) that prints out a message to stdout:

#define TOKENPASTE(x, y) TOKENPASTE2(x, y)
#define TOKENPASTE2(x, y) x ## y
#define WARNING(message) \
  static void TOKENPASTE(_print_warning, __LINE__)() __attribute__((constructor)); \
  static void TOKENPASTE(_print_warning, __LINE__)() \
  { \
    puts(message); \
  }

WARNING("fix this before ship")  // prints out a message at runtime before main

This causes a message to be printed out at runtime instead of compile-time, which is almost as good, especially if you have no other options. The only restriction is that you have to use this at global scope outside of a function definition.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜