TIP 748: Use 'bool' in public API

Login
Bounty program for improvements to Tcl and certain Tcl packages.
 Author:         Jan Nijtmans <jan.nijtmans@gmail.com>
 State:          Draft
 Type:           Project
 Tcl-Version:    9.1
 Vote:           Pending
 Created:        05-Feb-2026
 Keywords:       bool
 Tcl-Branch:     tip-748

Abstract

This TIP proposes to add change all public functions which return a int which is actually a bool, to change the return type to bool.

Rationale

Using a bool has the advantage that the compiler can optimize the code more, because there are only 2 possible values. For int's this assumtion cannot be made.

Specification

For compilers needing it, #include &lt;stdbool.h&gt; will be included in tcl.h. In conforming C23 compilers, bool is a new keyword which can be used without any extra header file. In time, the need for this extra header file will disappear.

The following funtions are changed, returning a bool:

  • Tcl_IsShared()
  • Tcl_AsyncReady()
  • Tcl_IsSafe()
  • Tcl_UniCharIsAlnum()
  • Tcl_UniCharIsAlpha()
  • Tcl_UniCharIsDigit()
  • Tcl_UniCharIsLower()
  • Tcl_UniCharIsSpace()
  • Tcl_UniCharIsUpper()
  • Tcl_UniCharIsWordChar()
  • Tcl_UniCharIsControl()
  • Tcl_UniCharIsGraph()
  • Tcl_UniCharIsPrint()
  • Tcl_UniCharIsPunct()
  • Tcl_IsChannelShared()
  • Tcl_IsChannelRegistered()
  • Tcl_IsChannelExisting()
  • Tcl_IsStandardChannel()
  • Tcl_IsEnsemble()
  • Tcl_AsyncMarkFromSignal()
  • Tcl_IsEmpty()

For Tk, the list is:

  • Tk_CharBbox()
  • Tk_SetWindowVisual()
  • Tk_StrictMotif()
  • Tk_CollapseMotionEvents()
  • Tk_AlwaysShowSelection()
  • Tk_MacOSXIsAppInFront()

There is a catch. Functions returning a bool, use less bits in the register where the value is returned (like the EAX register on x68). So, bits 0-7 will have the expected value, but bits 8-31 of this register might just have some random value left over from previous code. Older extensions compiled with older (Tcl 9.0) header files which still used int, might interpret those random bits as non-zero, or true. The solution for this is fill the stub table with wrapper functions, which extend the EAX register filling bits 8-31 with all zero's. This way, callers expecting an int will behave the same way as callers expecting a bool.

Here is an example wrapper function (in x68_64 assembler)

    Tcl_IsEqual_stub_wrapper(Tcl_Obj *):
        call    Tcl_IsEqual(Tcl_Obj *)
        movzx   eax, al
        ret

The movzx (move with zero extend) extends the 8-bit result from the Tcl_IsEqual() call to 32 bits. On other processors, the instruction used might be different (e.g "and eax, 255" on x86, "and w0, w0, 255" on ARM64). On WebAssembly, bool's are always returned as 32-bit integers, so no wrapper functions are needed. In C it is not possible to return a boolean in a processor flag (like the carry flag). Some signal-processors might do that (even though it's not according to the C standard), then the same approach as WebAssembly can be used.

The other way around, extensions compiled with Tcl 9.1 headers but running on Tcl 9.0, is no problem. This way, there is both forward and backward binary compatibility between Tcl 9.0 and 9.1. Extensions compiled with Tcl 9.1 headers can make use of the bool optimizations, while extensions compiled with Tcl 9.0 headers cannot, but that's the only difference.

Reference Implementation

See the tip-748 branch.

Copyright

This document has been placed in the public domain.

History