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.