packages feed

hs-bindgen-1.0.0.0: CHANGELOG.md

# Revision history for hs-bindgen

## 1.0.0.0 -- 2026-10-08

### Breaking changes

* Drop support for GHC 9.2.
* Bindings generated by earlier versions do not compile against the new
  `hs-bindgen-runtime`; regenerate them. See the `hs-bindgen-runtime`
  changelog.
* Macros defined on the command line are no longer passed to Clang as `-D`
  arguments but are *root directives*: an ordered list of `#include` and
  `#define` directives. The root header is rendered from this list, and the
  generated C wrapper source starts with the same rendering, so that binding
  generation and binding compilation agree by construction. The wrapper
  translation unit of a module therefore includes every main header.
  Previously, `-D FOO` had to be stated twice: once for `hs-bindgen` and once
  as `ghc-options: -optc-DFOO` in the `.cabal` file. See [issue
  #2214][is-2214] and the [C stages][manual-c-stages] manual page.
  * The CLI option `-D`/`--define-macro` is replaced by `--hash-define NAME
    VALUE`. The order of `--hash-define` and `HEADER` arguments matters.
    `--hash-define` takes *two* arguments: `-DFOO` becomes `--hash-define FOO
    1`; an empty replacement list is `--hash-define FOO ''`.
  * `ClangArgsConfig.defineMacros` is removed. In Template Haskell mode, use
    the new `hashDefine :: String -> String -> BindgenM ()` next to
    `hashInclude`. This is `#define` syntax, not `-D` syntax: `hashDefine
    "FOO" ""` is `#define FOO`, `hashDefine "FOO" "1"` is `#define FOO 1`.
  * As before, raw `-D` options passed via `argsBefore`/`argsInner`/`argsAfter`
    or `BINDGEN_EXTRA_CLANG_ARGS` reach binding generation only, not the
    compilation of the C wrapper.
* Macros defined by `-D` Clang options or by `#define` root directives are now
  declarations. See [issue #2280][is-2280].
  * They are not in any header, so the default selection predicate does not
    select them; program slicing selects the ones a selected declaration uses.
  * Consider `struct S { T x; };` with `-DT=int`. Previously, `x` was a
    `CInt`. Now, `S` is deselected without program slicing, just as if `T`
    were defined in a header that is not a main header; with program slicing,
    `x` has the macro type `T`.
  * `--select-all` selects all of these macros, including those the Clang
    driver defines itself, such as `__GCC_HAVE_DWARF2_CFI_ASM`. So does
    `--select-by-decl-name` when its pattern matches their names. See also the
    new selection predicate `--select-from-all-headers`.
  * Generated binding specifications do not list these macros.
* The `IncludeDir` data constructors have been renamed: `Dir` → `AbsDir` and
  `Pkg` → `PkgDir`. Their paths are now checked in Template Haskell mode: a
  relative `AbsDir` path warns (it is resolved against the working directory of
  the compiler invocation), and an absolute `PkgDir` path is an error (the
  package root would be discarded). See [issue #2217][is-2217].
* The `SelectPredicate` type has been renamed to `SelectionPredicate`, and the
  `selectPredicate` field of `Config_` has been renamed to
  `selectionPredicate`.
* The `--select-by-header-path` regex now matches against canonical absolute
  paths. See [issue #2236][is-2236].
* The `--path-style` CLI option and the corresponding `PathStyle` type and
  `haddockPathStyle` field of `Config_` have been removed. They had no effect:
  generated Haddock comments show the header path as written in the `#include`
  directive. See [issue #2266][is-2266].
* The `--log-show-time` CLI option has been removed. Trace output no longer
  includes timestamps.
* CLI exit codes have changed. Exit code 2 is now used for CLI usage errors;
  a failed call to `libclang` now exits with code 3 (previously 2), and an
  error in `hs-bindgen` with code 4 (previously 3). See the invocation section
  of the manual.
* The `LLVM_CONFIG` environment variable is no longer used to locate
  `llvm-config`. Set `LLVM_PATH`, or configure `PATH` so that the desired
  `llvm-config` is found.
* Generated field names referencing anonymous structs and unions are now
  prefixed with `anon'`. This highlights that the field is generated by
  `hs-bindgen`; the tick ensures that the name cannot clash with a C field,
  since ticks are not allowed in C identifiers. Since anonymous structs and
  unions are named after the generated fields, these names now also include an
  `anon'` infix. Code rarely needs to refer to these names: the fields of an
  anonymous struct or union can be accessed as indirect fields of the
  enclosing struct or union (see below). See [issue #2064][is-2064] and [PR
  #2070][pr-2070].
* Tagged types that would clash with the name of a typedef that refers to them
  are now disambiguated with a `_struct`/`_union`/`_enum` suffix (mirroring the
  C keyword) instead of `_Aux`. Clash detection now also looks through arrays,
  blocks, and function types (argument and result types), not just pointers,
  so e.g. `typedef struct {…} foo[10];` no longer produces clashing names.
  Qualifiers (e.g. `const`) are treated as transparent, so `typedef const
  struct {…} foo;` is now squashed like its unqualified counterpart. This
  renames affected generated identifiers. See [issue #1445][is-1445].
* Derived names (data constructors, record fields, union getters and setters,
  enum constants, and `_Aux` types for flexible array members and function
  pointers) are now checked for collisions. A declaration whose derived names
  collide is deselected with a warning instead of producing uncompilable
  Haskell. In particular, under `OmitFieldPrefixes`, a struct with two fields
  that mangle to the same Haskell name is deselected. See [issue
  #1432][is-1432].
* Modules generated under `OmitFieldPrefixes` now enable `NoFieldSelectors` (in
  addition to `DuplicateRecordFields`). No top-level field selector is emitted,
  so an unprefixed field name can no longer clash with a non-field declaration
  of the same name; fields are accessed via `HasField`/record dot syntax.
* Remove the generated union getters and setters (e.g. `get_u_c`). Use the new
  `get` and `set` functions from `hs-bindgen-runtime` instead. See [issue
  #2060][is-2060] and [PR #2091][pr-2091].
* Character literal macros are now translated to `CChar` (previously
  `CharValue` from `c-expr-runtime`), and string literal macros to a strict
  `ByteString` (previously `(Ptr CChar, Int)`). Multi-character literal macros
  (e.g. `#define X 'ab'`) are no longer supported, as their value is
  implementation-defined.
* The types used in `foreign import` declarations (FFI types) have been
  overhauled. Previously, every argument and result type was reduced to a
  primitive type with a fixed size, which made the generated bindings less
  portable than necessary. See the [FFI types][manual-ffi-types] manual page
  and [PR #2267][pr-2267].
  * An external binding specification can (and should) specify the FFI type of
    a Haskell type: a module and a type that may appear in a `foreign import`
    when that module is in scope. Generated `foreign import`s use the FFI type,
    and convert from and to the Haskell type with `toFFIType`/`fromFFIType` of
    the `HasFFIType` class.
  * `HasFFIType` instances are now only generated for types that can be used in
    `foreign import` argument and result positions.
  * `HasFFIType` is an open class: users can write instances, e.g. for types
    referenced by external binding specifications.
* In external binding specifications, the class name `HasField` now records
  that a type has the usual `HasField` instances for the fields of record
  datatypes. Specifications that use `HasField` for the `HasField` instances of
  the pointer manipulation API must rename it to `HasFieldPtr`. See [PR
  #2094][pr-2094].
* The name mangler reserves the names that generated modules import
  unqualified from the `Prelude`, each in its namespace. See [issue
  #2287][is-2287].
  * `String` and `fmap` are now reserved: a C type `string` becomes `String'`,
    a C function `fmap` becomes `fmap'`.
  * `Void`, `FiniteBits` and `showsPrec` are no longer reserved: a C type
    `Void` becomes `Void`, not `Void'`.
  * Reserved names apply only in their own namespace: a C enumeration constant
    `Eq` becomes the pattern `Eq`, not `Eq'`. The names of `Foreign.C.Types`,
    such as `CInt`, remain reserved for types and constructors alike.

### New features

* Macro handling has been overhauled. See [PR #1862][pr-1862].
  * Type-like macros (e.g. `#define A int`) are now parsed and typechecked
    together with value-like macros (e.g. `#define FOO 1`) using `c-expr-dsl`,
    rather than `language-c`, and translated directly to Haskell types. See
    [issue #1953][is-1953].
  * Names in macro bodies are resolved against all declarations in the
    translation unit.
  * Program slicing follows the dependencies of macros: selecting a macro also
    selects the declarations it uses.
  * When reparsing a declaration that uses macros, only the macros Clang
    expanded *in that declaration* are substituted.
  * Macro expansions in global variable declarations are supported. See [issue
    #831][is-831].
* Declarations may use type macros together with other macros, including
  macros that `hs-bindgen` cannot translate, such as macros expanding to
  attributes. The type macros are reflected in the generated bindings, and the
  other macros are expanded as Clang expands them. Previously, type macros were
  only supported in bindings that used no other macros at all.
  Support is decided per declaration: it works as long as no macro the
  declaration expands is ambiguous, that is, neither the macro nor any macro it
  depends on has conflicting redefinitions (see below). See [issue
  #1225][is-1225], [issue #2012][is-2012], [PR #1892][pr-1892] and [PR
  #2034][pr-2034].
* Benign macro redefinitions now collapse into one declaration, and do not
  make the expansion of the macro ambiguous. A macro redefinition is benign if
  and only if all definitions have the same name, parameter list and
  replacement list (white space within the replacement list is ignored), and
  none of the macros they depend on, directly or indirectly, has conflicting
  redefinitions; all other redefinitions conflict. In particular, repeating a
  definition word for word conflicts if a macro it uses is redefined
  differently in between. We generate no bindings for a macro with conflicting
  redefinitions. For any repeated
  declaration, macro or not, we keep the definition in a main header, or the
  first if none is in a main header. A declaration first defined in an
  included header and repeated in a main header is therefore now selected by
  the default selection predicate. See [issue #2264][is-2264] and [PR
  #2281][pr-2281].
* In Template Haskell mode, the macro language (how macro bodies are parsed,
  typechecked and translated) can be chosen:
  `HsBindgen.TH.withHsBindgenMacroLang` takes the macro language as an
  argument, while `withHsBindgen` uses the default. `HsBindgen.Macro` provides
  `cExpr` (the default), `empty` (recognises no macros; Clang's own expansions
  are used), and `raw` (every macro becomes a `HsBindgen.Runtime.Macro.Raw
  String` value holding its name, parameter list and token spellings).
  The macro language argument is a function of the C standard, which
  `withHsBindgenMacroLang` detects. The macro language interface is opaque, so
  custom macro languages are not yet supported; they will be once the
  `hs-bindgen` library API is finalised (see [issue #1003][is-1003]). See
  [issue #2242][is-2242] and [issue #2243][is-2243].
* A new CLI option `--parse-empty-macros` (`EmptyMacros` with
  `ParseEmptyMacros`/`DoNotParseEmptyMacros` in Template Haskell mode) passes
  macros with an empty replacement list on to the macro language. `raw` can
  translate such macros. The default `cExpr` has no expression to translate and
  declines them; they are reported like any other macro that failed to
  translate. By default, empty macros are not parsed at all, since include
  guards have this shape. See [issue #2246][is-2246].
* `hs-bindgen` now emits a single, default-visible summary line reporting how
  many selected macros it failed to translate, e.g. `14 macros failed to
  translate; use --log-enable-macro-warnings for details`. Previously these
  failures were only logged at `Info` level and hidden at the default
  verbosity, giving the impression that macros were not translated at all. See
  [issue #2185][is-2185].
* A new CLI option `--select-from-all-headers` (`SelectHeader FromAllHeaders`
  in Template Haskell mode) selects every declaration in any header, main or
  included. Unlike `--select-all`, it does not select macros defined by `-D`
  Clang options or by root directives. See [issue #2280][is-2280].
* Extract Haddock documentation from C headers using Doxygen. When the
  `doxygen` binary is available on `PATH`, `hs-bindgen` invokes it to parse
  structured documentation comments (Javadoc/Doxygen-style `/** ... */`) and
  translates them into Haddock comments on the generated bindings. If `doxygen`
  is not found, `hs-bindgen` warns and generates metadata-only comments (source
  location and C name).
* Mirror Doxygen `@defgroup` sections (including nested `@ingroup` groupings)
  as Haddock section headers in the export lists of generated modules.
* The `hs-bindgen-cli info doxygen` subcommand dumps the parsed Doxygen
  comments.
* Generate class instances for field access and zero values of structs,
  unions and newtypes:
  * `GHC.Records.Compat.HasField` instances for struct fields, union fields,
    and the fields of generated newtypes (for typedefs, enums, and macro
    types), with Haddock comments;
  * `GHC.Records.HasField` instances for union fields;
  * `HsBindgen.Runtime.Struct.IsStruct` instances for structs;
  * `HsBindgen.Runtime.Union.IsUnion` instances for unions.

  With `OverloadedRecordUpdate` (see `HsBindgen.Runtime.Overloading`), struct
  and union values can be constructed by record updates of the zero value of
  `IsStruct` or `IsUnion`. This is particularly useful for unions, which are
  opaque datatypes, and combines with indirect fields (see below).

  See [issue #2059][is-2059], [issue #2060][is-2060], [issue #2083][is-2083],
  [issue #2121][is-2121], [PR #2075][pr-2075], [PR #2087][pr-2087], [PR
  #2091][pr-2091], [PR #2150][pr-2150] and [PR #2164][pr-2164].
* Generate `HasField` instances for indirect fields, both for values and, for
  the pointer manipulation API, for pointers. Indirect fields are fields of
  anonymous structs and unions that can be accessed as if they were fields of
  the enclosing struct or union, as in C. With `OverloadedRecordDot`, a field
  of an anonymous union inside a struct can thus be read from a value of, or a
  pointer to, the struct directly, without naming the generated union type.
  See [issue #2061][is-2061] and [PR #2136][pr-2136].
* Support bit-fields in unions. See [issue #1253][is-1253].
* Generate `_Aux` newtypes for function types that are indirectly referenced by
  `typedef`s. Previously these newtypes were only generated when function types
  were indirectly referenced through pointers. Now any type of indirection is
  supported, such as arrays, qualifiers, and blocks. Likewise, generate
  `ToFunPtr` and `FromFunPtr` instances for all nested function types,
  including those nested in global variables and typedefs. See [issue
  #1520][is-1520] and [PR #2068][pr-2068].
* Generate a `StaticSize` instance for `emptydata` types whose underlying C
  type is complete (a struct, union, or enum with a known size and alignment,
  or a typedef of one), so that callers can allocate the type from Haskell even
  though its fields are hidden. Types that are opaque in C (such as forward
  declarations) get no instance. See [issue #2014][is-2014].
* The C type specification of binding specifications gains an `enum` key with
  values `open` (default) or `closed`. For a closed `enum`, we generate a
  `COMPLETE` pragma for the declared patterns, so that GHC considers a match
  on all of them exhaustive. See [issue #2101][is-2101].
* In Template Haskell mode, external types referenced via external binding
  specifications that are not in scope now produce a helpful compile error
  suggesting the missing import.
* A new CLI option `--color WHEN` controls ANSI colours in diagnostics, where
  `WHEN` is `always`, `auto` (default: detect terminal support), or `never`.
  See [issue #2166][is-2166].
* A new CLI option `--log-squashed-as-info` (and matching
  `CustomLogLevelSetting` constructor `MakeMangleNamesSquashedInfo`) demotes
  the `select-mangle-names-squashed` trace from `Notice` to `Info`, so the
  per-typedef squash messages no longer appear at the default verbosity. See
  [issue #1574][is-1574].
* A new CLI option `--log-as-error-bugs` turns bug-level trace messages into
  errors. This is useful when `hs-bindgen` is used in a CI pipeline.
* The `hs-bindgen-cli info include-graph` command gained a `--toposort` flag
  that outputs the headers as a topologically sorted list (one per line, each
  header after the ones it `#include`s) instead of a Mermaid graph. Respects
  `--include`/`--exclude` and `--show-paths`. See [issue #2080][is-2080].
* Support LLVM/Clang 23. See [issue #2235][is-2235].

### Minor changes

* The `c-expr-dsl` and `c-expr-runtime` libraries have been extracted into
  their own repository ([well-typed/c-expr](https://github.com/well-typed/c-expr))
  and are consumed from Hackage.
* Print types without redundant parentheses, and type operators with infix
  notation, in generated bindings. See [issue #1790][is-1790], [issue
  #1715][is-1715] and [PR #1917][pr-1917].
* `HsBindgen.TH` now also exports `BindgenM` (opaque).
* `hs-bindgen-cli info builtin-macros` no longer lists macros defined by `-D`
  Clang options, including the ones the Clang driver adds itself. See [issue
  #2280][is-2280].
* Trace messages capture call stacks where they are created rather than where
  they are emitted, making `--log-show-call-stack` output point at the code
  that produced the message.

### Bug fixes

* Generated modules no longer clash with `Prelude` names. Previously, C
  declarations such as `typedef int Maybe` or `enum { LT, EQ, GT }` resulted in
  ambiguous names. See [issue #2287][is-2287].
* Object-like macros whose replacement list starts with `(`, such as
  `#define G (x, y) x + y`, are no longer parsed as function-like macros. A
  macro is function-like only if there is no white space between its name and
  the opening parenthesis.
* A function-like macro whose parameter is spelled like a C keyword, such as
  `#define F(bool) bool`, is no longer dropped. Such a parameter shadows the
  keyword in the replacement list: the body of `#define F(bool) bool` is the
  parameter, not the type.
* A header that uses a macro defined by a `-D` Clang option, and then redefines
  it, no longer makes `hs-bindgen` panic. The redefinition is now a conflict,
  like two differing definitions in a header. See [issue #2280][is-2280].
* Fix the parsing of primitive types in declarations that involve macro
  expansions. The bug would, for example, cause `long long int` to be parsed as
  `long int` in some cases. See [issue #1685][is-1685] and [PR #1921][pr-1921].
* Fix the reparser to ignore storage class specifiers, function specifiers, and
  attribute specifier sequences. Previously, macro-using declarations carrying
  any of these failed to reparse and silently fell back to the un-reparsed
  type, dropping macro typedef names from generated bindings. See [issue
  #1891][is-1891] and [PR #1955][pr-1955].
* Prevent confusing info-level messages for reparse errors involving
  declarations that contain nested declarations. For example, for a nested
  declaration such as `typedef struct { MyInt x; } * foo;` where `MyInt` is a
  macro type, a message would be traced that `foo` could not be reparsed, even
  though the struct field `x` is still reparsed successfully. See [issue
  #1382][is-1382] and [PR #2021][pr-2021].
* Unnamed declarations originating from the same macro expansion no longer
  make `hs-bindgen` panic. Their identifiers now include a hash of the
  declaration, which makes them unique on all supported LLVM versions. See
  [issue #1860][is-1860] and [issue #2210][is-2210].
* Support untagged structs, unions and enums that are indirectly referenced
  by global variables. For example, `struct { int x; } var;` was
  previously supported but `struct { int x; } * var;` or `struct { int x; }
  var[];` would cause a panic. See [PR #2017][pr-2017].
* External binding specifications now match correctly when the same header is
  reached by different `#include` spellings (e.g. `../core.h` vs `core.h`).
  Identity comparisons use canonical paths instead of the Clang-reported
  filename, which depends on include order. See [issue #2236][is-2236].
* Declarations using `_Float16`, `__fp16`, `__bf16`, or `__ibm128` now fail to
  parse with an unsupported-feature warning, instead of being reported as a
  bug in `hs-bindgen`. See [issue #2230][is-2230].
* Declarations using SIMD vector types now fail to parse with an
  unsupported-feature warning. See [issue #2198][is-2198].
* Declarations with unexposed types (such as the type of `malloc` with
  LLVM/Clang 22) now fail to parse with a warning.
* Silently ignore `__declspec(dllimport)` and `__declspec(dllexport)`
  attributes when parsing function, variable, and enum declarations.
  Previously, these triggered a `Bug`-level `Unexpected cursor kind` trace on
  Windows for every CRT declaration carrying `__declspec(dllimport)`. See
  [issue #1910][is-1910].
* `_Static_assert` declarations are now ignored, rather than reported as an
  unexpected cursor kind.
* Generated modules now enable every language extension they need, such as
  `FlexibleInstances` and `ForeignFunctionInterface`, so that they compile
  with `Haskell2010` or `Haskell98` as the default language. Previously, some
  of these were covered only implicitly by `GHC2021`.
* Stop emitting the `CApiFFI` language pragma in generated modules that do not
  use the `capi` calling convention. See [issue #1868][is-1868].
* Fix reversed order of Haddock documentation in Template Haskell mode. See
  [issue #1832][is-1832] and [PR #1895][pr-1895].
* In Template Haskell mode, traces are no longer prefixed with "Template
  Haskell error: ", which made warnings look like errors. All traces now go to
  `stderr` (previously, only warnings and errors did). See [issue
  #2216][is-2216].
* Fix duplicated `--safe`, `--unsafe`, and `--pointer` options in the
  `preprocess --help` output. See [issue #2010][is-2010].

[manual-c-stages]: https://github.com/well-typed/hs-bindgen/blob/main/manual/low-level/usage/c-stages.md
[manual-ffi-types]: https://github.com/well-typed/hs-bindgen/blob/main/manual/low-level/translation/ffi-types.md
[is-831]: https://github.com/well-typed/hs-bindgen/issues/831
[is-1003]: https://github.com/well-typed/hs-bindgen/issues/1003
[is-1225]: https://github.com/well-typed/hs-bindgen/issues/1225
[is-1253]: https://github.com/well-typed/hs-bindgen/issues/1253
[is-1382]: https://github.com/well-typed/hs-bindgen/issues/1382
[is-1432]: https://github.com/well-typed/hs-bindgen/issues/1432
[is-1445]: https://github.com/well-typed/hs-bindgen/issues/1445
[is-1520]: https://github.com/well-typed/hs-bindgen/issues/1520
[is-1574]: https://github.com/well-typed/hs-bindgen/issues/1574
[is-1685]: https://github.com/well-typed/hs-bindgen/issues/1685
[is-1715]: https://github.com/well-typed/hs-bindgen/issues/1715
[is-1790]: https://github.com/well-typed/hs-bindgen/issues/1790
[is-1832]: https://github.com/well-typed/hs-bindgen/issues/1832
[is-1860]: https://github.com/well-typed/hs-bindgen/issues/1860
[is-1868]: https://github.com/well-typed/hs-bindgen/issues/1868
[is-1891]: https://github.com/well-typed/hs-bindgen/issues/1891
[is-1910]: https://github.com/well-typed/hs-bindgen/issues/1910
[is-1953]: https://github.com/well-typed/hs-bindgen/issues/1953
[is-2010]: https://github.com/well-typed/hs-bindgen/issues/2010
[is-2012]: https://github.com/well-typed/hs-bindgen/issues/2012
[is-2014]: https://github.com/well-typed/hs-bindgen/issues/2014
[is-2059]: https://github.com/well-typed/hs-bindgen/issues/2059
[is-2060]: https://github.com/well-typed/hs-bindgen/issues/2060
[is-2061]: https://github.com/well-typed/hs-bindgen/issues/2061
[is-2064]: https://github.com/well-typed/hs-bindgen/issues/2064
[is-2080]: https://github.com/well-typed/hs-bindgen/issues/2080
[is-2083]: https://github.com/well-typed/hs-bindgen/issues/2083
[is-2101]: https://github.com/well-typed/hs-bindgen/issues/2101
[is-2121]: https://github.com/well-typed/hs-bindgen/issues/2121
[is-2166]: https://github.com/well-typed/hs-bindgen/issues/2166
[is-2185]: https://github.com/well-typed/hs-bindgen/issues/2185
[is-2198]: https://github.com/well-typed/hs-bindgen/issues/2198
[is-2210]: https://github.com/well-typed/hs-bindgen/issues/2210
[is-2214]: https://github.com/well-typed/hs-bindgen/issues/2214
[is-2216]: https://github.com/well-typed/hs-bindgen/issues/2216
[is-2217]: https://github.com/well-typed/hs-bindgen/issues/2217
[is-2230]: https://github.com/well-typed/hs-bindgen/issues/2230
[is-2235]: https://github.com/well-typed/hs-bindgen/issues/2235
[is-2236]: https://github.com/well-typed/hs-bindgen/issues/2236
[is-2242]: https://github.com/well-typed/hs-bindgen/issues/2242
[is-2243]: https://github.com/well-typed/hs-bindgen/issues/2243
[is-2246]: https://github.com/well-typed/hs-bindgen/issues/2246
[is-2264]: https://github.com/well-typed/hs-bindgen/issues/2264
[is-2266]: https://github.com/well-typed/hs-bindgen/issues/2266
[is-2280]: https://github.com/well-typed/hs-bindgen/issues/2280
[is-2287]: https://github.com/well-typed/hs-bindgen/issues/2287
[pr-1862]: https://github.com/well-typed/hs-bindgen/pull/1862
[pr-1892]: https://github.com/well-typed/hs-bindgen/pull/1892
[pr-1895]: https://github.com/well-typed/hs-bindgen/pull/1895
[pr-1917]: https://github.com/well-typed/hs-bindgen/pull/1917
[pr-1921]: https://github.com/well-typed/hs-bindgen/pull/1921
[pr-1955]: https://github.com/well-typed/hs-bindgen/pull/1955
[pr-2017]: https://github.com/well-typed/hs-bindgen/pull/2017
[pr-2021]: https://github.com/well-typed/hs-bindgen/pull/2021
[pr-2034]: https://github.com/well-typed/hs-bindgen/pull/2034
[pr-2068]: https://github.com/well-typed/hs-bindgen/pull/2068
[pr-2070]: https://github.com/well-typed/hs-bindgen/pull/2070
[pr-2075]: https://github.com/well-typed/hs-bindgen/pull/2075
[pr-2087]: https://github.com/well-typed/hs-bindgen/pull/2087
[pr-2091]: https://github.com/well-typed/hs-bindgen/pull/2091
[pr-2094]: https://github.com/well-typed/hs-bindgen/pull/2094
[pr-2136]: https://github.com/well-typed/hs-bindgen/pull/2136
[pr-2150]: https://github.com/well-typed/hs-bindgen/pull/2150
[pr-2164]: https://github.com/well-typed/hs-bindgen/pull/2164
[pr-2267]: https://github.com/well-typed/hs-bindgen/pull/2267
[pr-2281]: https://github.com/well-typed/hs-bindgen/pull/2281

## 0.1.0-alpha2 -- 2026-03-27

### Breaking changes

* Rename option `--enable-record-dot` to `--omit-field-prefixes`, which is more
  to the point.
* Occurrences of the `CFieldType`/`CBitfieldType` type families in
  class instance heads are now replaced by their definition.
* `--enable-blocks` CLI option renamed to `-fblocks`, matching `clang`
* Macro declarations are now handled internally using a separate namespace.
  Binding specifications and selection predicates now refer to macros using
  `macro`.  For example, a macro named `foo` is referred to as `macro foo`.
* For C function *declarations* that take arrays as arguments, generate Haskell
  function declarations that take pointers to their corresponding array
  *elements* as arguments. This uses the `Elem` associated type class from the
  new `IsArray` class. See [PR #1712][pr-1712].
* For C function *types* (.e.g, `typedef`s) that take arrays as arguments,
  generate Haskell function types (.e.g, `newtype`s) that take pointers to their
  corresponding array *elements* as arguments. This uses the `Elem` associated
  type class from the new `IsArray` class. See [PR #1712][pr-1712].
* Parse predicates have been removed. Now, `hs-bindgen` always parses and
  reifies all declarations, reducing code complexity and cognitive overhead
  imposed on users. To migrate, remove `--parse-*` command line client options,
  or the parse-related configuration option when using Template Haskell model.

### New features

* The `info include-graph` sub-command has received new options: `--include
  PCRE`, and `--exclude PCRE` allow fine-tuned choice of headers to include or
  exclude from the include graph; `--simple` reduces include graph verbosity,
  for example, by removing edge labels.
* Generate explicit export lists in preprocessor-generated modules, hiding
  internal `hs_bindgen_` helper bindings from the public API and documentation
  ([#76](https://github.com/well-typed/hs-bindgen/issues/76)). Export items
  are module-qualified (e.g. `Example.myFunc`) to avoid ambiguity with
  Prelude names.
* The command line client has a new `internal frontend` sub-command. It takes a
  `--pass` option (e.g. `internal frontend --pass select`), dumping the result
  of the provided frontend pass. Defaults to `adjust-types` (the final pass)
  when omitted.
* Add `--post-qualified-imports` flag to generate post-qualified imports
  (`import Data.Proxy qualified`) instead of pre-qualified imports. This adds
  the `ImportQualifiedPost` language extension to generated modules.
* Support top-level untagged structs and enums as global variables
  (e.g., `struct { int x; int y; } point;`). The untagged type is named
  after the global variable. Extern untagged declarations
  (e.g., `extern struct { .. } config;`) are rejected as unusable.
* Generate an `IsArray` instance for each newtype of a type with an `IsArray`
* Support unnamed bit-field declarations, used for padding.
* Generate bindings for nested struct and union declarations even if we failed
  to generate bindings for the enclosing struct or union. See [PR
  #1849][pr-1849].
* Generate bindings for nested anonymous structs and unions. See [PR
  #1839][pr-1839] and [PR #1869][pr-1869].

### Minor changes

* Support `language-c` 0.9.x through 0.10.2
  ([#1662](https://github.com/well-typed/hs-bindgen/issues/1662)).
* Re-export all global definitions used by `hs-bindgen` generated code from
  `hs-bindgen-runtime`. This may affect required packages when using
  `hs-bindgen` generated code. In particular, the packages `ghc-prim` and
  `primitive` are not required by `hs-bindgen` generated code anymore.
* Improve and disambiguate delayed parse trace messages.
* Improve error handling in `hs-bindgen` frontend, see [issue #1009][is-1009]

### Bug fixes

* Fix generation of documentation for record fields in Template Haskell mode
  with `OmitFieldPrefixes`. Previously, duplicate record fields induced "ambiguous
  occurrence" errors. This fix is only available for GHC versions 9.8 and newer.
  For older versions of GHC, we deactivated creation of documentation for record
  fields in Template Haskell mode.
* Generate bindings for `static` (non-`const`) declarations. Previously these
  were rejected as an unsupported, even though the duplicate-symbols warning
  suggested using `static`
  ([#1769](https://github.com/well-typed/hs-bindgen/issues/1769)).
* Wrap function names in parentheses in generated C wrappers (`(erf)(x)`
  instead of `erf(x)`) to prevent function-like macro expansion when a macro
  shadows the function name.
* Fix incorrect enum constant values for enums with unsigned underlying types
  (e.g. `enum : uint8_t`). Values above the signed range (such as 128 or 255
  for `uint8_t`) were incorrectly stored as negative numbers because
  `hs-bindgen` used the signed libclang API.
* Include `FunPtr` for macro-defined newtypes. See [PR #1711][pr-1711].
* Fix a panic that occurred in some cases when generating `_Aux` newtypes for
  function pointers. See [issue #1694][is-1694] and [PR #1724][pr-1724].
* Fix a panic that occurred when the argument to a `#include` is a macro. In
  Haddock documentation of declarations in the included header, we just
  document the filename of the header.
* Fix `--create-output-dirs` not creating directories for `--gen-binding-spec`
  output paths. See [issue #1806][is-1806].
* Skip functions whose parameters reference struct/union declarations that
  will not be visible outside of the function, including both forward
  references and inline definitions. This could indicate a missing `#include`
  in the C header. Previously, forward references caused a panic in
  `MangleNames`; now they are skipped with a warning.

[is-1009]: https://github.com/well-typed/hs-bindgen/issues/1009
[is-1694]: https://github.com/well-typed/hs-bindgen/issues/1694
[is-1806]: https://github.com/well-typed/hs-bindgen/issues/1806
[pr-1711]: https://github.com/well-typed/hs-bindgen/pull/1711
[pr-1712]: https://github.com/well-typed/hs-bindgen/pull/1712
[pr-1724]: https://github.com/well-typed/hs-bindgen/pull/1724
[pr-1839]: https://github.com/well-typed/hs-bindgen/pull/1839
[pr-1849]: https://github.com/well-typed/hs-bindgen/pull/1849
[pr-1869]: https://github.com/well-typed/hs-bindgen/pull/1869

## 0.1.0-alpha -- 2026-02-06

* First public pre-release.