I.0 The Principle
An implementation shall diagnose an error it can already prove.
A deterministic language should use the knowledge it already possesses. Where a program construct is invalid and the invalidity is evident at translation time, silence is not a conforming response. See clause 4.3 and behavior.md section 108.
This annex separates what an implementation shall diagnose from what it should diagnose. The first list is a conformance requirement. The second is the difference between an implementation that meets the specification and one that is good.
I.1 Categories
Error. Translation stops. The program is not translated into an executable form. Every constraint violation is an error.
Warning. Translation continues and the meaning of the program is unchanged. Under the strict profile of clause 4.6.3, every warning in clause I.3 becomes an error.
Note. Additional information attached to an error or a warning, such as the location of a conflicting declaration. Notes are recommended and are never required.
Quality requirements.
A diagnostic shall name the source location of the construct. A diagnostic for a redeclaration, a conflict, or a shadowing shall also name the location of the other declaration. A diagnostic for a removed construct shall name the replacement spelling, and should offer the rewrite as an applicable fix.
I.2 Required Diagnostics
Each of these is an error unless it is marked as a warning.
I.2.1 Constraint violations
Every constraint violation stated anywhere in clause 5, clause 6, or clause 7. This is the largest group and it is not repeated here.
I.2.2 Removed constructs
autoorregisterused as a declaration specifier, or as an identifier. Clause 6.4.1.1.- A function declaration with empty parentheses. Clause 6.7.5.3.
- An old-style function definition. Clause 6.7.5.3.
- An array-syntax function parameter. Clause 6.7.5.2.
staticor a qualifier inside parameter array brackets. Clause 6.7.5.2.- A variable-length array declarator. Clause 6.7.5.2.
- A multi-character character constant. Clause 6.4.4.4.
- Bare
inlineorextern inline. Clause 6.7.4. - An
externdeclaration with an initializer. Clause 6.2.2.3. - A second definition of the same object or function in one translation unit. Clause 6.9.2.
- A digraph or a trigraph sequence used as punctuation. Clause 5.2.1.1.
- A
#defineor#undefofbool,true,false,null, orNULL. Clause 6.10.3.3. - An integer constant used where a pointer is required, including
int *p = 0andp == 0. The diagnostic shall namenullas the replacement. Clause 6.4.4.6. - An attempt to convert a null constant to an integer type, including
int n = NULL. Clause 6.3.2.3. - Tokens following
onceon a#pragma onceline. Clause 6.10.2.4.
I.2.3 Canonicalization
- A noncanonical primitive type spelling, including
_Boolwhereboolis canonical. Clause 6.7.2.1. - Declaration specifiers in a noncanonical order. Clause 6.7.8.
I.2.4 Provable arithmetic errors
Where the operands are constants or are otherwise statically known on a reachable path:
- division or remainder by zero. Clause 6.5.5.
- a signed division whose result is not representable. Clause 6.5.5.
- a shift count outside the valid range. Clause 6.5.7.
- an integer constant too large for any candidate type. Clause 6.4.4.1.
- a floating constant outside the range of its type. Clause 6.4.4.2.
- a floating-to-integer conversion whose result is not representable. Clause 6.3.1.4.
I.2.5 Provable memory errors
- An array subscript outside the array's extent, where both the index and the extent are known. Clause 6.5.2.1.
- A dereference of a pointer known to be null. Clause 6.5.3.2.
- A
returnof a pointer to an automatic object of the returning function. Clause 6.8.6.4. - A modification of an object known to be defined with a
const-qualified type. Clause 6.7.3.1. - A modification of a string literal. Clause 6.4.5.
I.2.6 Control flow
- A path that reaches the closing brace of a non-
voidfunction without areturn, where the path is provable. Clause 6.8.6.4. - A
gotothat jumps into the scope of an automatic object in a way that bypasses its initialization. Clause 6.8.6.1. - A
breakorcontinueoutside any loop orswitch. Clause 6.8.6. - Duplicate
casevalues, or more than onedefault, in oneswitch. Clause 6.8.1.
I.2.7 Types and declarations
- An incompatible redeclaration, in the same scope or across scopes. Clause 6.9.5.
- An incompatible function call, where the incompatibility is statically known. Clause 6.5.2.2.
- An argument count that does not match the prototype. Clause 6.5.2.2.
- An initializer that cannot convert to the declared type. Clause 6.7.9.
- A duplicated designator in one initializer list. Clause 6.7.9.4.
- A use of an undeclared identifier. Clause 6.5.1.
- A self-referential initializer that reads the object being declared. Clause 6.2.1.2.
I.2.8 Library
- A format string mismatch, where the format is a string literal at the call site. Clause 7.2.17.
- An
assertwhose argument is an assignment expression. Clause 7.2.1.
I.2.9 Mixed signedness in arithmetic
Warning. An arithmetic operation in which a signed operand is converted to an unsigned type by the usual arithmetic conversions, where the signed operand is not known to be nonnegative. Clause 6.3.1.6.
This is required because it is the most common source of silent arithmetic surprise remaining in the edition. Comparison was fixed by clause 6.3.1.7. Arithmetic was left compatible with C, and this warning is the price of that compatibility.
I.2.10 Fallthrough
Warning. A fallthrough from a nonempty case group into another labeled group. Clause 6.8.4.2.
The implementation shall provide a documented way to suppress it for an intentional fallthrough.
I.2.11 Limits
- A program that exceeds a fixed limit the implementation imposes. Annex B clause B.0.
I.2.12 Namespaces
- An exported identifier inside a namespace, or a namespace name, containing two consecutive underscores. Clause 6.4.2.0.
- A qualified identifier whose namespace is not visible at the point of use. Clause 6.5.1.1.
- A qualified identifier naming an entity the designated namespace does not declare. Clause 6.5.1.1.
- A namespace definition inside a block, a structure, a union, or a parameter list. Clause 6.7.10.
- A definition of a namespace member by a qualified declarator outside its namespace. Clause 6.7.10.
maindeclared inside a namespace. Clause 6.9.6.7.- Two entities in the program whose linkage names are equal, where the implementation can detect it. Clause 6.9.6.7.
- A
#namespacedirective that is not the first thing in its source file, or a second one in the same file. Clause 6.10.10. - A
#namespacedirective in a source file that also contains a namespace definition. Clause 6.10.10. - A malformed namespace qualification in a
#namespacedirective. Clause 6.10.10. - A
#namespacedirective in a file reached by#include. Clause 6.10.10. - A
#importor#namespacedirective inside a namespace definition. Clause 6.10.10 and clause 6.10.11. - An import cycle. The diagnostic shall name the files in the cycle. Clause 6.10.11.
- An imported header defining a macro the importing file has already defined differently. Clause 6.10.11.
- A header named by
#importthat cannot be found, under the search rules of clause 6.10.2. - A namespace named
main, or named by an identifier reserved under clause 6.4.2.1. Clause 6.9.6.7. - A
:immediately followed by::, where a space was intended. Clause 6.4.6.
I.2.13 Reproducibility
- A
SOURCE_DATE_EPOCHvalue that is present but not a decimal count of seconds. Annex K clause K.5.1. - Detection by the implementation that it has produced a nonreproducible artifact. Annex K clause K.11.4.
- Exhaustion of an optimization budget, where the implementation's documented response is to fail rather than to skip the transformation. The diagnostic shall name the budget and the construct. Annex K clause K.9.2.
- Exhaustion of a host resource during translation. Annex K clause K.2.1.
I.3 Recommended Diagnostics
These are warnings. An implementation should produce them by default, and shall document which ones it produces. The strict profile promotes them to errors.
I.3.1 Expressions
- An expression that modifies an object more than once, or that both modifies and independently reads an object, within one full expression. Clause 6.5.0.1.
- An expression statement with no effect.
- An expression whose meaning depends on maximal munch in a way a reader is likely to misread. Clause 6.4.0.
- A cast with no effect. Clause 6.5.4.
- A cast that discards a qualifier. Clause 6.7.3.1.
- A comparison between values of two different enumerated types. Clause 6.7.2.3.
- A compound assignment whose narrowing store loses information. Clause 6.5.16.2.
- A suspicious narrowing conversion.
- An ignored return value from a function whose result carries an error report. An explicit
(void)cast suppresses it. Clause 6.3.2.2.
I.3.2 Declarations
- A shadowing declaration likely to be accidental. Clause 6.2.1.1.
- An unused object with block scope.
- An unused function with internal linkage.
- An unused parameter.
- An unused
staticobject at file scope. - A declaration of a reserved identifier. Clause 6.4.2.1.
- A multi-digit octal constant whose digits are all valid decimal digits. Clause 6.4.4.1.
I.3.3 Control flow
- Unreachable code.
- An
elsewhose indentation disagrees with its association. Clause 6.8.4.1. - A null statement immediately following the header of an
if,while, orfor. Clause 6.8.3. - A label that is never the target of a jump. Clause 6.8.1.
- A
switchover an enumerated type that omits a named enumerator and has nodefault. Clause 6.7.2.3.
I.3.4 Style and idiom
- An object-like macro whose replacement list is a single constant, where a
static constobject would serve. Clause 6.10.0.1. - A function-like macro whose parameter appears more than once in its replacement list. Clause 6.10.3.
- A call to
atoi,atol,atof, oratoll. Clause 7.2.18. - A call to
strtokrather thanstrtok_r. Clause 7.2.19. - A call to
tmpnamorsystem. Clause 7.2.26. - An unrecognized
#pragma. Clause 6.10.6. - Use of a construct deprecated by clause 6.11.1.
- A namespace member hiding a name from an enclosing namespace, where the hiding is likely to be accidental. Clause 6.5.1.3.
- A header both imported and included in one translation unit. Clause 6.10.11.
- An
#includedirective lexically inside a namespace definition, which places the included text into the namespace. Clause 6.7.10. - A
#pragma onceappearing after a declaration in the file it protects. Clause 6.10.2.4. - A header reached by
#includewith no protection against repeated inclusion. Clause 6.9.3. - Use of
__DATE__or__TIME__where the declared translation timestamp was defaulted rather than set. Annex K clause K.5.2.
I.4 What an Implementation Shall Not Diagnose
- A layout or indentation choice. House style is not a language rule. Clause 0.7.
- A mismatch between a typedef name and its underlying type, since there is no mismatch. Clause 6.7.7.
- An ignored return value that has been explicitly cast to
void. Clause 6.3.2.2. - A construct this specification defines, on the grounds that ISO C99 left it undefined. The whole point of defining it was to make it usable.
I.5 Recommended Practice
A diagnostic should tell the programmer three things: what is wrong, where it is, and what to write instead. The third is the one most implementations omit, and it is the one that makes migration fast.
For a removed construct, the diagnostic should carry an applicable fix, so that a whole codebase can be migrated by applying fixes rather than by hand editing. Nearly every removal in this edition has a mechanical rewrite, and clause H.1.2 lists them.