Compiler modes and strictness

PXX has one dialect, not several semantic modes. What changes is how strict that dialect is about a handful of FPC-parity rules. This page explains the model as a whole; the individual switches are listed on the command line page and, for the in-source forms, on the directives page.

The model: lax → strict → mimic

--strict-overload-width — parity on request

Also not in the umbrella, and for a sharper version of the same reason: --strict-overload changes which programs are accepted, but --strict-overload-width changes which body a call binds to. Enrolling it would change what the corpora --strict-fpc is proven against actually resolve to, so that is a separate measured decision and it has not been made.

FPC picks the narrowest integer overload that fits. The default dialect keeps an exact-width match and otherwise lands on the widest candidate. Given F(Int64) and F(LongInt) declared in that order:

argument default --strict-overload-width
Integer, LongInt, a literal, an alias of Integer LongInt LongInt
SmallInt, Byte Int64 LongInt
Cardinal Int64 Int64

The Cardinal row is the one that carries the rule. It shows the choice is narrowest-that-fits, not narrowest-declared: LongInt is the same width as Cardinal but cannot hold its top half, so Int64 is the narrowest that fits and the flag changes nothing there. The unsigned set behaves the same way — with U(QWord), U(LongWord), U(Word), a Byte argument picks QWord by default and Word under the flag.

The default is intended, not a bug. The widening is the dialect; the flag is FPC parity on request. It is command-line only — there is no {$STRICT_OVERLOAD_WIDTH} directive.

Runtime checks are a separate axis

Everything above decides whether a program is accepted — it is dialect strictness. The runtime check switches are a different question: whether the compiler emits a test that fires while the program runs. They are not part of --strict or --mimic-fpc and are not affected by them.

Switch Emits Default
{$R+} / {$RANGECHECKS ON} range checks off
{$Q+} / {$OVERFLOWCHECKS ON} integer overflow checks off
{$I+} / {$IOCHECKS ON} IO-result checks on (and --mimic-fpc keeps it on)
{$NILCHECKS ON|OFF} / --no-nil-check nil-pointer checks tri-state: calls checked, derefs not
--no-div-check (opt-out) div/mod zero check on

{$NILCHECKS} is the one that does not have a single default — see directives.

Why lax is the default

PXX is its own dialect first and an FPC-compatibility tool second. The lax default serves the dialect; the strict flags and --mimic-fpc serve compatibility when you want it. That split is deliberate: you opt into FPC-parity strictness per rule, rather than opting out of it.

{$MODE} — which dialects PXX targets

PXX targets the FPC and Delphi family. Those modes are accepted as compatibility markers and map onto PXX's one dialect; strictness is controlled by the switches above, not by the mode marker. Dialects outside that family are not silently compiled as if they were in it.

{$MODE …} Result Why
objfpc fpc tp delphi delphiunicode pxx accepted the family PXX targets
iso extendedpascal warning not implemented; compiled as the default dialect
macpas error not implemented, and compiling it as the default dialect produces a wrong binary rather than a diagnostic
anything else error not a mode FPC accepts either

{$mode macpas} is an error rather than a warning because the failure is specific and silent: MacPas conditional directives ({$setc}, {$ifc}, {$elsec}, {$endc}) are not recognised, so both arms of the conditional compile. A program that announces {$MODE MACPAS} at the top is told there and then, rather than a few hundred lines later or not at all.

Support for a dialect is deferred, not refused — it comes back when there is real code in active use that needs it.

{$mode delphi} is the one marker that changes behaviour

The others are inert. Delphi mode has exactly two deltas:

default (objfpc-ish) {$mode delphi}
Nested comments on — { outer { inner } } is one comment off, as in Delphi
Assigning a routine to a procedural variable write the address: f := @F f := F also binds the address

-Mobjfpc is the only mode marker with a command-line form, and it selects the default dialect.

Next