Guidelines for C/C++ FE diagnostics
All these, plus the following:
Types of diagnostics
Diagnostics messages should follow GNU standards for error messages. In particular, text starts in lower-case and does not end in a period
A single diagnostic is composed of one pedwarn/permerror/error/warning/inform/sorry call followed by one or more inform calls.
- Diagnostics should be as concise as possible but not conciser, preferably a single line. Nonetheless, there are several valid reasons for splitting a diagnostic in several lines:
- The diagnostic contains extra details that are only shown once (per file/function/execution).
The diagnostic refers to multiple locations. In particular, when mentioning a declaration, it is recommended to add an inform call pointing to the declaration.
Always use a note (inform) to give these additional details.
These additional inform calls should be conditional on the return value of pedwarn/permerror/warning. If they return false, then inform should not be called.
It does not make sense to have inform notes after fatal. They will never be printed.
pedwarn is for code that is accepted by GCC but it should be rejected or diagnosed according to the current standard, or it conflicts with the standard (either the default or the one selected by -std=). It can also diagnose compile-time undefined behavior (but not runtime UB). pedwarns become errors with -pedantic-errors.
Most pedwarns are controlled by -Wpedantic, a few are controlled by options that are enabled by -Wpedantic and others are enabled by default (when they are dubious enough). That is, although -Wpedantic is only used for pedwarns, the choice between using pedwarn or warning is independent of -Wpedantic and only depends on the current -std= value.
The flag pedantic (or OPT_Wpedantic) should not cause generated code differences or errors. Moreover, it should not be used to choose between pedwarn or warning. It should only be used in three situations:
To control whether to call pedwarn() in cases that the decision is expensive. Simple cases are like:
if (pedantic && something_expensive()) pedwarn(loc, OPT_Wpedantic, "whatever");
and there are more complex cases where the work is done far away from the point where we call pedwarn. In particular, it does not save much (and interferes with #pragma GCC diagnostics) to use:
and the following is a bug:if (pedantic) pedwarn(loc, OPT_Wpedantic, "whatever");
if (pedantic) pedwarn(loc, 0, "whatever"); // it should use OPT_Wpedantic
To control whether to use -Wpedantic or -Wsomething-else for a call to pedwarn controlled by two options:
pedwarn(loc, pedantic ? OPT_Wpedantic : OPT_Wsomething_else, "whatever");
To avoid giving another warning for something that is already warned by -Wpedantic.
The same rules apply to libcpp, which uses cpp_pedwarning (instead of pedwarn), CPP_PEDANTIC (pfile) (instead of pedantic) and CPP_W_PEDANTIC (instead of OPT_Wpedantic). In particular, you may use cpp_pedwarning without CPP_W_PEDANTIC, but you may not use CPP_W_PEDANTIC without cpp_pedwarning and you may not use CPP_PEDANTIC (pfile) without CPP_W_PEDANTIC. Note that currently (2016), libcpp is not clean with respect to these rules.
permerror() should only be used for code that has been historically accepted by GCC, but it is now considered an error to accept it. GCC will only accept it when using -fpermissive and without any guarantees that the code will work or keep working in the future. The use of permerror() should be very limited. In particular, never use permerror() for GCC extensions, unless they are officially deprecated.
Locations
Diagnostic calls should take an explicit location. In particular, the location should not be passed implicitly using the formatting specifier '+', such as in '%q+D', because it is handled too late and too deep in the diagnostics machinery to modify the location of the diagnostic. For example, it breaks #pragma GCC diagnostics.
When the diagnostic does not refer to a particular source code location, it should use an explicit UNKNOWN_LOCATION rather than no location at all (since the latter uses input_location implicitly and who knows what that is pointing at). It is always better to pass input_location explicitly rather than implicitly.
In cases where we want to emit diagnostics about a token that is located in a macro that is itself defined in system header, for example, for the NULL macro, using the original location of the token will suppress the diagnostic (unless -Wsystem-header). Instead, one should use:
source_location loc = expansion_point_location_if_in_system_header (original_location);
- If you want to not warn for macros expanded from non-system headers, you can use:
if (!(from_macro_expansion_at (expansion_point_location_if_in_system_header (EXPR_LOCATION (primop0))))))
Warning Options
The behavior in the presence of conflicting options such as -Wall -Wno-unused -Wunused-variables is described in the manual.
New warnings, even if enabled by default, should be controlled by an -W* option, preferably by an existing one, if it makes sense and to avoid too many options, or by a new one otherwise.
- There are three types of warning options:
Options such as -Wall and -Wextra should only enable other options and not control individual warnings. The rationale is that the warnings controlled by these options are too diverse and it makes sense to selectively disable particular subsets.
Options that enable many related warnings, but specific subsets can be disabled by other options. Examples are -Wtraditional, -Wpedantic, -Wformat and -Wconversion.
Options that do not enable other options. Example -Woverflow.
- As a rough guideline, a warning option should be:
enabled by default if it has (almost) no false positives (e.g., -Woverflow);
added to -Wall if it is generally useful with low number of false positives that are easy to work-around;
added to -Wextra if it has quite a lot of false positives but they are still easy to work-around;
Warning options should move up in this list when bugfixes reduce the number of false positives. These cases are not meant to be exhaustive: some options should never be enabled by other option if the warning is too specific (-Wdouble-promotion); other options are already controlled by options such as -Wpedantic and -Wformat and do not need to move up in this list (but they might if deemed useful).
Warning options should be described either in common.opt or c-family/c.opt. Relationships between warnings should be encoded using the appropriate properties in these files.
-pedantic is an obsolete alias for -Wpedantic
-pedantic-errors is not equivalent to -Werror=pedantic. The manual says: "This is not equivalent to -Werror=pedantic, since there are errors enabled by this option and not enabled by the latter and vice versa.". However, as of 2012, -pedantic-errors does imply -Werror=pedantic. Moreover, The description of -Wpedantic should also contain "in some cases where there is undefined behavior at compile-time" [ source ]. See also https://gcc.gnu.org/PR53075 and https://gcc.gnu.org/ml/gcc-patches/2014-10/msg01799.html