Skip to content

const/constexpr INFINITY can cause clang to make a different result from inf/inf or inf-inf #165989

@wind0204

Description

@wind0204

Title.

The usual result from inf/inf or inf-inf is a negative NaN, but when I use a const infinity clang calculates it in compile-time and saves a positive NaN for runtime use

Ubuntu GCC 13.3.0(gcc -std=gnu2x minimal.c -lm) didn't have the issue but Ubuntu clang 18 and Ubuntu clang 20 showed the symptom.

The CPU I use is Haswell.

I think you can reproduce the symptom with the code below ( clang minimal.c -std=gnu23 -lm )

#include <stdio.h>
#include <stdint.h>
#include <math.h>

/*
 * \brief for little endian systems
 */
union ieee754_binary32 {
  struct {
    uint32_t fraction: 23;
    uint16_t exponent: 8;
    uint8_t sign: 1;
  };
  float whole;
};

int main(int argc, char * argv[])
{
  float inf = INFINITY;
  float nan = NAN;

#if __clang_major__ <= 18
  const float cinf = INFINITY;
  const float cnan = NAN;
#else
  constexpr float cinf = INFINITY;
  constexpr float cnan = NAN;
#endif

  fprintf( stdout, "inf - inf = %f\n", (inf - inf) );
  fprintf( stdout, "const_inf - const_inf = %f\n", (cinf - cinf) );
  union ieee754_binary32 inspector = {.whole=(cinf - cinf)};
  fprintf( stdout, "inspector = {.whole=(const_inf - const_inf)}; inspector.sign = %u\n", inspector.sign );

  fprintf( stdout, "inf / inf = %f\n", (inf / inf) );
  inspector.whole = (inf / inf);
  fprintf( stdout, "inspector = {.whole=(inf / inf)}; inspector.sign = %u\n", inspector.sign );
  fprintf( stdout, "const_inf / const_inf = %f\n", (cinf / cinf) );

  inspector.whole = (cinf / cinf);
  fprintf( stdout, "inspector = {.whole=(const_inf / const_inf)}; inspector.sign = %u\n", inspector.sign );

  return 0;
}

The output from clang-built binaries:

inf - inf = -nan
const_inf - const_inf = nan
inspector = {.whole=(const_inf - const_inf)}; inspector.sign = 0
inf / inf = -nan
inspector = {.whole=(inf / inf)}; inspector.sign = 1
const_inf / const_inf = nan
inspector = {.whole=(const_inf / const_inf)}; inspector.sign = 0

The output from a GCC-built binary:

inf - inf = -nan
const_inf - const_inf = -nan
inspector = {.whole=(const_inf - const_inf)}; inspector.sign = 1
inf / inf = -nan
inspector = {.whole=(inf / inf)}; inspector.sign = 1
const_inf / const_inf = -nan
inspector = {.whole=(const_inf / const_inf)}; inspector.sign = 1

Thank you so much!

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions