Menu

Ambiguous Namespace Detection in GCBASIC resolved

Anobium
2026-06-26
3 days ago
  • Anobium

    Anobium - 2026-06-26

    Background

    GCBASIC supports user-defined CONSTANTS, which allow a programmer to assign a
    fixed value to a named symbol. GCBASIC also supports two directives, #samevar
    and #samebit, which are intended to resolve the changing nature of the flat
    Microchip namespace across registers and bits.

    The problem is that Microchip does not maintain a universally consistent
    namespace across all microcontrollers. This inconsistency, combined with the
    way GCBASIC handles #samevar and #samebit, can introduce ambiguity that is
    difficult to detect and harder to debug.

    Prior to this change, the user has no way of knowing that a conflict exists.
    There is no warning, no error, and no indication that the compiler has
    encountered an ambiguous name. Incorrect code may be generated silently, and
    the resulting behaviour can be extremely difficult to diagnose because the
    compiled output appears valid.

    This capability is in build 1605 or greater.


    A Real-World Example That Triggered This Investigation

    A user reported that the following code, targeting the PIC10F200, produced
    incorrect assembly output.

    OSCCAL.FOSC4 = 1
    

    The user expected this to set bit 0 of OSCCAL. Instead, the compiler generated
    code that modified CAL0, which is bit 1. The generated assembly was syntactically
    valid and assembled without error, but the hardware behaviour was wrong. There
    was no warning from the compiler.

    The workaround at the time was to use the explicit bit address directly.

    OSCCAL.0 = 1
    

    This confirmed that the compiler knew the correct register, but the name FOSC4
    was being resolved incorrectly. The root cause was that FOSC4 exists as both
    a CONSTANT (used to control timers) and as a register bit in OSCCAL. The
    compiler resolved FOSC4 as the CONSTANT rather than the register bit, and
    produced the wrong result silently.


    The Problem in Detail

    Example 1: FOSC4 on the PIC10F200

    The 10F200 range has a register bit called FOSC4, located at OSCCAL.0.
    However, FOSC4 is also defined as a CONSTANT used to control timers, with a
    value of 1. When a programmer references FOSC4 in code targeting the 10Fxxx
    family, the meaning is ambiguous.

    • As a CONSTANT, FOSC4 has a value of 1.
    • As a register bit, FOSC4 refers to OSCCAL,0, which has a value of 0.

    The compiler resolves the name as a CONSTANT, generates incorrect assembly, and
    produces no diagnostic. This affects six microcontrollers in the 10F2xx range.

    Example 2: TWBR on the ATmega328P

    The register TWBR is common across many AVR microcontrollers and serves as
    the control register for I2C. On the ATmega328P, however, this register is
    named TWBR0 to support two or more I2C channels.

    In the past, GCBASIC addressed this by allowing TWBR to be mapped to TWBR0
    using #samevar. The difficulty is that #samevar operates universally and
    is not chip-specific. As a result, TWBR0 is created as a CONSTANT regardless
    of whether TWBR0 exists as a real register on the target microcontroller.

    Any programmer who then references TWBR0 directly is in an ambiguous
    situation. The compiler sees both a CONSTANT called TWBR0 and a register
    called TWBR0, and it cannot reliably determine which one was intended.


    The Solution

    This change introduces a detection step that examines the microcontroller
    namespace specifically. It reports any case where a CONSTANT shares a name
    with either a register or a register bit. Two checks are performed.

    1. CONSTANT vs register bit — iterates the SysVarBits map and checks
      each name against the Constants map.
    2. CONSTANT vs register — iterates the SysVars map and checks each name
      against the Constants map.

    Any collision is reported as AMBIGUOUS in the compiler diagnostic output file,
    and is also printed to the terminal in red so that it is immediately visible.

    With the old compiler, the FOSC4 conflict would now be reported as follows.

    DUPLICATE CONSTANT/BIT NAMES:
    --------------------------------
    AMBIGUOUS: FOSC4
    

    Once the conflict is resolved by correcting the offending #samevar or
    #samebit directive, the output becomes.

    DUPLICATE CONSTANT/BIT NAMES:
    --------------------------------
    None found
    

    Where the Results Are Reported

    The results of the examination are available in two places.

    CDF Diagnostic File

    The compiler diagnostic file (CDF) contains the full examination results,
    showing every ambiguous name found, or confirming that none were found.

    DUPLICATE CONSTANT/BIT NAMES:
    --------------------------------
    None found
    
    DUPLICATE CONSTANT/REGISTER NAMES:
    ------------------------------------
    AMBIGUOUS: OSCCON
    

    Compilation Messages

    Ambiguous names are also reported directly in the compilation output, so they
    are visible immediately without needing to inspect the CDF file. For example.

    GCBASIC (2026.06.25 (Windows 64 bit) : Build 1605)
    Compiling: first-start-sample.gcb
    Program compiled successfully (Compile time: 17.62 seconds)
    Assembling program using GCASM
    Program assembled successfully (Assembly time: 1.125 seconds)
    An error has been found:
     Warning: Ambiguous constant/register name(s): OSCCON
     Error: Warnings generated and treated as errors
    The message has been logged to the file Errors.txt.
    Done
    

    In this example, OSCCON exists as both a CONSTANT and a register. The
    compiler reports it as a warning, and since warnings are treated as errors,
    compilation is halted. The programmer is directed to the issue immediately
    rather than receiving silently incorrect output.


    Resolution

    The good news is that any ambiguity can be resolved, and in practice only a
    small number of specific cases need attention. Once an ambiguous name is
    identified, the offending #samevar or #samebit directive can be removed or
    made chip-specific, eliminating the collision entirely.

    This detection step makes those cases visible for the first time, so they can
    be resolved deliberately rather than discovered accidentally by a programmer
    whose code produces the wrong result.

     
    👍
    1
  • Anobium

    Anobium - 3 days ago

    New: Added EnableAmmbiguityInspection. Compiler will not report ambiguous use of constant when register or register.bit have the same title name.

    Added to use.ini

    [gcbasic]
    EnableAmmbiguityInspection = y
    ...
    
     
  • Anobium

    Anobium - 3 days ago

    This was a little more complex than I thought to add this inspection but it works well.

    In the 1000s of demos.. there were seven cases when the use of a constant was the same as a register.bit.

    UP, DOWN, ON, OFFand a few I2c registers.

    Enjoy this improvement in the quality of the compiler.

     

Log in to post a comment.

Auth0 Logo