🏠 ESL - Engineering Software Lab Scaling MISRA C:2025 compliance: Rule 7.5 to zero with Sourcegraph + Parasoft
ESL · STATIC ANALYSIS ENGINEERING · SOLUTION PLAN

Scaling MISRA C:2025 Compliance
From Thousands of Violations to Proven Zero

A repeatable find → fix → prove loop for Rule 7.5, built on Sourcegraph Enterprise and Parasoft C/C++test.

11
Rule 7.5 candidates in the demo module, seeded across all violation classes
8
Parasoft baseline findings, MISRA C 2025 scan, measured
2
Commits: v1 automation + expert fixes, merged on the demo fork
0
Remaining violations, Parasoft 2026.1.3-certified
Rule 7.5 is classified Mandatory: the scan passes only at zero. The loop below is how we get there: Parasoft opens the loop with a baseline scan of one module, Sourcegraph fixes at scale, and Parasoft verifies every pass; a non-zero scan sends us back to script redesign until the verifier reports zero. The same loop becomes the template for every other MISRA C:2025 rule.
Sourcegraph Sourcegraph Enterprise finds and fixes at scale Parasoft Parasoft C/C++test verifies and certifies zero
Pilot executed for real on 2026-11-04: demo repo driftregion/iso14229 (seeded branch misra-rule-7-5-demo), verifier Parasoft C/C++test Standard 2026.1.3, MISRA C 2025 configuration. Production scope stays 4 repos and 400 branches; the pilot numbers on these slides are measured, not illustrative.
THE PROBLEM, CONCRETELY

MISRA C:2025 Rule 7.5: the argument of an integer constant macro shall have an appropriate form

One recurring coding habit produces easily identifiable violations: a negative value or a suffix placed inside the macro.

Noncompliant: unary minus or suffix inside the macro
/* Calibration constants, as written today */
#define TEMP_OFFSET   INT32_C(-40)
#define MIN_PRESSURE  INT32_C(-100)
#define DEFAULT_TRIM  INT32_C(-25)
#define MASK          UINT32_C(0xFFUL)
Compliant: minus outside the macro, suffix removed
/* Minus moved outside, no suffix inside */
#define TEMP_OFFSET   (-INT32_C(40))
#define MIN_PRESSURE  (-INT32_C(100))
#define DEFAULT_TRIM  (-INT32_C(25))
#define MASK          UINT32_C(0xFF)
Every #define and every call site
set_trim(INT32_C(-25)) is equally noncompliant. The pattern hides in headers, drivers, and tests across all 4 repos.
Mechanically findable, mechanically fixable
The same shape repeats everywhere, which is exactly what cross-repo search plus batch automation is built for.
WHY THE CLEANUP MUST BE AUTOMATED

Manual fixing does not survive 4 repos, 400 branches, and continuous development

Clustered
One module already contains dozens of violations. Extrapolated across the codebase, the count is in the thousands.
Recurring
Every feature branch can reintroduce the pattern. A one-time hand cleanup is obsolete the week it finishes.
Binary
Mandatory rule: any single remaining violation fails the scan. "Mostly fixed" is not a compliance state.
Manual cleanupSourcegraph + Parasoft loop
SearchGrep per repo, per branch, hope you got the patterns rightFour scoped queries cover every violation class across all repos and indexed branches at once
FixThousands of hand edits, copy-paste risk, headers and call sites missedOne automated batch applies every mechanical fix as a reviewed pull request per repo
Prove"We think it is clean"Search returns zero and the Parasoft scan certifies zero, then both run continuously
THE ENGINEERING LOOP · PARASOFT STARTS AND VERIFIES, SOURCEGRAPH ACTS

The loop: Parasoft measures, Sourcegraph fixes, Parasoft decides

1 · PARASOFT STARTS Baseline C/C++test scan one module, small scope 2 · MEASURE ~500 Rule 7.5 violations in that one module alone 3 · EXTRAPOLATE ~50,000 project-wide 4 repos · 400 branches 4 · DECIDE Hand-fixing: thousands of edits, no proof → automate 5 · SOURCEGRAPH Design the scripts: match queries + value-preserving replacement rules 6 · SOURCEGRAPH Run the Batch Change: finds every incident, fixes it reviewed PR, CI green 7 · PARASOFT VERIFIES Verification re-scan: did Sourcegraph succeed? the scanner is the judge Zero findings? NOT ZERO: redesign the script (v2, v3, …) and run again YES 8 · ZERO PROVEN Scale the proven script: merge across all 4 repos, 400 branches inherit 9 · HOLD AT ZERO Standing gate: SG guard query blocks new violations at the PR; Parasoft scans in CI
Parasoft opens the loop and closes it: the baseline scan sizes the problem, and every later scan is the verdict on Sourcegraph's work. Zero is when the verifier says zero, not when the tool claims it. On any non-zero scan we go straight back to script design, exactly as shown by the red loop.
Iteration is cheap by design: each pass is a script edit plus a Batch Change preview, minutes of work, not another thousand hand edits.
SOURCEGRAPH IN THE LOOP · STEP 5, DESIGN THE MATCH QUERIES

One query finds every negative-argument violation across all 4 repositories

⚲ Code Search
⊞ Batch Changes Enterprise
▤ Insights Enterprise
repo:zuwasi/iso14229@misra-rule-7-5-demo (INT32_C|INT64_C|UINT32_C|UINT64_C)\(\s*-\s*[0-9]+\s*\) lang:C count:5000  .*
5 results in 2 files · 1 repository (measured, guard query on the cleaned branch returns 0)patternType:regexp
zuwasi/iso14229 5 negative-argument matches in 2 files · demo baseline inventory: 11 candidates across all classes
▸ demo/rule75_seed/calibration_constants.h
16#define DEMO_TEMP_OFFSET   INT32_C(-40)  /* cold plateau */ 17#define DEMO_MIN_PRESSURE  INT32_C(-100)
▸ demo/rule75_seed/calibration_demo.c
17    demo_trim = INT32_C(-25);  /* call sites match too */
further instances: INT64_C(-500), INT32_C(-5) · plus 4 suffixed, 1 non-literal, 1 signed-minimum in the same 2 files
Measured 2026-11-04 on the demo branch (the same patterns are proven with local grep while the eswlab tenant awaits its Sourcegraph license renewal; production runs these queries on Sourcegraph). Three further queries cover suffixed arguments, a leading plus sign, and non-literal arguments reserved for human review. Release branches are covered with Sourcegraph revision syntax, so nothing hides on the other 399 branches.
SOURCEGRAPH IN THE LOOP · STEP 6, RUN THE BATCH CHANGE

Thousands of fixes become four reviewed pull requests, not a black box

SourcegraphBatch change: misra-rule-7-5-demo  ·  run for real on the demo fork · draft-first, review before merge
▸ zuwasi/iso14229  commit 0fc00476 · v1 automated fix (tools/rule75_v1.py)Merged+89 −9Compile OK
▸ zuwasi/iso14229  commit 2c1f6403 · expert fixes: signed minimum, non-literal, Rule 8.4 declarationsMerged+9 −4Compile OK
▸ demo/rule75_seed/calibration_constants.h  4 negatives relocated, 3 suffixes strippedExpert review+16 −11Scan: 0
▸ demo/rule75_seed/calibration_demo.c  1 negative relocated, 1 suffix strippedExpert review+2 −2Scan: 0
Real diff from the demo changeset, demo/rule75_seed/calibration_constants.h
– #define DEMO_TEMP_OFFSET   INT32_C(-40)
+ #define DEMO_TEMP_OFFSET   (-INT32_C(40))
– #define DEMO_MIN_PRESSURE  INT32_C(-100)
+ #define DEMO_MIN_PRESSURE  (-INT32_C(100))
Every change is a visible diff
Reviewed by the team like any other code change, with the repo's own CI checks running on each changeset.
All 400 branches stay consistent
Changesets merge into each default branch; every other branch inherits the fix through normal merge. No hand-editing of 400 branches.
Real run, 2026-11-04, on github.com/zuwasi/iso14229, branch misra-rule-7-5-demo. In production the same script runs as a Sourcegraph Batch Change with one draft changeset per repo. The automation is value-preserving by construction: the numeric value never changes, only its form.
STEP 5 IN DETAIL · DESIGNING THE SCRIPTS, EXACTLY

SourcegraphTwo mechanical transformations, value-preserving by construction

Applied automatically at every occurrence; v1 script tools/rule75_v1.py, run for real on the demo module
INT32_C(-40)    →  (-INT32_C(40))
INT32_C(-100)   →  (-INT32_C(100))
INT64_C(-500)   →  (-INT64_C(500))
UINT32_C(100U)  →  UINT32_C(100)
UINT32_C(0xFFUL) →  UINT32_C(0xFF)
Value never changes. The numeric value is identical before and after; only the form moves. The compiler and CI protect anything the automation could get wrong, and every diff is human-reviewed before merge.
The automation knows what not to touch. A short expert-owned list is never auto-fixed, shown right. Both exclusions were exercised in the demo run: the signed minimum and the non-literal argument were skipped, reported, and then fixed by expert decision (commit 2c1f6403).
Draft by default
The batch change ships as an unreviewed draft. Nothing merges until the team signs off and CI is green on every repo.
These scripts are versioned design artifacts, not one-shot runs: if the Parasoft verification scan still reports findings, the script is redesigned (v2, v3, ...) and the loop repeats until the verifier reports zero. That path is the red loop in the flowchart.
SAFETY RAILS

Four edge cases are routed to human experts, never to the automation

Signed minimum: INT32_MIN
INT32_C(-2147483648) cannot become (-INT32_C(2147483648)), because 2147483648 does not fit in a 32-bit signed type. The compliant form is ((-INT32_C(2147483647))-1). The automation excludes it; an expert fixes the handful of cases. Exercised in the demo: the script skipped it and the expert fix is merged.
Range checks after suffix removal
The argument must fit the macro's type. Any value that was already out of range is surfaced early by the compiler and the scanner, which is the correct signal.
Non-literal arguments
INT32_C(OTHER_MACRO) or INT32_C(2+3) are also violations, but need a human decision. A dedicated query collects them into a short manual-review list. Exercised in the demo: INT32_C(DEMO_TEMP_OFFSET) was skipped by the script and resolved by hand.
Release-branch pinning
Branch-scoped queries with Sourcegraph revision syntax confirm zero on active release branches, so the fix set is proven everywhere it matters.
PARASOFT IN THE LOOP · THE VERIFIER, STEPS 1, 7 AND 9

ParasoftParasoft C/C++test enforces MISRA C:2025 and certifies the zero

Parasoft C/C++test: MISRA C 2025 test configuration with 388 of 388 rules enabled, and the Quality Tasks violation list
Real Parasoft C/C++test session: the MISRA C 2025 compliance pack selected in the test configuration (388 rules enabled), and the Quality Tasks panel listing per-file violations. This same tool opens the loop and closes it. Measured in the demo pilot, 2026-11-04: the baseline scan found 8 violations in the demo module (5 Rule 7.5, 3 Rule 8.4) and the verification scan after the v1 script plus expert fixes reported 0, on C/C++test Standard 2026.1.3 (the same verdict was confirmed on 2025.2). Its zero report is the compliance evidence for auditors and certification.
WHAT THE RESULT LOOKS LIKE · COMPLIANCE DASHBOARD

Rule 7.5 counts, from baseline to held zero: measured in the demo pilot

MISRA C:2025 Rule 7.5 Cleanup — Demo Pilot: driftregion/iso14229

Static analysis compliance dashboard · Mandatory Rule 7.5 · Sourcegraph inventory + Parasoft C/C++test evidence
Parasoft C/C++test Standard 2026.1.3
Measured 2026-11-04
8 → 0
Violations, total (5 Rule 7.5 + 3 Rule 8.4)
▼ -100% after v1 + expert merge
1 / 1
Demo modules at zero findings
Parasoft-certified, 2026.1.3
11
Source-level candidates reconciled vs scan
Divergence documented, see below
100%
Mandatory rules in scope
No deviations filed

Violations per scan (demo module, measured)

0 4 8 Scan 1: baseline (8 = 5 Rule 7.5 + 3 Rule 8.4) Scan 2: verification (0)

Per-file zero proof (demo module)

calibration_constants.h4 → 0
calibration_demo.c1 → 0
Rule 7.5 findings per file, baseline to verification. Source-level guard queries return zero on the demo branch; the Parasoft scan is the evidence of record.
Dashboard adapted from the ESL ThreadX LoongArch64 compliance dashboard format to this program. All counts are measured, 2026-11-04: Parasoft C/C++test Standard 2026.1.3, MISRA C 2025 configuration, gcc 12, demo repo driftregion/iso14229 (seeded branch misra-rule-7-5-demo). Verifier finding: on both 2025.2 and 2026.1.3, Rule 7.5 flags the suffix and non-literal forms; the negative-in-macro form is accepted by the scanner, so the zero gate covers the suffix and non-literal classes, while the v1 script also normalizes negatives as value-preserving cleanup. In production the same dashboard is populated from the real per-repo baseline scans.
STAYING AT ZERO

Zero is proven twice, then held automatically

SourcegraphProof 1 · the finder becomes the auditor
The exact queries from step 1 run again, and on release branches. Zero results means the pattern is gone at source level, confirmed in seconds, any time. The same query also runs as a CI guard on every pull request, so a new violation is blocked at the PR that introduced it.
ParasoftProof 2 · the scanner certifies it
A full Parasoft C/C++test scan of the whole project reports zero Rule 7.5 findings. That report is the compliance evidence of record for auditors and certification, and it reruns in the pipeline on every merged change.
Zero violations become a property of the process, not a one-time achievement: the guard query stops new violations at the pull request, and the scanner re-certifies the merged result continuously.
Week 1
Pilot: pilot module scanned, inventory sized, dashboard populated with real numbers — executed in the demo pilot, 2026-11-04
Weeks 2-3
Batch change across all 4 repos, reviewed and merged; release-branch queries confirm zero
Week 4+
Standing gate: guard query in CI, Parasoft scan in the pipeline, dashboard shows held zero
Elapsed time in the demo pilot, seed to verified zero: under one day. Production estimate stays under one month. The workflow is then a template: the next MISRA C:2025 rule gets the same search, fix, and proof loop with no new tooling.
1 / 11
← Swipe to navigate →