Skip to content

Add diagnostic warning levels (-Wall/-Wextra/-Wpedantic)#11812

Open
expipiplus1 wants to merge 9 commits into
shader-slang:masterfrom
expipiplus1:push-ynnsosvxlrwk
Open

Add diagnostic warning levels (-Wall/-Wextra/-Wpedantic)#11812
expipiplus1 wants to merge 9 commits into
shader-slang:masterfrom
expipiplus1:push-ynnsosvxlrwk

Conversation

@expipiplus1

@expipiplus1 expipiplus1 commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Fixes #11012.

Motivation

The diagnostic system had no notion of warning "levels": every warning was either always on, or had to be individually disabled with -Wno-<id>. There was no way to group advisory/stylistic warnings the way clang/gcc do with -Wall/-Wextra/-Wpedantic.

Proposed solution

Add clang/gcc-style warning groups. Following that model the groups are independent (not nested): a warning tagged with a group is emitted only when that group is enabled, while untagged warnings stay in the always-on default group. Most warnings need no annotation; only opt-in warnings are tagged.

A warning is tagged in slang-diagnostics.lua by passing an all/extra/pedantic sentinel positionally to warning(), alongside its spans:

warning("keyword-used-as-name", 20103,
    "keyword used as a name",
    span { loc = "location", message = "..." },
    pedantic)

The level rides on DiagnosticInfo and gating happens in one place, DiagnosticSink::getEffectiveMessageSeverity. Explicit per-id overrides (-W<name>/-Wno-<name>/-warnings-as-errors) continue to take precedence over group gating.

Control is exposed via the -Wall/-Wextra/-Wpedantic CLI flags and the WarningLevel compiler-API option (SlangWarningLevel).

Staging — pedantic is enabled by default for now. As the first example, keyword-used-as-name (E20103) is tagged pedantic: using a type keyword as a name is legal and usually works, so it is a style/portability hint rather than a likely bug. To avoid silently dropping any warning from today's output, the pedantic group is enabled by default in this PR, so tagging only records the group and changes nothing observable yet. A follow-up will flip pedantic to off-by-default and assign groups to the rest of the catalog.

Change summary

File Change
include/slang.h New SlangWarningLevel enum (Default/All/Extra/Pedantic) and CompilerOptionName::WarningLevel = 155 (appended; intValue0 is the group to enable, repeatable).
source/compiler-core/slang-diagnostic-sink.h New internal WarningLevel enum (static-asserted against the public one), a level field on DiagnosticInfo (defaulted so existing aggregate/DIAGNOSTIC(...) initializers keep compiling), enableWarningLevel/isWarningLevelEnabled, and the enabled-groups bitmask (pedantic on by default for now).
source/compiler-core/slang-diagnostic-sink.cpp Gate opt-in warnings in getEffectiveMessageSeverity; keep an explicit "enable" override for grouped warnings (see Process report).
source/slang/slang-diagnostics-helpers.lua Define the all/extra/pedantic sentinels, recognise them in add_diagnostic, carry level through to the processed entry, and export them.
source/slang/slang-diagnostics.lua Import the sentinels; tag keyword-used-as-name as pedantic.
source/slang/slang-rich-diagnostics.h.lua / .cpp getWarningLevelEnum mapping and emit the level as the 5th DiagnosticInfo field.
source/slang/slang-options.cpp Register -Wall/-Wextra/-Wpedantic (one option, three names) and map each to a WarningLevel group value.
source/slang/slang-compiler-options.cpp Apply the WarningLevel option array to the sink in applySettingsToDiagnosticSink.
tests/diagnostics/warning-levels.slang End-to-end test of the flag wiring and -Wno precedence.

Concepts and vocabulary

  • Warning group / level: the all/extra/pedantic bucket a warning belongs to, mirroring the clang/gcc groups. Default is the implicit always-on group.
  • DiagnosticInfo: the static descriptor for each diagnostic (id, severity, name, message — now also level). The Lua catalog generates these for the rich diagnostics; the compiler-core DIAGNOSTIC(...) macro catalogs generate the rest.
  • getEffectiveMessageSeverity: the single chokepoint (used by both the legacy and rich diagnostic paths) that resolves a diagnostic's nominal severity into its effective severity after pragmas, per-id overrides, group gating, and warnings-as-errors.
  • per-id override (m_severityOverrides): the map behind -W<name>/-Wno-<name>/-warnings-as-errors, keyed by diagnostic id.

Process report

Where the level lives, and why. The Lua catalog is the single source of truth for diagnostics, so the group is declared there and flows to DiagnosticInfo::level. The sink reads info.level directly rather than maintaining a side table. The level field has a default member initializer (WarningLevel::Default); this is what lets the existing 4-element aggregate initializers — both the Lua-generated ones and the DIAGNOSTIC(id, severity, name, msg) macro catalogs in compiler-core — keep compiling unchanged.

Gating. In getEffectiveMessageSeverity, after the existing pragma-tracker step, a warning whose group is not enabled is lowered to Severity::Disable. This sits in the else of the per-id-override check, so an explicit -W<name>/-Wno-<name> always wins over group gating.

One cascading fix — keeping the enable override for grouped warnings. overrideDiagnosticSeverity previously dropped any override equal to the diagnostic's nominal severity. With groups that is wrong: a warning whose group is off has an effective default of "suppressed", so an explicit -W<name> enabling it back to Warning is meaningful and must be kept, otherwise group gating would re-suppress it. The fix restricts the "remove when equal to default" shortcut to WarningLevel::Default diagnostics, where the nominal and effective defaults still coincide.

Input-shape check for the CLI handler. The three flags are registered as a single option with three names, so only -Wall/-Wextra/-Wpedantic ever reach the WarningLevel case; any other spelling is a wiring bug, so the fall-through asserts via SLANG_UNEXPECTED. Exact-match option lookup takes priority over the -W<id> prefix, so these are never confused with -W<name>.

Example chosen conservatively, and no behavior change yet. Only keyword-used-as-name is tagged. Because the pedantic group is on by default in this PR, the warning still appears exactly as before (its existing test passes unchanged), and the new warning-levels.slang test confirms the flags are accepted and that -Wno-keyword-used-as-name still suppresses it. Flipping pedantic off-by-default and grouping the rest of the catalog is intentionally left to follow-up, per the issue.

@expipiplus1 expipiplus1 requested a review from a team as a code owner June 29, 2026 08:21
@expipiplus1 expipiplus1 requested review from bmillsNV and Copilot and removed request for a team June 29, 2026 08:21
@expipiplus1 expipiplus1 added the pr: non-breaking PRs without breaking changes label Jun 29, 2026
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds warning-level grouping across the diagnostic API, Lua diagnostics pipeline, CLI option handling, sink filtering, and validation tests. It tags keyword-used-as-name as pedantic, wires -Wall/-Wextra/-Wpedantic, and adds unit and integration tests for grouped warning behavior.

Changes

Warning Level Groups

Layer / File(s) Summary
Public API and sink contracts
include/slang.h, source/compiler-core/slang-diagnostic-sink.h
Adds public and internal warning-level enums, extends DiagnosticInfo with level, and adds sink enable/query APIs plus the enabled-level bitmask.
Lua diagnostics and rich output
source/slang/slang-diagnostics-helpers.lua, source/slang/slang-rich-diagnostics.h.lua, source/slang/slang-rich-diagnostics.cpp, source/slang/slang-diagnostics.lua
Adds warning-level sentinels, records and exports diagnostic levels, maps them for rich diagnostics output, and marks keyword-used-as-name as pedantic.
CLI option parsing and application
source/slang/slang-options.cpp, source/slang/slang-compiler-options.cpp, docs/user-guide/08-compiling.md
Registers WarningLevel, parses -Wall/-Wextra/-Wpedantic, applies them to DiagnosticSink, and documents the option.
Severity gating in DiagnosticSink
source/compiler-core/slang-diagnostic-sink.cpp
Suppresses warnings when their level is disabled and retains per-id overrides for opt-in warning groups.
Diagnostic validation tests
tools/slang-unit-test/unit-test-diagnostic-warning-level.cpp, tests/diagnostics/warning-levels.slang
Adds unit coverage for warning-level gating and integration coverage for pedantic diagnostics, CLI flag behavior, and per-warning suppression.

Related issue: #11012
Suggested reviewers: bmillsNV

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding diagnostic warning levels and the -Wall/-Wextra/-Wpedantic flags.
Description check ✅ Passed The description matches the changeset and explains the warning-level groups, flags, and default pedantic behavior.
Linked Issues check ✅ Passed The PR implements diagnostic warning levels, CLI flags, and grouping/default behavior requested by #11012.
Out of Scope Changes check ✅ Passed The changes stay focused on warning-level support, tests, and docs without unrelated additions.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds clang/gcc-style diagnostic warning groups to Slang, allowing opt-in “advisory/stylistic” warnings via -Wall / -Wextra / -Wpedantic (and the corresponding public compiler option), while keeping untagged warnings always-on by default.

Changes:

  • Introduces a public SlangWarningLevel and CompilerOptionName::WarningLevel, plus an internal WarningLevel carried on DiagnosticInfo.
  • Implements warning-group gating in DiagnosticSink::getEffectiveMessageSeverity, while preserving per-diagnostic overrides (-W… / -Wno-…) precedence.
  • Adds CLI parsing for -Wall / -Wextra / -Wpedantic and an end-to-end regression test covering group gating and override behavior.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
include/slang.h Adds public SlangWarningLevel and new CompilerOptionName::WarningLevel.
source/compiler-core/slang-diagnostic-sink.h Adds internal WarningLevel, DiagnosticInfo::level, and sink enable/query helpers + bitmask.
source/compiler-core/slang-diagnostic-sink.cpp Implements group gating in effective severity resolution; adjusts override retention logic for grouped warnings.
source/slang/slang-diagnostics-helpers.lua Adds/export warning-level sentinels and propagates level through diagnostic processing.
source/slang/slang-diagnostics.lua Imports sentinels and tags implicit-conversion-to-double as pedantic.
source/slang/slang-rich-diagnostics.h.lua Adds mapping from Lua warning-level strings to C++ WarningLevel enums.
source/slang/slang-rich-diagnostics.cpp Emits the warning level into generated DiagnosticInfo initializers for rich diagnostics.
source/slang/slang-options.cpp Registers -Wall/-Wextra/-Wpedantic and maps spellings to SlangWarningLevel option values.
source/slang/slang-compiler-options.cpp Applies the (repeatable) WarningLevel option array to the diagnostic sink.
tests/diagnostics/warning-levels.slang Adds an end-to-end test covering default suppression, group enable, per-id enable, and -Wno precedence.

Comment thread source/compiler-core/slang-diagnostic-sink.h
Comment thread source/compiler-core/slang-diagnostic-sink.h
github-actions[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/slang/slang-diagnostics-helpers.lua (1)

392-406: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Handle warning-level sentinels before binding primary_span.

Locationless diagnostics are allowed, but this parser only recognizes is_warning_level inside .... A call like warning("foo", 1, "msg", pedantic) leaves pedantic in primary_span, so the diagnostic stays in the default group and the entry shape becomes invalid.

Suggested fix
 local function add_diagnostic(name, code, severity, message, primary_span, ...)
+  local level = "default"
+  if primary_span and primary_span.is_warning_level then
+    level = primary_span.level
+    primary_span = nil
+  end
+
   local diag = {
     name = name,
     code = code,
     severity = severity,
     message = message,
     primary_span = primary_span,
-    -- Warning group; "default" (always emitted) unless a sentinel below overrides it.
-    level = "default",
+    -- Warning group; "default" (always emitted) unless a sentinel overrides it.
+    level = level,
   }
@@
     for _, s in ipairs(extra_spans) do
       if s.is_warning_level then
+        if diag.level ~= "default" then
+          error("diagnostic '" .. name .. "' specifies more than one warning level")
+        end
         -- A warning-level sentinel (all/extra/pedantic): record the group and skip it; it is
         -- not a span or note.
         diag.level = s.level

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: d0a0eee7-0b3b-4153-a1d5-11aab52b2104

📥 Commits

Reviewing files that changed from the base of the PR and between 51959e2 and 7a52885.

📒 Files selected for processing (10)
  • include/slang.h
  • source/compiler-core/slang-diagnostic-sink.cpp
  • source/compiler-core/slang-diagnostic-sink.h
  • source/slang/slang-compiler-options.cpp
  • source/slang/slang-diagnostics-helpers.lua
  • source/slang/slang-diagnostics.lua
  • source/slang/slang-options.cpp
  • source/slang/slang-rich-diagnostics.cpp
  • source/slang/slang-rich-diagnostics.h.lua
  • tests/diagnostics/warning-levels.slang

Comment thread source/compiler-core/slang-diagnostic-sink.h
Comment thread source/slang/slang-compiler-options.cpp
Comment thread source/slang/slang-diagnostics.lua Outdated
Comment thread tests/diagnostics/warning-levels.slang Outdated
github-actions[bot]

This comment was marked as outdated.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9348627a-3da5-41e5-b001-19e6e92f1644

📥 Commits

Reviewing files that changed from the base of the PR and between 7a52885 and 92ab688.

📒 Files selected for processing (3)
  • source/compiler-core/slang-diagnostic-sink.h
  • source/slang/slang-diagnostics.lua
  • tests/diagnostics/warning-levels.slang

Comment thread tests/diagnostics/warning-levels.slang
@jhelferty-nv jhelferty-nv removed the request for review from bmillsNV June 29, 2026 18:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e2b78215-0dc9-4f19-92d6-30440a33fe33

📥 Commits

Reviewing files that changed from the base of the PR and between 92ab688 and d242c10.

📒 Files selected for processing (6)
  • docs/user-guide/08-compiling.md
  • source/compiler-core/slang-diagnostic-sink.h
  • source/slang/slang-compiler-options.cpp
  • source/slang/slang-diagnostics.lua
  • tests/diagnostics/warning-levels.slang
  • tools/slang-unit-test/unit-test-diagnostic-warning-level.cpp

Comment thread docs/user-guide/08-compiling.md Outdated
Comment thread tools/slang-unit-test/unit-test-diagnostic-warning-level.cpp Outdated
github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

Add clang/gcc-style warning groups to the diagnostic system. Each group is
enabled independently: a warning tagged with a group is emitted only when that
group is enabled, while untagged warnings stay in the always-on default group.

Warnings are tagged in slang-diagnostics.lua by passing an `all`/`extra`/
`pedantic` sentinel positionally to warning(); the level rides on DiagnosticInfo
and is gated in DiagnosticSink::getEffectiveMessageSeverity. Explicit per-id
overrides (-W<name>/-Wno-<name>) still take precedence over group gating.

Exposed via the -Wall/-Wextra/-Wpedantic CLI flags and the WarningLevel compiler
API option (SlangWarningLevel). As an example, implicit-conversion-to-double
(E30082), a purely advisory performance hint, is moved to the pedantic group.

Fixes shader-slang#11012.
… default

Switch the example pedantic warning from implicit-conversion-to-double to
keyword-used-as-name (E20103): using a type keyword as a name is legal and
usually works, so it is a style/portability hint rather than a likely bug.

Enable the pedantic group by default for now so this grouping does not change
any current output; a follow-up will flip pedantic to off-by-default and assign
groups to the rest of the catalog.
…s/docs

- Bounds-check the bit shift in enableWarningLevel/isWarningLevelEnabled and
  validate the WarningLevel int at the applySettingsToDiagnosticSink boundary, so
  a bogus value cast in through the public option cannot cause an out-of-range
  shift (undefined behavior).
- Add CompilerOptionName::WarningLevel to allowDuplicate() so -Wall/-Wextra/
  -Wpedantic accumulate instead of collapsing to one stored group.
- Drop the unused all/extra Lua aliases (keep pedantic).
- Document WarningLevel and the -Wall/-Wextra/-Wpedantic flags in the user guide.
- Add a DiagnosticSink unit test covering off-by-default group gating, per-id
  override precedence, the warnings-as-errors interaction, and out-of-range
  safety; exercise -Wall/-Wextra in the end-to-end test.
- Note in the user guide that the pedantic group is enabled by default today
  (so -Wpedantic is currently a no-op), pending the follow-up that makes it opt-in.
- Use a direct include path (compiler-core/slang-diagnostic-sink.h) in the new
  unit test instead of relative traversal.
The parent-sink constructor forwarded flags/color/unicode but not the enabled
warning-group bitmask, so a child sink lost the group configuration. Add
get/setEnabledWarningLevels (mirroring getFlags/setFlags) and copy it too.
github-actions[bot]

This comment was marked as outdated.

Exercises the additive allowDuplicate handling and the exact-match-wins
disambiguation against the -W<id> prefix in a single slangc run.
github-actions[bot]

This comment was marked as outdated.

The check-cmdline-ref CI step compares docs/command-line-slangc-reference.md
against `slangc -help-style markdown -h`; the new warning-level flags need the
generated reference updated.
github-actions[bot]

This comment was marked as outdated.

github-actions[bot]

This comment was marked as outdated.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: 🟡 Minor — 1 gap

Adds clang/gcc-style warning groups (WarningLevel::Default/All/Extra/Pedantic) to DiagnosticSink with -Wall/-Wextra/-Wpedantic CLI flags and a public CompilerOptionName::WarningLevel = 155. Gating lives in getEffectiveMessageSeverity; per-id -W<name>/-Wno-<name> overrides win over group gating (with a corresponding fix in overrideDiagnosticSeverity so a -W<name> restoring the nominal severity is not stripped for grouped warnings). Pedantic is on by default as a staging step; only keyword-used-as-name (E20103) is tagged so far.

Changes Overview

Diagnostic sink infrastructure (source/compiler-core/slang-diagnostic-sink.{h,cpp})

  • New WarningLevel enum with static_asserts mirroring the public SLANG_WARNING_LEVEL_*. DiagnosticInfo gains a level field (default Default for aggregate-init compat). DiagnosticSink gains enableWarningLevel/isWarningLevelEnabled (bounds-check < 32 before shift), get/setEnabledWarningLevels, an m_enabledWarningLevels bitmask initialized with Pedantic bit set, and parent-sink inheritance of the bitmask. getEffectiveMessageSeverity gates warnings after per-id overrides; overrideDiagnosticSeverity keeps overrides equal to default severity when the diagnostic is in an opt-in group.

Option plumbing (source/slang/slang-compiler-options.cpp, slang-options.cpp, include/slang.h)

  • New public SlangWarningLevel enum and CompilerOptionName::WarningLevel = 155 (appended before CountOf). CLI parser maps -Wall/-Wextra/-Wpedantic via string comparison; applySettingsToDiagnosticSink iterates the (allow-duplicate) WarningLevel option array and calls enableWarningLevel for values in {ALL, EXTRA, PEDANTIC}, silently ignoring others.

Lua diagnostic generation (source/slang/slang-diagnostics-helpers.lua, slang-diagnostics.lua, slang-rich-diagnostics.h.lua, slang-rich-diagnostics.cpp)

  • Positional all/extra/pedantic sentinels in warning()/err() set diag.level; add_diagnostic recognises them via is_warning_level. Rich-diagnostics template emits WarningLevel::X as the fifth DiagnosticInfo initializer via a new getWarningLevelEnum helper that errors on unknown level names.

Tests (tests/diagnostics/warning-levels.slang, tools/slang-unit-test/unit-test-diagnostic-warning-level.cpp)

  • Six unit tests: default gating, additive enabling, per-id override precedence, warnings-as-errors interaction, parent-sink inheritance, out-of-range safety. One .slang file with five slangc runs (default, -Wpedantic, -Wall, -Wextra, all-three, -Wno-<id>).

Docs (docs/command-line-slangc-reference.md, docs/user-guide/08-compiling.md)

  • New CLI reference section and new WarningLevel row in the CompilerOptionValue table.
Findings (1 total)
Severity Location Finding
🟡 Gap docs/command-line-slangc-reference.md:260-266 File is auto-generated; hand-authored section diverges from what slangc -help-style markdown -h produces from the registration in slang-options.cpp.

Comment thread docs/command-line-slangc-reference.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: non-breaking PRs without breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add diagnostic warning levels

3 participants