Repository navigation
feat(maul): share check_nodiscard.py, which requires every internal bool marked - #124
Conversation
siracozmen01
left a comment
There was a problem hiding this comment.
Review at 2058b19: changes needed (1). Read, not run.
1. The indented two-line test fires on any indented line whose last word is bool, comments included. Problems refuses a line when re.match(r"^\s+.*\bbool\s*$", line) holds. That pattern does not require the line to look like a declaration. In a function body, a comment such as // the answer is a plain bool makes the check report "an indented bool declaration" and fail the library. So does a wrapped expression or argument list whose line happens to end with the word.
None of the five mains has such a line today (the body found no unread shapes). But a rule every library will carry should not fail on a comment. The fix is to give it the shape of the column-0 wrapped pattern: re.compile(r"^\s+" + specifiers + r"bool\s*$"), so only specifiers may come before bool. Alternatively, exclude //, /*, * and # the way unread does. A self-test case (" // returns a bool", False, 0) would pin it.
2. Column-0 non-declarations cannot reach unread. It needs a line that starts at column 0, does not start with whitespace, #, /, * or typedef, and contains bool <name>(.
- Macro continuations: these start with whitespace, or with
#for the#defineline. - Struct initializers and file-scope variables:
static bool s_x = F(1);,(bool)F(andbool (*fp)(all lackbool, whitespace, a name and then(. extern "C" {: it holds nobool. Only a one-lineextern "C" bool f(would be refused, and that is fail-closed on a real declaration.- Comments: excluded, as the self-test shows.
3. The two-line read cannot take a wrong name.
name_linetakes the identifier immediately before(at the first column of the very next line, which is the function's name.- Anything else on that line yields no match, and the
endsbranch then refuses the declaration: a blank line, a comment, a further macro (PP_NOINLINE Name(), a function pointer, or a variable (s_ready = false;, with no(). - The name line itself matches none of the patterns, so it is not counted twice.
4. The renamed edits keep every caller's check.
- All ten functions are
static, so their callers are in the same template file and identical in every library that carries it. - With
@PP@_NODISCARDthe gcc-14 and clang-20 builds at-Werrorwould refuse any dropped result. They pass in the synced maul-ui (inflate.c) and maul-tween (elementary.c,elementary_float.c) trees, so no caller drops one in any library. - The added
#include "@LIB@/base.h"reaches each library's own header through its include directory.
The prefix read (^#define ([A-Z0-9]+)_NODISCARD) and the part directories are covered by the self-test's tree. The conventions line states the uniform rule and names the check. The title fits.
siracozmen01
left a comment
There was a problem hiding this comment.
Review of the delta 2058b19 to c457f02: ready. Read, not run.
The fix is in, and only check_nodiscard.py changed. The indented test is now one pattern, ^\s+ + specifiers + bool(?:\s+(\w+)\s*\(|\s*$), so only specifiers may stand before bool, and bool must be followed by a name and ( or end the line.
What it refuses: an indented one-line declaration, and an indented static bool with the name on the next line, which the self-test keeps at 1.
What it does not touch:
- a comment ending in "bool" (
//is no specifier); bool done;andbool ok = f(1);, where no(follows the name;boolValue(x), whereboolis not followed by whitespace or the line's end.
The two new self-test cases pin the comment shapes. The rest is as reviewed at 2058b19.
## Problem v0.0.53's `check_nodiscard.py` reports two unmarked bool functions in the shared `maul/renamed/src/cpu.h`: `@P@IsCpuBackendSupported` and `@P@CheckCpu`. #124 marked the other renamed files but missed these, because the `@P@` placeholder hid their names from its scan. maul2d, maul3d and maul-anim carry cpu.h and cannot pass the check without editing a family file. ## Change `cpu.h` includes `@LIB@/base.h` and marks both declarations `@PP@_NODISCARD`. A public `base.h` that also declares them (all three libraries do, unmarked) keeps its own declaration; the mark on this later one makes a dropped result warn inside the library. ## Verification Synced from this branch into scratch trees of maul2d, maul3d and maul-anim: - `src/cpu.h` passes `clang-format --dry-run -Werror`, and `src/cpu.c` builds with gcc-14 and clang-20 at `-std=c23 -Wall -Wextra -Wpedantic -Werror`; - `tools/check_nodiscard.py` no longer reports cpu.h; - a call that drops `maniCheckCpu`'s result warns under gcc-14; - every call of the two functions in the three libraries (src, tests, bench) uses the result. Closes #125
Problem
An internal function returning
booleither refuses or answers, and a caller that drops it goes on past a refusal or with an out value left unset. maul-locale now marks every such function and checks that with its owntools/check_nodiscard.py(maul-locale #489). The family states no such rule and shares no check, and the shared sources undermaul/renamed/srccarry ten unmarked static bools that every library carrying them would fail on.Change
maul/files/tools/check_nodiscard.py, lifted from maul-locale's and made family-wide:<PP>_NODISCARDabase.hunderinclude/(or a listed part'sinclude/) defines;src/and eachtools/source-dirs.txtpart'ssrc/, subdirectories included: every bool function in a header, every static one in a source file;[[maybe_unused]]),static,inlineandexternbeforebool;boolmay end its line with the name first on the next, the shape clang-format writes for long declarations;bool) is an error naming its place, so the check never passes what it did not read;--self-testcovers every shape, a part directory and a nested header.maul-conventions.mdstates the rule and lists the check.maul/renamed/src:inflate.cmarks Build, Codes, Stored, Fixed, ReadLengths and Dynamic;elementary.candelementary_float.cmark PowSpecial(F) and Atan2Special(F) and include@LIB@/base.h. Every caller already checks each one.A library takes it by syncing, adds the check to its
check.shrules step, and marks its own bool functions in the same pull request.Verification
--self-testpasses.[[maybe_unused]] static MUI_NOINLINE bool/muiActMarked(is one).inflate.cand maul-tween'selementary.candelementary_float.cpassclang-format --dry-run -Werrorand build with gcc-14 and clang-20 at-std=c23 -Wall -Wextra -Werror; maul-tween's tree passestools/check_source.py.Closes #123