Menu

#3957 Indirect assignment of a non-null value through a pointer discards non-null inference

open
nobody
None
other
5
2026-03-23
2026-03-23
No

1: Sample code that reproduces the problem.

_Optional int *poi;

void chandler(_Optional int **ppoi)
{
  int i;

  // constrains poi to non-null on the fallthrough path
  if (!poi) return;

  *poi = 1;   // no recommended diagnostic
  *ppoi = &i; // non-null constraint on poi is unaffected
  *poi = 2;   // no recommended diagnostic
}

void monica(_Optional int **ppoi, _Optional int *lpoi)
{
  // constrains poi and lpoi to non-null on the fallthrough path
  if (!poi || !lpoi) return;

  *poi = 1;     // no recommended diagnostic
  *ppoi = lpoi; // non-null constraint on poi is unaffected
  *poi = 2;     // no recommended diagnostic
}

void rachel(_Optional int **ppoi_1, _Optional int **ppoi_2)
{
  int i;

  // constrains *ppoi_1 to non-null on the fallthrough path
  if (!*ppoi_1) return;

  **ppoi_1 = 1;  // no recommended diagnostic
  *ppoi_2 = &i;  // non-null constraint on *ppoi_1 is unaffected
  **ppoi_1 = 2;  // no recommended diagnostic
}

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

sdcc --std=c23 -c /work/bug6.c

3: SDCC version tested (type "sdcc -v" to find it)

SDCC : mcs51/z80/z180/r2k/r2ka/r3ka/r4k/r5k/r6k/sm83/tlcs90/ez80/z80n/r800/ds390/pic16/pic14/TININative/ds400/hc08/s08/stm8/pdk13/pdk14/pdk15/mos6502/mos65c02/f8/f8l TD- 4.5.21 #16327 (Linux)

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

The above examples from the Recommended Practice part of subsection 6.5.2 "Type qualifiers" in the _Optional TS are intended to illustrate best-case analysis that might be possible if a translator takes into account whether the value assigned to a pointer (that could alias another pointer) can be null, and therefore whether it is necessary to discard previously-inferred constraints on the value of other pointers that the analyser is tracking.

In chandler, the value of poi, an object declared at file scope that points to an optional-qualified type, is constrained to be non-null on the fallthrough path of an if statement, therefore the implementation is recommended not to produce a diagnostic message for the lvalue *poi in the first assignment. ppoi, a pointer to a pointer to an optional-qualified type, cannot be proven not to point to poi without interprocedural analysis. The assignment of &i to the lvalue *ppoi can modify the value of poi, but the assigned value is not a null pointer. The implementation is therefore recommended not to produce a diagnostic message for the lvalue *poi in the last assignment.

The monica function is similar to chandler except that the assigned value can be proven by flow-sensitive analysis to be non-null, as opposed to its non-null value being a known compile-time constant.

The rachel function is similar to chandler except that the address of the potentially-aliased pointer is passed as an argument instead of the potentially-aliased pointer being a global variable.

SDCC produces diagnostic messages for the final assignment in each function:

/work/bug6.c:12: warning 355: pointer to _Optional could not be proven to be non-null at dereference
/work/bug6.c:22: warning 355: pointer to _Optional could not be proven to be non-null at dereference
/work/bug6.c:34: warning 355: pointer to _Optional could not be proven to be non-null at dereference

Ideally, no diagnostic messages would be produced for these examples.

This is not a bug because it concerns Recommended Practice. I thought it might be useful to report it regardless, in case there is scope for improvement (if the maintainers of SDCC consider that useful).

Discussion


Log in to post a comment.

MongoDB Logo MongoDB