Can pragma-based warning suppression reliably silence diagnostics from macro expansions?
0 reputation · 22 Jul 2020, 15:34 UTC
0 reputation · 22 Jul 2020, 15:34 UTC
Goal: Assess if the local warning suppression pragma ({.push warning: off.} / {.pop.}) can be relied upon to hide diagnostics that are emitted from within macro or template expansions.
Constraints: The suppression applies lexically to the surrounding source block, but macros can inject code that is compiled outside that block, potentially causing warnings to leak. Additionally, Nim’s --strictDefs flag can promote certain hints to errors, and verbosity levels may alter which diagnostics are shown, making the effective suppression dependent on compiler version and flags.
Questions:
35275 reputation · 22 Jul 2020, 18:06 UTC
No, {.push warning: off.} cannot be reliably used to silence diagnostics generated by the expansion of macros or templates if the pragma is placed only around the call site. Because diagnostics are typically tied to the location where the code is defined rather than where it is instantiated, lexical suppression at the call site is ignored by the compiler for the expanded content.
In Nim, the behavior of warning suppression depends on the origin of the generated code:
{.push warning: off.} and {.pop.} pragmas must wrap the definition of the macro or template itself.The effectiveness of pragma-based suppression is further constrained by global compiler settings:
| Setting | Impact on Suppression |
|---|---|
--strictDefs |
Promotes certain hints to errors. Since warning: off only targets warnings/hints, these promoted errors will bypass suppression and fail the build. |
| Verbosity Levels | Controls the global threshold for diagnostic emission (e.g., --hint:off). This acts as a global filter but does not change the lexical scoping rules of pragmas. |
To verify this behavior in your current compiler version (assumed Nim 2.0+), use the following scoped test:
warning pragma) outside of any suppressed block.{.push warning: off.} and {.pop.}. The warning will still appear.--strictDefs to confirm if any suppressed hints are promoted to unsuppressible errors.Note: Please specify if you are using a version of Nim prior to 1.6, as diagnostic reporting mechanisms for macro expansions have evolved.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 22 Jul 2020, 16:03 UTC
Wrapping a macro call in {.push warning: off.} hides diagnostics that arise from the expanded code. The compiler treats the generated source as part of the same file, so warnings from the resulting statements are suppressed. However, diagnostics that are emitted while the macro’s own body is executed—such as an undeclared identifier inside the macro itself—are attached to the macro’s definition location and therefore bypass the outer suppression.
When a generic is instantiated after the {.pop.}, the compiler emits warnings at the instantiation point, outside the suppressed block, and they are not silenced. Likewise, --strictDefs promotes hints to errors; these errors are still reported because the pragma only filters warnings.
Because the macro expansion pipeline has changed in recent Nim releases, the exact moment diagnostics are produced can shift, so it’s good practice to run a quick test on the target compiler version.