All files / TRANSPILE/2-Plan ComplianceAnnotations.ts

100% Statements 7/7
100% Branches 0/0
100% Functions 4/4
100% Lines 7/7

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128                                                                    60x     60x             60x                                   11x                               34x                       101x                                                     4x                    
import type IComplianceAnnotation from "./types/IComplianceAnnotation";
 
/**
 * 2.2 Plan -- which safety-standard rule shaped a construct, and how that is
 * said in the generated C.
 *
 * CLAUDE.md makes this a C-Next standard, not a nicety:
 *
 *   Whenever codegen emits code whose shape is dictated by a safety standard
 *   ... rather than by the obvious/naive translation, it MUST emit an
 *   explanatory comment directly above the generated construct. ... The
 *   comment names the standard + specific rule and gives a short WHY (what the
 *   naive form would have done and which rule it violates).
 *
 * The generated C is the certification artifact, so an auditor has to be able
 * to trace each non-obvious construct back to the rule that shaped it -- and,
 * separately, to enumerate every rule the transpiler cites at all. Three sites
 * used to build these strings by hand, and one of them had drifted off the
 * house form: no trailing period, and a parenthetical naming the C-Next
 * construct rather than what the naive C would have done. Nothing could have
 * noticed, because the form was a convention in prose and the text was a string
 * literal three files apart.
 *
 * So the form is `render`'s, the rules are this table, and
 * `__tests__/ComplianceAnnotations.test.ts` holds both to CLAUDE.md's shape.
 *
 * Distinct from `MisraSuppressionUtils`, which emits `cppcheck-suppress`
 * directives -- a suppression tells a TOOL to stop reporting; an annotation
 * tells a READER why the code looks like this.
 * Adding a rule means adding a row; it cannot be added off-form.
 */
 
class ComplianceAnnotations {
  /** The only standard cited today. Kept explicit so a second one is visible. */
  private static readonly STANDARD = "MISRA C:2012";
 
  /** ADR-026 `forever` lowers to `for (;;)`. */
  static readonly FOREVER_LOOP: IComplianceAnnotation = {
    rule: "14.3",
    what: "infinite loop written as `for (;;)` for C-Next `forever`",
    why: "`while (1)` has a controlling expression with an invariant value, which the rule forbids",
  };
 
  /** ADR-029's generated init function needs a declaration before its definition. */
  static readonly INIT_PROTOTYPE: IComplianceAnnotation = {
    rule: "8.4",
    what: "declaration for the ADR-029 generated init function",
    why: "the definition has external linkage and would otherwise be undeclared",
  };
 
  /**
   * A slice copy unrolled to per-element writes.
   *
   * Only cited when an equivalent `memcpy` would genuinely violate the rule --
   * the source type is known and differs from the destination element type, so
   * the two pointer arguments would be incompatible. Matching types, an unknown
   * source type, or a single element cite nothing (#1081).
   */
  static sliceUnroll(
    destCType: string,
    srcCType: string,
  ): IComplianceAnnotation {
    return {
      rule: "21.15",
      what: "slice copy unrolled to per-element writes",
      why: `memcpy would pass incompatible pointer types: ${destCType}* vs ${srcCType}*`,
    };
  }
 
  /**
   * A float's bits reached through a union (ADR-007). Copying them into an
   * integer with `memcpy` would pass a float pointer beside an integer one,
   * which the rule forbids (#1760 review: the union carried no citation).
   */
  static floatBitsUnion(
    floatCType: string,
    bitsCType: string,
  ): IComplianceAnnotation {
    return {
      rule: "21.15",
      what: "float bits accessed through a union",
      why: `memcpy would pass incompatible pointer types: ${floatCType}* vs ${bitsCType}*`,
    };
  }
 
  /**
   * The one rendering of the house form,
   * `/* <Standard> Rule <N>: <what> (<why>). *\/`.
   */
  static render(annotation: IComplianceAnnotation): string {
    return (
      `/* ${ComplianceAnnotations.STANDARD} Rule ${annotation.rule}: ` +
      `${annotation.what} (${annotation.why}). */`
    );
  }
 
  /**
   * Every annotation this transpiler can emit.
   *
   * ## Its only caller is a test, deliberately
   *
   * That is the #1418 shape -- "a test-only caller counts as usage, so knip
   * reports clean on a method whose last production caller is gone" -- and this
   * branch deleted six methods that had it. So the difference is stated rather
   * than left for someone to rediscover: those six were duplicates of a live
   * sink, and deleting them removed a second way to do one thing. This one has
   * no production caller because enumerating the set is not something the
   * transpiler does while transpiling; it is what the tests hold to the house
   * form, and what answers "which rules does our codegen cite?" for someone
   * auditing the generated C.
   *
   * Without it the test would hardcode the list, and there would be two lists.
   * If a sweep proposes deleting this, the question to ask is whether the
   * assertion in `__tests__/ComplianceAnnotations.test.ts` still has a set to
   * assert over.
   */
  static all(): readonly IComplianceAnnotation[] {
    return [
      ComplianceAnnotations.FOREVER_LOOP,
      ComplianceAnnotations.INIT_PROTOTYPE,
      ComplianceAnnotations.sliceUnroll("uint8_t", "uint32_t"),
      ComplianceAnnotations.floatBitsUnion("float", "uint32_t"),
    ];
  }
}
 
export default ComplianceAnnotations;