Menu ▾ ▴

#4169 Relational comparison introduces an unwanted _Optional diagnostic for its other operand

closed-fixed
None
Front-end
5
2026-10-22
2026-10-21
No

1: Sample code that reproduces the problem.

int compare(_Optional char *p, char *q)
{
  if (p)
    return p >= q;
  return 0;
}

Save as optional-relational-conversion.c.

2: Exact command used to run SDCC on this sample code.

sdcc -mz80 --std-c99 --stack-auto -S optional-relational-conversion.c

The same result occurs with -mmos65c02, -mstm8 and -mmcs51 in place of -mz80.

3: SDCC version tested.

SDCC 4.6.4 #17038 (Linux), official snapshot dated 20 October 2026.
Also reproducible in Compiler Explorer with SDCC 4.6.0 and SDCC trunk (4.6.4 #17013 when tested on 21 Oct): https://godbolt.org/z/jxsGaf8vK

4: Copy of the error message or incorrect output, or a clear description of the observed versus expected behaviour.

optional-relational-conversion.c:4: warning 358: pointer to _Optional could not be proven to be non-null at relational operator

Only p has type pointer to optional-qualified type, and its value has been checked before the comparison. I expected no _Optional diagnostic. The caller must still satisfy the ordinary requirements for ordering pointers; this example does not assert that arbitrary pointer values can be ordered.

Adding a check of q suppresses the warning, as does removing _Optional from the declaration of p. The same unwanted warning occurs for <, >, <= and >=.

With --dump-i-code, SDCC shows a conversion of q from char * to _Optional char * before the comparison. The recommended diagnostic should depend on the optional-qualified referenced types of the source operands, rather than qualification introduced by this internal conversion. The source operand q has no optional-qualified referenced type.

This also appears relevant to CBUtilLib's comparison of a checked strchr result with its unqualified input pointer. Unlike [bugs:#4148], the reduced example has no structure members.

Related

Bugs: #4148

Discussion

  • Christopher Bazley

    My fork of Clang does not have the same issue: https://godbolt.org/z/v1z9nE8xE

     
  • Christopher Bazley

    Please consider the attached candidate bug fix. It was created with help from Codex, so it will need approval from someone else (e.g. @spth). It looks to me like quite a nice simplification/unification: the existing POINTER_NONNULL_CHECK mechanism is now used for comparison operations too.

     
    • Philipp Klaus Krause

      Multiple ternary operators in an expression might not be the most elegant C code. Still, I think having two of them in an expression isn't that bad vs. introducing a helper function (that is only used once) containing a switch and making the file 20 lines longer. So I'd prefer just the ternary operators in both expressions instead of those two helper functions.

       
      • Christopher Bazley

        Did you consider that compilers can warn about missing case statements but not about missing ternary operators? I'm just curious.

         
        • Philipp Klaus Krause

          Not really, but I don't think it justifies the extra overhead of 2x20 lines here; also a bug here wouldn't be that bad - it wouldn't affect the generated code, it would just result in a slightly wrong text in a warning.

           
      • Christopher Bazley

        So I'd prefer just the ternary operators in both expressions instead of those two helper functions.

        See attached revised patch.

         
        • Philipp Klaus Krause

          Looks good to me.

           
  • Christopher Bazley

    Fixed by [r17068]

     

    Related

    Commit: [r17068]

  • Christopher Bazley

    • status: open --> closed-fixed
    • assigned_to: Christopher Bazley
     

Log in to post a comment.