Skip to content
PaskalCPP
Build and run

Diagnostics

Errors speak PaskalCPP. A mistake in PaskalCPP code is reported in PaskalCPP's words and types; what only C++ can judge is clang's or the linker's report, mapped back to the .pcpp file, line and column it came from.

Who reports a mistake

Every code names the part of the compiler that reports it:

PrefixReported by
LXthe lexer
PRthe parser
CDthe conditional directives (@ifdef and the others)
SMsemantics
EMthe emitter
ZBthe build driver and the toolchain
CMPthe compiler
DBthe debugger

The reference lists every code with its messages.

  • A mistake on a PaskalCPP construct is reported by PaskalCPP: an unterminated string is LX0001, a missing ; PR0001 (expected ';', found 'LN'), a string assigned to an int32 SM0200, a call no overload takes SM0402.
  • What only C++ can judge is the toolchain's diagnostic, code ZB0016, with clang's or the linker's own message, mapped back to the .pcpp file, line and column: a bare name no declaration has (it may be a C/C++ name: use of undeclared identifier 'LMissing'), a mistake in mixed C++, a symbol no library defines (at the line that calls it). Both targets print the same.
  • A check the compiler writes into the C++ for what clang decides (alignment, packed and overlay fields, printing a C/C++ value) is reported with its SM code, in PaskalCPP's words, at the PaskalCPP construct.
  • clang's warnings are reported on a build that succeeds too, as warnings located in the .pcpp file.
errorSM0200…/samples/diagnostics_narrowing.pcpp(33,13)
'int32' does not convert implicitly to 'int8'; write int8(LBig)

How a report prints

A report is one line, [<LABEL>] <file>(<line>,<column>) <CODE>: <message>. The label is HINT, WARN, ERROR or FATAL (cyan, yellow, red and magenta on a console), and the file is its full path with forward slashes.

A note explains the report above it, indented two spaces: <file>(<line>,<column>): Note: <message>. SM0402, for example, gets one note per overload.

errorSM0324…/samples/diagnostics_overload_repeat.pcpp(34,1)
'Show' is already declared with these parameter types: overloads differ in their parameter types …/samples/diagnostics_overload_repeat.pcpp(29,1): note: the first declaration of 'Show' with these parameter types
  • Columns are printed in UTF-16 units, as the editor, VS Code and the language server count them, for PaskalCPP's reports and clang's mapped ones alike.
  • A place with no column (the linker knows only the line) prints column 0: (4,0).
  • Hints and warnings print as they are made, with their notes, between the build's status lines. Errors print together at the end, then Failed., and pcpp exits 1. A build zig ran says Build failed with exit code <n>. first.

Hints and warnings never fail a build: the program builds and runs.

diagnostics_warnings.pcpp
module exe diagnostics_warnings;

@message hint "diagnostics_warnings: a hint";
@message warn "diagnostics_warnings: a warning";

begin
  println("octal {}", 010);
  println("escape {}", "a\qb");
end.
output on x86_64-windows-gnu and x86_64-linux-gnu
octal 8
escape aqb
[Heap] Allocs: 0, Frees: 0, Leaked: 0

How many reports a build shows

pcpp stops at the first error: its budget is one error, and clang is asked for one error per C++ file (-Wfatal-errors); a budget above one asks clang for that many (-ferror-limit=<n>). The language server checks with a budget of 100.

  • Only errors spend the budget: hints and warnings are always kept, and a fatal is kept past the budget.
  • Nothing is emitted or built after a PaskalCPP error: the report comes right after Compiling <file>, with no target or build lines.

One mistake, one report

  • A diagnostic is reported once per build: the same file, line, column, level and message from a header several C++ files include is the first file's report, with its notes.
  • What PaskalCPP has judged, clang never judges again: an unknown escape in a plain string is PR0021 and in a char PR0064, once, and the program gets the character itself ("a\qb" prints aqb).
  • The line splice and comment warnings (LX0201 to LX0203) are the lexer's; clang's copies of them in the .pcpp file are dropped, so a build shows each once, on both targets.