Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Diagnostic System Overview

The cudafe++ diagnostic system is a 7-stage pipeline rooted in EDG 6.6's error.c. It manages 3,795 error message templates, 9 severity levels, per-error suppression tracking, #pragma diagnostic overrides, and two output formats (text and SARIF JSON). The most-connected function in the entire binary -- sub_4F2930 (assertion handler) with 5,185 call sites -- feeds into this system, making error handling the single largest cross-cutting concern in cudafe++.

Error Table

The error message template table lives at off_88FAA0: an array of 3,795 const char* pointers indexed by error code (0--3794).

RangeCountOriginDisplay Format
0--34563,457Standard EDG 6.6#N-D
3457--3794338NVIDIA CUDA extensions#(N+16543)-D (20000--20337-D series)

The renumbering logic in construct_text_message (sub_4EF9D0):

int display_code = error_code;
if (display_code > 3456)
    display_code = error_code + 16543;   // 3457 → 20000, 3794 → 20337
sprintf(buf, "%d", display_code);

The -D suffix is appended only when severity <= 7 (warnings and below). Errors with severity > 7 (catastrophic, command-line error, internal) omit the suffix:

const char *suffix = "-D";
if (severity > 7)
    suffix = "";

Any access with error code > 3794 triggers sub_4F2D30 (error_text), which fires an assertion: "error_text: invalid error code" (error.c:911).

Severity Levels

Nine severity values are stored as a single byte at offset 180 of the diagnostic record:

ValueNameDisplay String (lowercase)Display String (uppercase)ColorizationExit Behavior
2note"note""Note"cyan (code 4)continues
4remark"remark""Remark"cyan (code 4)continues
5warning"warning""Warning"magenta (code 3)continues
6command-line warning"command-line warning""Command-line warning"magenta (code 3)continues
7error (soft)"error""Error"red (code 2)continues, counted
8error (hard)"error""Error"red (code 2)continues, counted, not suppressible by pragma
9catastrophic"catastrophic error""Catastrophic error"red (code 2)immediate exit(4)
10command-line error"command-line error""Command-line error"red (code 2)immediate exit(4)
11internal error"internal error""Internal error"red (code 2)immediate exit(11) via abort path

Uppercase display strings are used when dword_106BCD4 is set, indicating the diagnostic originates from a predefined macro file context (e.g., "In predefined macro file: Error #...").

The special string "nv_diag_remark" at offset +8 yields "remark" -- an NVIDIA-specific annotation kind for CUDA diagnostic remarks.

Severity Byte Arrays

Three parallel byte arrays, indexed as [4 * error_code], track per-error severity state:

ArrayAddressPurpose
byte_10679200x1067920Default severity -- the compile-time severity assigned to each error code
byte_10679210x1067921Current severity -- the effective severity after #pragma overrides
byte_10679220x1067922Tracking flags -- bit 0: first-time guard, bit 1: already-emitted, bit 2: has pragma override

The 4-byte stride means each error code occupies a 4-byte slot across all three arrays, with only the first byte of each slot used. This layout allows the pragma override system (sub_4F30A0) to efficiently look up and modify per-error severity.

7-Stage Diagnostic Pipeline

  caller emits error
       |
       v
  [1] create_diagnostic_entry     sub_4F40C0
       Allocate ~200-byte record, set error_code + severity
       |
       v
  [2] check_for_overridden_severity   sub_4F30A0
       Walk #pragma diagnostic stack, apply push/pop overrides
       |
       v
  [3] check_severity              sub_4F1330      ← 62 callers, 77 callees
       Central dispatch: suppress/promote, error limit, output routing
       |
       ├─── text path ──────────────────────────────────────┐
       |                                                     |
       v                                                     v
  [4] write_message_to_buffer    sub_4EF620       [6] write_sarif_message_json  sub_4EF8A0
       Expand %XY format specifiers from template             JSON-escape + wrap
       |                                                     |
       v                                                     v
  [5] construct_text_message     sub_4EF9D0 (6.5 KB)       SARIF JSON buffer → stderr
       file:line prefix, severity label, word wrap,
       caret lines, template context, include stack
       |
       v
  [4a] process_fill_in           sub_4EDCD0 (1,202 lines)
       Expand %T/%n/%s/%p/%d/%u/%t/%r specifiers
       |
       v
       output → stderr or redirect file

Stage 1: create_diagnostic_entry (sub_4F40C0)

Allocates a diagnostic record via sub_4EC940 and initializes it:

record = allocate_diagnostic_record();
record->kind = 0;              // primary diagnostic
record->error_code = a1;       // offset 176
if (severity <= 7)
    check_for_overridden_severity(a1, &severity, position);
record->severity = severity;   // offset 180
// resolve source position → file, line, column
// link into global diagnostic chain (qword_106BA10)

The wrapper sub_4F41C0 sets dword_106B4A8 (file index mode) to -1 for command-line and fatal severities (6, 9, 10, 11), disabling file-index tracking for diagnostics that have no meaningful source location.

Sub-diagnostics are created by sub_4F5A70 with kind=2, linked to their parent's sub-diagnostic chain at offsets 40/48 of the parent record.

Stage 2: check_for_overridden_severity (sub_4F30A0)

Walks the #pragma diagnostic stack stored in qword_1067820. Each stack entry is a 24-byte record containing a source position, a pragma action code, and an optional error code target.

Pragma action codes and their effect on severity:

CodePragmaEffect
30ignoredSet severity to 3 (suppress)
31remarkSet severity to 4
32warningSet severity to 5
33errorSet severity to 7
35defaultRestore from byte_1067920[4 * error_code]
36push/pop markerScope boundary for push/pop tracking

The function uses binary search (bsearch with comparator sub_4ECD20) to find the nearest pragma entry that applies at the current source position, then walks backward through the stack to resolve nested push/pop scopes.

Stage 3: check_severity (sub_4F1330)

The central dispatch function (601 decompiled lines, 62 callers, 77 callees). This is the most complex function in the error subsystem.

Complete decision tree pseudocode (derived from the decompiled sub_4F1330):

void check_severity(diagnostic_record *record) {
    dword_1065938 = 0;                    // reset caret-position cache
    uint8_t min_sev = byte_126ED69;       // minimum severity threshold

    // ── Gate 1: Minimum severity filter ──
    if (min_sev > record->severity) {
        if (min_sev == 3)                 // severity 3 = suppress sentinel
            ASSERT_FAIL("check_severity", error.c:3859);
        goto count_and_exit;              // silently discard
    }

    // ── Gate 2: System-header / suppress-all promotion ──
    if (is_system_header(record->source_sequence_number)) {
        min_sev = 8;                      // promote to hard error
    } else if (qword_106BCD8) {           // suppress-all-but-fatal mode
        min_sev = 7;                      // treat as error-level floor
    } else if (min_sev == 3) {
        ASSERT_FAIL("check_severity", error.c:3859);
    }

    if (record->severity < min_sev)
        goto count_and_exit;

    // ── Gate 3: Per-error tracking flags ──
    uint8_t *flags = &byte_1067922[4 * record->error_code];
    if (record->severity <= 7) {          // suppressible severities only
        uint8_t old = *flags;
        *flags |= 2;                      // mark as emitted
        if ((old & 1) && (old & 2))       // first-time guard + already-emitted
            goto suppressed;              // skip: already seen in this scope
    } else {
        *flags |= 2;                      // hard errors: always mark, never skip
    }

    // ── Gate 4: Pragma diagnostic check ──
    if (dword_126C5E4 != -1) {            // scope tracking active
        if (check_pragma_diagnostic(record->error_code,
                                     record->severity,
                                     &record->source_seq)) {
suppressed:
            // Update error/warning counters even when suppressed
            uint8_t sev = record->severity;
            if (sev <= 7 && sev < byte_126ED68)  // promote to error threshold
                sev = sev;                        // keep as-is
            else
                sev = 7;                          // count as error
            update_suppressed_counts(sev, &qword_126EDC8);
            goto count_and_exit;
        }
        // Record pragma scope if applicable
        if (in_template_scope() || has_special_scope_flags())
            record_pragma_diagnostic(record->error_code, record->severity);
    }

    // ── Gate 5: Suppress-all-but-fatal redirect ──
    if (qword_106BCD8 && !dword_106BCD4 && record->error_code != 992) {
        emit_error_992();                 // replace with fatal error 992
        return;                           // guard against catastrophic loop
    }

    // ── Severity promotion: warning → error threshold ──
    uint8_t effective_sev = record->severity;
    if (effective_sev <= 7 && effective_sev >= byte_126ED68) {
        effective_sev = 7;                // promote to error
        if (dword_126C5C8 == -1) {
            update_counts(7, &qword_126ED80);
            if (!dword_126ED78)           // no further counting needed
                goto skip_extra_counts;
            goto update_additional_counts;
        }
    } else if (effective_sev > 7 || effective_sev < byte_126ED68) {
        // Already at error+ or below promotion threshold
    }
    update_counts(effective_sev, &qword_126ED80);
    if (dword_126ED78 && (effective_sev - 9) > 2)  // not catastrophic/internal
        goto update_additional_counts;

skip_extra_counts:
    if (qword_126EDC0)
        update_counts(effective_sev, qword_126EDC0);

    // ── Allocate output buffers (first use) ──
    if (!qword_106B488) {
        qword_106B488 = alloc_buffer(0x400);
        qword_106B480 = alloc_buffer(0x80);
    }
    reset_buffer(qword_106B488);
    reset_buffer(qword_106B480);

    // ── Catastrophic loop detection ──
    if (record->severity == 9) {
        if (dword_106B4B0) {              // already processing catastrophic
            fprintf(stderr, "%s\n", "Loop in catastrophic error processing.");
            emergency_exit(9);            // never returns
        }
        dword_106B4B0 = 1;               // set catastrophic guard
        if (record->error_code == 3709 || !dword_126ED48)
            goto emit_message;
    } else if (record->severity == 11 || record->error_code == 3709) {
        goto emit_message;                // internal error or warnings-as-errors
    }

    // ── Template context expansion ──
    int context_count = 0;
    for (int scope = dword_126C5E4; scope > 0; scope--) {
        context_count += format_scope_context(scope);
    }
    // Include-file context
    if (dword_126EE48 && qword_106B9F0 && has_include_context()) {
        file_info = lookup_source_file(record->source_seq);
        if (file_info != current_file) {
            context_count++;
            // Emit error 1063/1064 (include-stack context)
            create_sub_diagnostic(record, (context_count != 1) ? 1064 : 1063);
        }
    }
    // Context elision (when context_limit is set)
    if (dword_126ED58 > 0 && dword_126ED58 + 1 < context_count) {
        // Emit error 1150: "%d context lines elided"
    }

emit_message:
    // ── Output routing ──
    reset_buffer(qword_106B488);
    if (dword_106BBB8 == 1) {
        // SARIF JSON path
        write_sarif_json(record);         // → qword_106B478
        fputs(sarif_buffer, stderr);
        fflush(stderr);
    } else {
        construct_text_message(record);   // → sub_4EF9D0
    }

    // ── Termination for fatal severities ──
    if (record->severity >= 9 && record->severity <= 11) {
        cleanup();                        // flush output, close files
        emergency_exit(record->severity); // exit with severity as code
        // unreachable
    }

    // ── Error limit enforcement ──
    if (qword_126ED90 + qword_126ED98 >= qword_126ED60) {
        fprintf(stderr, "%s\n", "Error limit reached.");
        if (qword_106C260)                // raw listing file
            fwrite("C \"\" 0 0 error limit reached\n", 1, 29, listing);
        cleanup();
        emergency_exit(9);               // exit(catastrophic)
    }

    // ── Warnings-as-errors promotion ──
    if (record->severity == 5 && dword_106C088 && !dword_106B4BC) {
        uint8_t saved_min = byte_126ED69;
        byte_126ED69 = 4;                // temporarily lower threshold
        dword_106C088 = 0;               // prevent recursion in self
        dword_106B4BC = 1;               // prevent recursion guard
        emit_diagnostic(4, 3709, ...);   // "warnings treated as errors"
        byte_126ED69 = saved_min;        // restore threshold
        dword_106C088 = 1;               // restore mode
    }

    // ── File index update ──
    if (dword_106B4A8 != -1)
        update_file_index(record);

count_and_exit:
    return;
}

Key decision points explained:

Minimum severity gate:

The global byte_126ED69 is the minimum severity threshold -- diagnostics below this level are silently discarded. When the threshold is 3 (the "suppress" sentinel), an assertion fires, which prevents the threshold from ever being set to the suppress level directly.

System-header promotion:

When a diagnostic originates from a system header (detected by sub_5B9B60), its severity is promoted to 8 (hard error, not suppressible by pragma). This applies equally to CUDA system headers.

Per-error tracking:

Bit 0 of the tracking flags (byte_1067922[4 * error_code]) acts as a first-time guard: if both bit 0 (first-time) and bit 1 (already-emitted) are set, the error has been suppressed-then-seen, and further emissions are skipped depending on the pragma scope.

Suppress-all-but-fatal mode:

When qword_106BCD8 is set and the error is not error 992 (the fatal sentinel), check_severity replaces the current diagnostic with error 992 and re-enters.

Catastrophic loop detection:

The re-entry guard dword_106B4B0 prevents infinite recursion when a catastrophic error triggers another catastrophic error during its own processing. The message "Loop in catastrophic error processing." is printed directly to stderr followed by emergency_exit(9).

Error limit enforcement:

qword_126ED90 (total errors) + qword_126ED98 (total warnings) are checked against qword_126ED60 (error limit). When exceeded, the compiler writes the limit message and exits with catastrophic status. The raw listing file also receives a machine-readable C "" 0 0 error limit reached line.

Warnings-as-errors promotion:

When dword_106C088 (warnings-are-errors mode) is set, every warning (severity 5) triggers error 3709 ("warnings treated as errors") as a follow-up diagnostic. The implementation temporarily lowers the minimum severity threshold to 4 (remark), disables warnings-as-errors mode, sets the recursion guard, emits the diagnostic, then restores all three values. This prevents the error-3709 diagnostic from itself triggering another error-3709.

Output routing:

if (dword_106BBB8 == 1)
    // SARIF JSON path: sub_4EF8A0 → qword_106B478
else
    sub_4EF9D0(record);   // text path → construct_text_message

Termination for fatal severities:

Severities 9 (catastrophic), 10 (command-line error), and 11 (internal error) all trigger cleanup via sub_66B5E0 followed by sub_5AF2B0(severity), which maps severity to the process exit code.

Stage 4: write_message_to_buffer (sub_4EF620)

Looks up the error template string from the table and expands format specifiers:

const char *template = off_88FAA0[error_code];   // error_code must be <= 3794

Format specifier syntax: %XY...Zn where:

  • X = specifier letter (T, d, n, p, r, s, t, u)
  • Y...Z = option characters (a-z, A-Z), max 29
  • n = trailing digit = fill-in index

Special forms:

  • %% = literal %
  • %[label] = named label fill-in, looked up in off_D481E0 table

Each specifier dispatches to process_fill_in (sub_4EDCD0) with the appropriate fill-in kind.

Stage 5: construct_text_message (sub_4EF9D0)

The largest function in the error subsystem at 1,464 decompiled lines (6.5 KB). Formats the complete diagnostic output.

Output format:

file(line): severity #code-D: message text

Variant formats:

  • "At end of source: ..." -- when line number is 0
  • "In predefined macro file: ..." -- when dword_106BCD4 is set
  • "Line N" -- when the file name is "-" (stdin)

Sub-diagnostic indentation:

KindIndent (chars)Continuation indent
0 (primary)010
2 (sub-diagnostic, same parent)1020
2 (sub-diagnostic, different parent)1222
3 (related)111

Word wrapping:

The function wraps output text at dword_106B470 (terminal width) column boundaries. When colorization is disabled, it uses a simple space-scanning algorithm. When colorization is enabled (ESC byte 0x1B in the formatted string), it tracks visible character width separately from escape sequence bytes and wraps only on visual boundaries.

Fill-in verification:

After output, the function iterates the fill-in linked list and asserts that every entry has used_flag == 1. An unused fill-in triggers: "construct_text_message: not all fill-ins used for error string: \"...\"" (error.c:4781).

Raw listing output:

When qword_106C260 (raw listing file) is open and the diagnostic is not a continuation (kind != 3), a machine-readable line is emitted:

S "filename" line column message\n

Where S is a single-character severity code: R (remark), W (warning), E (error), C (catastrophic/internal). Internal errors additionally prefix "(internal error) " before the message text.

Stage 6: process_fill_in (sub_4EDCD0)

Expands a single format specifier by searching the diagnostic record's fill-in linked list (head at offset 184) for an entry matching the requested kind and index. 1,202 decompiled lines.

Fill-in kind dispatch (from ASCII code of specifier letter):

LetterASCIIKindPayload
%T846 (type)Type node pointer
%d1000 (decimal)Integer value
%n1104 (entity name)Entity node pointer + options
%p1122 (parameter)Source position
%r1147Byte + pointer
%s1153 (string)String pointer
%t1165(type variant)
%u1171 (unsigned)Unsigned integer value

Entity name options (for %n specifier):

OptionMeaning
fFull qualification
oOmit kind prefix
pOmit parameters
tFull with template arguments
aOmit + show accessibility
dShow declaration location
TShow template specialization

Assertion Handler (sub_4F2930)

The most-connected function in the entire cudafe++ binary: 5,185 call sites. Declared __noreturn.

Signature:

void __noreturn assertion_handler(
    char *source_file,     // EDG source file path
    int   line_number,     // source line number
    const char *func_name, // enclosing function name
    const char *prefix,    // message prefix (or NULL)
    const char *message    // detail message (or NULL)
);

Message format (with prefix):

assertion failed: <prefix> <message> (<file>, line <line> in <func>)

Message format (without prefix):

assertion failed at: "<file>", line <line> in <func>

The function allocates a 0x400-byte buffer via sub_6B98A0, concatenates the message components using sub_6B9CD0 (buffer append), then calls sub_4F21C0 (internal_error). Because sub_4F21C0 is also __noreturn, the code after the call is dead -- the decompiler shows a loop structure with sprintf(v20, "%d", v8) that is never actually reached.

When dword_126ED40 (suppress assertion output) is set, the message text is replaced with "<suppressed>".

Internal Error Handler (sub_4F21C0)

Creates error 2656 with severity 11 (internal error), outputs it through the standard pipeline, then exits.

void __noreturn internal_error(const char *message) {
    if (dword_1065928) {                     // re-entry guard
        fprintf(stderr, "%s: %s\n", "Internal error loop", message);
        sub_5AF2B0(11);                      // emergency exit
    }
    dword_1065928 = 1;                       // set guard
    diag = sub_4F41C0(2656, &current_pos, 11);  // create diag record
    if (message)
        sub_4F2E90(diag, message);           // attach message as fill-in
    sub_4F1330(diag);                        // route through check_severity
    sub_5AF1D0(11);                          // cleanup + exit(11)
    sub_4F2240();                            // update file index (unreachable)
}

The re-entry guard dword_1065928 prevents infinite recursion: if internal_error is called while already processing an internal error (e.g., an assertion fires inside the error formatting code), it prints "Internal error loop: <message>" directly to stderr and exits immediately with code 11.

Exit Codes

CodeConditionTrigger
0Compilation succeededNormal exit via sub_5AF1D0(0)
2Errors encounteredtotal_errors > 0 at exit
4Catastrophic errorSeverity 9 or 10 reached
11Internal errorSeverity 11 (assertion failure)
abortDouble internal errorRe-entry in sub_4F21C0 or catastrophic loop

The exit path flows through sub_5AF2B0, which maps the severity to the appropriate process exit code. Catastrophic loop detection ("Loop in catastrophic error processing.") calls sub_5AF2B0(9), which maps to exit code 4.

Diagnostic Record Layout

Each diagnostic record is approximately 200 bytes, allocated by sub_4EC940:

OffsetSizeFieldDescription
04kind0=primary, 2=sub-diagnostic, 3=continuation
88nextLinked list pointer (global chain)
168parentParent diagnostic (for sub-diagnostics)
248related_listRelated diagnostic chain
408sub_diagnostic_headFirst sub-diagnostic
488sub_diagnostic_tailLast sub-diagnostic
728context_headTemplate/include context chain
888related_infoRelated location info pointer
968source_sequence_numberPosition in source sequence
1364file_indexIndex into source file table
1402column_endEnd column for caret range
1444line_deltaLine offset for continuation
1528file_name_stringCanonical file path
1608display_file_nameDisplay-formatted file path
1684column_numberColumn number
1724caret_infoCaret position data
1764error_codeError code (0--3794)
1801severitySeverity level (2--11)
1848fill_in_list_headFirst fill-in entry
1928fill_in_list_tailLast fill-in entry

Fill-In Entry Layout

Each fill-in entry is 40 bytes, allocated from a free-list pool (qword_106B490) or heap (sub_6B8070):

OffsetSizeFieldDescription
04kindFill-in kind (0--7, mapped from format specifier letter)
41used_flagSet to 1 when consumed during formatting
88nextNext fill-in in linked list
168+payloadUnion: qword for most kinds; int+int for kind 4 (entity name)

Kind-specific initialization in alloc_fill_in_entry (sub_4F2DE0):

  • Kind 2 (parameter): payload = qword_126EFB8 (current source position)
  • Kind 4 (entity name): payload = 0, extra = 0xFFFFFFFF, flags = 0
  • Kind 7: byte + qword payload
  • Default: payload = 0

Colorization

Initialized by sub_4F2C10 (init_colorization, error.c:825):

  1. Check NOCOLOR environment variable -- if set, disable colorization
  2. Check sub_5AF770 (isatty) -- if stderr is not a terminal, disable
  3. Read EDG_COLORS or GCC_COLORS environment variable
  4. Default: "error=01;31:warning=01;35:note=01;36:locus=01:quote=01:range1=32"

Category codes used in escape sequences:

CodeCategoryDefault ANSI
1reset\033[0m
2error\033[01;31m (bold red)
3warning\033[01;35m (bold magenta)
4note/remark\033[01;36m (bold cyan)
5locus\033[01m (bold)
6quote\033[01m (bold)
7range1\033[32m (green)

Controlled by dword_126ECA0 (colorization requested) and dword_126ECA4 (colorization active). The sub_4ECDD0 function emits escape sequences to the output buffer, and sub_4F3E50 handles escape insertion during word-wrapped output.

Key Global Variables

VariableAddressTypePurpose
off_88FAA00x88FAA0const char*[3795]Error message template table
off_D481E00xD481E0struct[]Named label fill-in table
byte_10679200x1067920byte[4*3795]Default severity per error
byte_10679210x1067921byte[4*3795]Current severity per error
byte_10679220x1067922byte[4*3795]Per-error tracking flags
byte_126ED680x126ED68byteError promotion threshold
byte_126ED690x126ED69byteMinimum severity threshold
qword_126ED600x126ED60qwordError limit
qword_126ED900x126ED90qwordTotal error count
qword_126ED980x126ED98qwordTotal warning count
dword_106B4B00x106B4B0intCatastrophic error re-entry guard
dword_106B4BC0x106B4BCintWarnings-as-errors recursion guard
dword_106BBB80x106BBB8intOutput format (0=text, 1=SARIF)
dword_106C0880x106C088intWarnings-are-errors mode
dword_10659280x1065928intInternal error re-entry guard
qword_106BCD80x106BCD8qwordSuppress-all-but-fatal mode
dword_106BCD40x106BCD4intPredefined macro file mode
qword_106B4880x106B488qwordMessage text buffer (0x400 initial)
qword_106B4800x106B480qwordLocation prefix buffer (0x80 initial)
qword_106B4780x106B478qwordSARIF JSON buffer (0x400 initial)
dword_106B4700x106B470intTerminal width for word wrapping
qword_126EDF00x126EDF0FILE*Error output stream (default stderr)
qword_106C2600x106C260FILE*Raw listing output file

Function Map

AddressName (Recovered)EDG SourceSizeRole
0x4EC940allocate_diagnostic_recorderror.c--Pool allocator for diagnostic records
0x4ECB10write_sarif_physical_locationerror.c--SARIF location JSON fragment
0x4ECDD0emit_colorization_escapeerror.c--Emit ANSI escape to buffer
0x4ED190record_pragma_diagnosticerror.c--Record pragma override in scope
0x4ED240check_pragma_diagnosticerror.c--Check if error suppressed by pragma
0x4EDCD0process_fill_inerror.c:42971,202 linesFormat specifier expansion
0x4EF620write_message_to_buffererror.c:4703159 linesTemplate string expansion
0x4EF8A0write_sarif_message_jsonerror.c79 linesSARIF message JSON wrapper
0x4EF9D0construct_text_messageerror.c:31531,464 linesFull text diagnostic formatter
0x4F1330check_severityerror.c:3859601 linesCentral severity dispatch
0x4F2190check_severity_thunkerror.c8 linesTail-call wrapper
0x4F21A0internal_error_varianterror.c9 linescheck_severity + exit(11)
0x4F21C0internal_errorerror.c22 linesError 2656, severity 11, re-entry guard
0x4F2240update_file_indexerror.c114 linesLRU source-file index cache
0x4F24B0build_source_caret_lineerror.c~100 linesSource caret underline
0x4F2930assertion_handlererror.c101 lines5,185 callers, __noreturn
0x4F2C10init_colorizationerror.c:82543 linesParse EDG_COLORS/GCC_COLORS
0x4F2D30error_text_invalid_codeerror.c:91112 linesAssert on code > 3794
0x4F2DE0alloc_fill_in_entryerror.c41 linesPool allocator for fill-ins
0x4F2E90append_fill_in_stringerror.c--Attach string fill-in to diagnostic
0x4F30A0check_for_overridden_severityerror.c:3803~130 linesPragma diagnostic stack walk
0x4F3480format_assertion_messageerror.c~100 linesMulti-arg string builder
0x4F3E50emit_colorization_in_wraperror.c--Escape handling during word wrap
0x4F40C0create_diagnostic_entryerror.c:5202~50 linesBase record creator
0x4F41C0create_diagnostic_entry_with_file_indexerror.c13 linesWrapper with file-index mode
0x4F5A70create_sub_diagnosticerror.c:524232 lineskind=2 sub-diagnostic creator
0x4F6C40format_scope_contexterror.c--Extract instantiation context from scope

Call Graph

sub_4F2930 (assertion_handler)  [5,185 callers, __noreturn]
  └── sub_4F21C0 (internal_error)
        ├── sub_4F41C0 (create_diagnostic_entry, error=2656, sev=11)
        │     └── sub_4F40C0 (create_diagnostic_entry)
        │           └── sub_4F30A0 (check_for_overridden_severity)
        ├── sub_4F2E90 (append_fill_in_string)
        ├── sub_4F1330 (check_severity)  [62 callers, 77 callees]
        │     ├── sub_4ED240 (check_pragma_diagnostic)
        │     ├── sub_4EF9D0 (construct_text_message)
        │     │     ├── sub_4EF620 (write_message_to_buffer)
        │     │     │     └── sub_4EDCD0 (process_fill_in)
        │     │     ├── sub_4F24B0 (build_source_caret_line)
        │     │     └── sub_4F3E50 (emit_colorization_in_wrap)
        │     ├── sub_4EF8A0 (write_sarif_message_json)
        │     │     └── sub_4EF620 (write_message_to_buffer)
        │     ├── sub_4F5A70 (create_sub_diagnostic)
        │     ├── sub_4F2DE0 (alloc_fill_in_entry)
        │     ├── sub_4F6C40 (format_scope_context)
        │     ├── sub_66B5E0 (cleanup)
        │     └── sub_5AF2B0 (exit)
        ├── sub_5AF1D0 (cleanup + exit)
        └── sub_4F2240 (update_file_index)