4.1 Conforming Implementation
A conforming implementation shall:
- accept every strictly conforming program,
- produce the behavior this specification defines for every construct in such a program, within the limits of clause 5.2.4 and Annex B,
- produce a diagnostic message for every constraint violation,
- produce a diagnostic message for every required diagnostic listed in
annex-i-diagnostics.mdclause I.2, - implement every defined trap listed in
annex-d-defined-traps-and-unsafe-operations.mdclause D.2, - document every implementation-defined behavior listed in
annex-c-implementation-defined-behavior.md, - document the target ABI it selected,
- document its trap mechanism,
- document how a diagnostic message is recognized,
- produce reproducible artifacts as required by clause 4.10 and
annex-k-deterministic-translation.md, - provide the verification tooling required by Annex K clause K.11.
A conforming implementation may be hosted or freestanding. See clause 4.4 and clause 4.5.
A conforming implementation may have extensions, subject to clause 4.8.
4.2 Conforming Program
A strictly conforming program shall:
- use only the language features and library facilities this specification defines,
- not produce output that depends on implementation-defined behavior,
- not produce output that depends on unspecified behavior,
- not exceed any minimum implementation limit in Annex B.
A conforming program is one that is acceptable to a conforming implementation. A conforming program may rely on implementation-defined behavior and on documented extensions.
The distinction is the same one ISO C99 draws, and it carries the same practical weight: most useful systems programs are conforming rather than strictly conforming, because they depend on the size of a pointer or on the layout of a structure. That is expected. Ocean Edition I aims to shrink the set of things a program must avoid, not to shame the programs that use them.
4.3 Diagnostics
A conforming implementation shall produce at least one diagnostic message for a translation unit that contains a violation of any syntax rule or constraint, even when the behavior is also specified elsewhere as defined.
An implementation shall not translate a program containing a constraint violation into an executable form.
Beyond constraint violations, this edition places a positive obligation on implementations: an implementation shall diagnose an error it can already prove. Where a program construct is invalid and the invalidity is evident at translation time, silence is not a conforming response.
Examples of errors that shall be diagnosed at translation time when the operands are constants or otherwise statically known:
int a[4];
a[7] = 1; /* index provably outside the array */
int b = 1 / 0; /* provable division by zero */
int c = 1 << 64; /* provable invalid shift count on a 32-bit int */
const int d = 5;
*(int *)&d = 6; /* provable write to a const object */
See behavior.md section 108 and annex-i-diagnostics.md.
4.3.1 Warnings
An implementation should diagnose constructs that are valid but suspicious. Recommended warnings are listed in annex-i-diagnostics.md clause I.3.
A warning shall not change the meaning of a valid program. Under the strict profile of clause 4.6, a warning may be promoted to an error, which stops translation rather than changing behavior.
4.4 Hosted Implementation
A hosted implementation shall accept any strictly conforming program, shall provide the complete standard library described in clause 7, and shall support program startup and termination as described in clause 5.1.2.
The entry function of a hosted program is main, declared in one of these two forms:
int main(void)
int main(int argc, char **argv)
An implementation may support additional environment-specific entry signatures, and shall document them. See behavior.md section 3.
4.5 Freestanding Implementation
A freestanding implementation shall accept any strictly conforming program that confines its library use to the freestanding header set of clause 7.1.5, and shall document the name and signature of the entry point it uses, which need not be main.
The core language does not change in a freestanding environment. Pointers, arithmetic, objects, arrays, structures, unions, control flow, and default initialization behave exactly as they do in a hosted environment. See behavior.md section 110.
4.6 Edition Selection and Profiles
4.6.1 Edition selection
An implementation that supports more than one C edition shall provide a documented, explicit way to select Ocean Edition I, and shall not select it by default for source that was presented as ISO C.
The edition in effect for a translation unit is fixed for that translation unit. A translation unit is not partly one edition and partly another.
Design note. The separation of front ends is described in syntax.md section 58. Legacy semantics belong to the C99 front end, and Ocean Edition I semantics belong to the Ocean Edition I front end. Sharing a lexer and a back end is expected. Sharing a semantic model is not.
4.6.2 Linking across editions
A translation unit translated as Ocean Edition I may be linked with a translation unit translated as ISO C, provided that every entity declared in both agrees in type and in linkage under the rules of clause 6.9.5.
Linking does not import the semantics of the other edition. An Ocean Edition I function called from ISO C evaluates its own body under Ocean Edition I rules, and an ISO C function called from Ocean Edition I evaluates its body under ISO C rules. The boundary is the call.
4.6.3 The strict profile
An implementation should offer a strict profile in which every recommended diagnostic of clause I.3 becomes an error.
The strict profile shall not enable any additional runtime check that changes a defined result, and shall not disable any defined trap. It changes which programs translate, not what translated programs mean.
4.6.4 The checked profile
An implementation may offer a checked profile in which unsafe memory operations are detected at execution time and converted into defined traps.
The checked profile is permitted to cost performance and to change the storage layout of objects that are not visible across a linkage boundary. It shall not change the result of any operation this specification defines. See clause 4.9 and behavior.md section 107.
4.7 The Optimization Constraint
This clause is normative and is the specification-level statement of Law 7.
An implementation shall not treat an execution as impossible in order to obtain a fact about a program.
Specifically, an implementation shall not:
- assume that signed arithmetic does not overflow,
- assume that a shift count is in range,
- assume that a divisor is nonzero,
- assume that two pointers to different types designate different storage,
- assume that a loop terminates,
- assume that a pointer used in an access was valid,
- infer that a condition holds because the program would be invalid if it did not.
The last item is the general form, and the others are instances of it. An implementation obtains optimization facts from proof, from a source contract under clause 4.7.3, from range analysis, from profile data, or from guarantees of the selected target. It does not obtain them from semantic disappearance. See syntax.md section 31 and behavior.md section 105.
Optimization decisions shall additionally be deterministic. An implementation shall not let iteration order over an unordered container, a wall-clock budget, or a measurement of the host machine change the code it emits. See Annex K clause K.9.
4.7.1 What optimization remains permitted
An implementation may perform any transformation that preserves the observable behavior of the program, where observable behavior is:
- the sequence of accesses to
volatile-qualified objects, in the order the program specifies, - the data written to files or other output devices at program termination,
- the interactive behavior described in clause 5.1.2.3,
- whether a defined trap occurs, and which one occurs first.
Under this rule the elimination of a provably unobservable default initialization is permitted, and is expected. See clause 6.7.9.2 and syntax.md section 29.
4.7.2 Trap elision
An implementation may remove the machinery of a defined trap where it can prove the trap cannot occur.
An implementation shall not remove the machinery of a defined trap on the grounds that a program that would trap is not worth compiling correctly.
4.7.3 Source contracts
A source contract is a property that the program asserts by writing a declaration whose purpose is to assert it. An implementation may rely on a source contract without proving it.
The distinction between a source contract and a prohibited inference is the direction of the reasoning:
permitted the program states P, therefore P
prohibited not-P would make the program invalid, therefore P
Both produce a fact the implementation did not prove. They differ in where the fact came from. A source contract is written in the program, at a place the programmer chose, and it is visible to anyone reading the declaration. A prohibited inference is derived from a rule elsewhere in this specification, applies to code that never mentioned it, and is invisible at the point where it changes the meaning of the program.
The complete list of source contracts.
Ocean Edition I has exactly two, and this list shall not be extended by an implementation.
restrict on a pointer. The program asserts that storage reachable through the restricted pointer is not independently modified through another access path during the relevant execution. See clause 6.7.3.3.
const on an object definition. The program asserts that the object is not modified after initialization. An implementation may rely on the object's value being stable, and may place it in read-only storage. See clause 6.7.3.1.
const on a pointed-to type is not a source contract, because it constrains an access path rather than an object, and clause 6.7.3.1 states that the underlying object may be modified through a different path.
Violating a contract.
A program that violates a source contract has unsafe memory behavior. The implementation was entitled to rely on the assertion, and the program made a false one.
An implementation shall diagnose a violation it can prove, under clause 4.3, and should diagnose a violation it can detect at execution time under the checked profile of clause 4.6.4.
Design note. This clause exists because clause 4.7 and clause 6.7.3.3 would otherwise contradict each other. If violating a restrict contract is unsafe memory behavior, and an implementation may derive no fact from unsafe memory behavior not occurring, then restrict would grant nothing and the keyword would be decorative.
The resolution is that the fact does not come from the absence of the unsafe behavior. It comes from the programmer having written the contract down. That is the whole difference between this edition and the model it replaces: an optimization right is something a program grants explicitly, in a place a reader can find, rather than something an optimizer extracts from a rule about what invalid programs are not allowed to do. See syntax.md section 36.
4.8 Extensions
An implementation may provide extensions, subject to all of the following:
- an extension shall not change the behavior of any construct this specification defines,
- an extension shall not cause a strictly conforming program to be rejected,
- an extension shall be documented,
- an extension shall be identifiable in source, either through a reserved identifier of clause 7.1.4, a
#pragma, or an attribute-like spelling the implementation documents, - an implementation shall provide a mode in which every extension not required for the target is disabled,
- an extension shall not introduce a dependency on anything Annex K clause K.3.2 excludes from the input closure.
Recommended extension subjects are listed in 06.11-future-language-directions.md clause 6.11.5, including thread storage duration and complex arithmetic.
4.8.1 Extensions that are not permitted
An implementation shall not offer, under any option, a mode that:
- reintroduces implicit array-to-pointer conversion for arbitrary array expressions,
- reintroduces implicit function-to-pointer conversion,
- makes signed overflow undefined,
- makes evaluation order unspecified,
- leaves an object uninitialized where clause 6.7.9.2 requires a value,
- produces artifacts that do not satisfy clause 4.10,
while still claiming Ocean Edition I conformance. Such a mode is a different language, and an implementation offering it shall name it as such.
4.9 Program Correctness and Runtime Checking
Ocean Edition I does not impose mandatory runtime memory safety. Pointers remain unsafe, manual storage remains unsafe, and casts remain powerful. See behavior.md Law 8.
An implementation may provide diagnostic, sanitizer, or checked execution modes, and is encouraged to. Doing so shall not require the programmer to change ordinary C syntax.
4.10 Reproducible Translation
Translating the same inputs with the same implementation shall produce byte-for-byte identical artifacts.
An artifact is any file the implementation produces, including object files, archives, shared libraries, executable images, and debug information. The inputs that determine an artifact are the translation input closure, defined exhaustively in Annex K clause K.3.
The requirement holds across time, across hosts, across degrees of parallelism, and across incremental and clean builds. It is not a mode, it is not a flag, and a program cannot opt out of it.
The requirement is one-sided. It constrains what an implementation emits, never whether it succeeds in emitting anything. An implementation may refuse to translate for any documented reason, including exhaustion of an internal budget or of a host resource, because a failed translation produces no artifact. What it shall not do is succeed twice on the same inputs and produce two different results.
An implementation shall not respond to resource pressure by emitting a cheaper artifact. Where it cannot complete the work, it reports a diagnostic. See Annex K clause K.2.1.
The requirement governs results, not effort. An implementation should use the host it runs on as effectively as it can, including every processor and as much memory as it can obtain, and should prefer completing a translation to failing one. What adapts to the host is how the work is done. What is determined by the input is what comes out. See Annex K clause K.2.3.
An implementation shall additionally:
- provide a documented way to record the translation input closure of any artifact, sufficient to repeat the translation,
- provide a documented mode that verifies reproducibility by translating twice under varied conditions and comparing,
- provide a documented way to report a digest of any artifact,
- report a diagnostic where it detects that it has produced a nonreproducible artifact.
The complete specification is in annex-k-deterministic-translation.md.
Design note. Every other rule in this specification exists so that a programmer can predict what their program will do. Reproducible translation extends that to predicting what their build will produce. The two are the same commitment applied at two moments, and an implementation that honors the first while abandoning the second has honored half of it.
The requirement also makes measurement possible. Where an implementation may decide differently between two builds, a benchmark reports the effect of the programmer's change mixed with the effect of the compiler having chosen differently, and the two cannot be separated. Rebuilding without editing anything can move a result. Under this clause, identical inputs produce identical bytes, identical bytes perform identically, and a measured difference is therefore attributable to something the programmer actually changed. Annex K clause K.0.1 develops the argument, and clause K.14 distinguishes it from the stability property that no compiler can promise.
The one-sidedness is what keeps the requirement compatible with building large programs on small machines. An implementation is free to bound any analysis, and clause K.9.2 requires only that the bound be counted in units the implementation controls and that exhausting it have a consequence determined by the input. A budget measured in seconds appears to buy reliability and does not: both builds succeed, and the two programs differ.
The requirement also makes a claim checkable that would otherwise rest on trust. A programmer who has the source, the implementation, and the recorded input closure can rebuild an artifact and compare it against the one they were given. Without this annex, that comparison is impossible and the artifact has to be taken on faith.
4.11 Version Identification
A conforming implementation shall predefine the macros of clause 6.10.8.1, which include an edition identifier and an edition version number. A program may use them to detect the edition at translation time.