clang++: Handling of division by zero in array bounds

What I observe with various versions of Clang:

$ cat test.cc
#include <iostream>
int main() {
    char a[1/0];
    std::cout << sizeof a << '\n';
}

$ clang++ -Weverything test.cc
test.cc:3:11: warning: variable length arrays are a C99 feature
      [-Wvla-extension]
    char a[1/0];
          ^
test.cc:3:11: warning: variable length array used [-Wvla]
2 warnings generated.

$ ./a.out
0

Is there a specific reason to not emit a warning/error about the undefined behavior in evaluating the constant bounds expression, 1/0?

I believe that the issue here is that 1/0 is *not* a constant expression, it is undefined behaviour (typically, run-time trap). We probably should have a special return value for attempting to evaluate something that should be an ICE and finding that the result is undefined, which would allow this to become a more helpful error along the lines of ‘array length is an undefined value, this will abort at run time’.

Currently, I believe that the undefined value is simply marked as something that can not be evaluated at compile time and so this is equivalent to:

int foo(int d)
{
  char a[1/d];
  std::cout << sizeof a << '\n';
}

This is valid code when d > 0, but if d == 0 it will likely trap.

David

A constant expression that would give undefined behavior is ill-formed, and
the compiler is required to issue a diagnostic. It does, by default, but
the diagnostic is misleading and doesn't identify why the code is
ill-formed. So it's not formally a violation of the C++ standard, but it's
not a good error message. Compiling the code and acting as if 1/0 was 0 is
also fairly dubious (though again, not a violation of the C++ standard,
which only requires a diagnostic and never forbids producing an executable).

-- James

    >
    > What I observe with various versions of Clang:
    >
    >> $ cat test.cc
    >> #include <iostream>
    >> int main() {
    >> char a[1/0];
    >> std::cout << sizeof a << '\n';
    >> }
    >>
    >> $ clang++ -Weverything test.cc
    >> test.cc:3:11: warning: variable length arrays are a C99 feature
    >> [-Wvla-extension]
    >> char a[1/0];
    >> ^
    >> test.cc:3:11: warning: variable length array used [-Wvla]
    >> 2 warnings generated.
    >>
    >> $ ./a.out
    >> 0
    >
    > Is there a specific reason to not emit a warning/error about the undefined behavior in evaluating the constant bounds expression, 1/0?

    I believe that the issue here is that 1/0 is *not* a constant
    expression, it is undefined behaviour (typically, run-time trap).
    We probably should have a special return value for attempting to
    evaluate something that should be an ICE and finding that the result
    is undefined, which would allow this to become a more helpful error
    along the lines of ‘array length is an undefined value, this will
    abort at run time’.

    Currently, I believe that the undefined value is simply marked as
    something that can not be evaluated at compile time and so this is
    equivalent to:

    int foo(int d)
    {
      char a[1/d];
      std::cout << sizeof a << '\n';
    }

    This is valid code when d > 0, but if d == 0 it will likely trap.

    David

A constant expression that would give undefined behavior is ill-formed,

No, 1/0 is not a core constant expression, because evaluating it "would have undefined behavior as spedified in Clauses 1 through 16" ([expr.const]), so is not a constant expression. So apparently the non-standard C99 vla extension kicks in as David explained. (Question is whether that extension can be disabled?)

    >
    > What I observe with various versions of Clang:
    >
    >> $ cat test.cc
    >> #include <iostream>
    >> int main() {
    >> char a[1/0];
    >> std::cout << sizeof a << '\n';
    >> }
    >>
    >> $ clang++ -Weverything test.cc
    >> test.cc:3:11: warning: variable length arrays are a C99 feature
    >> [-Wvla-extension]
    >> char a[1/0];
    >> ^
    >> test.cc:3:11: warning: variable length array used [-Wvla]
    >> 2 warnings generated.
    >>
    >> $ ./a.out
    >> 0
    >
    > Is there a specific reason to not emit a warning/error about the
undefined behavior in evaluating the constant bounds expression, 1/0?

    I believe that the issue here is that 1/0 is *not* a constant
    expression, it is undefined behaviour (typically, run-time trap).
    We probably should have a special return value for attempting to
    evaluate something that should be an ICE and finding that the result
    is undefined, which would allow this to become a more helpful error
    along the lines of ‘array length is an undefined value, this will
    abort at run time’.

    Currently, I believe that the undefined value is simply marked as
    something that can not be evaluated at compile time and so this is
    equivalent to:

    int foo(int d)
    {
      char a[1/d];
      std::cout << sizeof a << '\n';
    }

    This is valid code when d > 0, but if d == 0 it will likely trap.

    David

A constant expression that would give undefined behavior is ill-formed,

No, 1/0 is not a core constant expression, because evaluating it "would
have undefined behavior as spedified in Clauses 1 through 16"
([expr.const]), so is not a constant expression.

The language requires a constant expression there. 1/0 is indeed not such
a thing, and hence a diagnostic is required.

So apparently the non-standard C99 vla extension kicks in as David
explained. (Question is whether that extension can be disabled?)

Right, the extension kicks in, and it's only standard-conforming if a
diagnostic is issued (as it is by default). In this case the extension
can't work (the size isn't defined), so that shouldn't happen -- not
because it violates the standard, but because it's nonsensical.

-- James