mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Jens Gustedt <jens.gustedt@inria.fr>
To: musl@lists.openwall.com
Subject: Re: type verification for number macros
Date: Wed, 26 Nov 2014 14:06:18 +0100	[thread overview]
Message-ID: <1417007178.28402.106.camel@eris.loria.fr> (raw)
In-Reply-To: <1416926756.16006.922.camel@eris.loria.fr>


[-- Attachment #1.1: Type: text/plain, Size: 1706 bytes --]

Hello,
 here is a new version of the test that also takes the correctness of
the CMPLX macros for special values into consideration.

I will follow up in the other thread with a new version of patch 1/4
that takes nsz' remarks into account.

Am Dienstag, den 25.11.2014, 15:45 +0100 schrieb Jens Gustedt:
> Hello,
> 
> after a recent discussion about DR 456, I noticed that the types and
> properties of the numerical macros that the C standard requires are
> not always completely trivial. Basically there are three distinct
> cases:
> 
>   (1) the standard requires that the type of an integer constant is the
>       promoted type
> 
>   (2) the standard requires that the type of an integer constant is the
>       exact type
> 
>   (3) the standard requires that the type of a floating point constant
>       is the exact type *and* that it must be suitable to initialize a
>       static varialble.
> 
> Joint is a program that checks all of these. This exposes 3 different
> bugs for musl:
> 
>   - [U]INTxx_C(x) macros don't have the exact type
>   - WINT_MIN must have type wint_t, that is unsigned for musl
>   - CMPLX(x, y) and friends must be usable for initialization
> 
> The later makes the compilation of the program fail with musl :(
> 
> In a follow up I will send 4 patches that address issues with this
> types of macros.
> 
> Jens
> 
> 


-- 
:: INRIA Nancy Grand Est ::: AlGorille ::: ICube/ICPS :::
:: ::::::::::::::: office Strasbourg : +33 368854536   ::
:: :::::::::::::::::::::: gsm France : +33 651400183   ::
:: ::::::::::::::: gsm international : +49 15737185122 ::
:: http://icube-icps.unistra.fr/index.php/Jens_Gustedt ::



[-- Attachment #1.2: test_number_macros.c --]
[-- Type: text/x-csrc, Size: 24036 bytes --]

/**
 ** copyright © 2014, Jens Gustedt
 ** All rights reserved.
 **
 ** Redistribution and use in source and binary forms, with or without
 ** modification, are permitted provided that the following conditions
 ** are met:
 **
 ** 1. Redistributions of source code must retain the above copyright
 ** notice, this list of conditions and the following disclaimer.
 **
 ** 2. Redistributions in binary form must reproduce the above
 ** copyright notice, this list of conditions and the following
 ** disclaimer in the documentation and/or other materials provided
 ** with the distribution.
 **
 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 ** CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 ** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 ** DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
 ** BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 ** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 ** TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ** ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
 ** TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
 ** THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 ** SUCH DAMAGE.
 **/

/**
 ** @file
 ** @brief Test C standard numerical macros for their size and type
 **
 ** The C standard imposes types for a lot of numerical values, such
 ** as minimum and maximum values of certain types.
 **
 ** Before C11, only the size and sometimes the signedness of a
 ** integer or floating point literal have been observable. With C11
 ** the type itself becomes observable through _Generic
 ** expressions. Portability requires then that the types of the
 ** macros are exactly what the standard defines.
 **
 ** There are basically three forms of restrictions by the
 ** standard.
 **
 ** The first is an exact definition of integer constants, e.g
 ** <code>UINT16_C(1)</code> must be of type
 ** <code>uint_least16_t</code>. These must all be suitable for
 ** evaluation in the preprocessor, so we also test them for that.
 **
 ** The second form is a prescription of the promoted type. These are
 ** e.g the minimum and maximum values of signed integer types. So the
 ** promotion rules apply for them: for narrow types the resulting
 ** type for the constant is int (most of the times) for wide types it
 ** that same wide types. E.g <code>SHORT_MAX</code> is usually of
 ** type <code>int</code>, <code>LONG_MAX</code> is <code>long</code>.
 ** They also must be suitable for evaluation in the preprocessor, so
 ** we also test them for that.
 **
 ** The third is an exact definition of floating point constants, e.g
 ** <code>_Complex_I</code> must be of type <code>_Complex
 ** double</code>. These can't be used in the preprocessor, so we
 ** don't test that, but must be suitable in initializers of static
 ** variables. So we test for that.
 **
 ** This program implements tests on two different levels. The first
 ** should work with any C99 compatible compiler. It checks that the
 ** sizes are correct, for signedness when that is possible, that is
 ** when the type doesn't promote, and if the constant is suitable for
 ** initialization of static objects.
 **
 ** When compiled with a C11 compiler and additional check for the
 ** type is made. The program prints all findings and a summary.
 **
 ** @return is @c EXIT_SUCCESS if all sizes and types were
 ** correct. Otherwise @c EXIT_FAILURE is returned.
 **/


#ifndef __STDC_NO_COMPLEX__
# include <complex.h>
#endif
#include <float.h>
#include <limits.h>
#include <math.h>
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <wchar.h>

/* some utilities to use with _Generic for type identification */

enum cls {
  c_def,
  c_b,
  c_c,
  c_hhi,
  c_hhu,
  c_hi,
  c_hu,
  c_i,
  c_u,
  c_li,
  c_lu,
  c_lli,
  c_llu,
  c_f,
  c_lf,
  c_llf,
  c_cf,
  c_clf,
  c_cllf,
};

#ifndef __STDC_NO_COMPLEX__
# define COMPLEX_TYPES _Complex float: c_cf, _Complex double: c_clf, _Complex long double: c_cllf
#else
# define COMPLEX_TYPES
#endif

#define TYPEID(X)                                                       \
_Generic((X),                                                           \
         default: c_def,                                                \
         _Bool: c_b,                                                    \
         char: c_c, signed char: c_hhi, unsigned char: c_hhu,           \
         signed short: c_hi, unsigned short: c_hu,                      \
         signed: c_i, unsigned: c_u,                                    \
         signed long: c_li, unsigned long: c_lu,                        \
         signed long long: c_lli, unsigned long long: c_llu,            \
         float: c_f, double: c_lf, long double: c_llf,                  \
         COMPLEX_TYPES)

#define TYPENAME(X)                             \
(char const*[]){                                \
    [c_def]  = "<unknown type>",                \
    [c_b] = "_Bool",                            \
    [c_c] = "char",                             \
    [c_hhi] = "signed char",                    \
    [c_hhu] = "unsigned char",                  \
    [c_hi] = "signed short int",                \
    [c_hu] = "unsigned short int",              \
    [c_i] = "signed int",                       \
    [c_u] = "unsigned int",                     \
    [c_li] = "signed long int",                 \
    [c_lu] = "unsigned long int",               \
    [c_lli] = "signed long long int",           \
    [c_llu] = "unsigned long long int",         \
    [c_f] = "float",                            \
    [c_lf] = "double",                          \
    [c_llf] = "long double",                    \
    [c_cf] = "_Complex float",                  \
    [c_clf] = "_Complex double",                \
    [c_cllf] = "_Complex long double",          \
      }[(X)]

/* Counters to track the number of bugs. */

static size_t size_right;
static size_t size_wrong;
static size_t sign_right;
static size_t sign_wrong;
static size_t type_right;
static size_t type_wrong;
static size_t missing;
static size_t mismatch;

#define CHECK_EXACT_SIZE(T, X, ST, SX)                  \
do {                                                    \
  if (sizeof(X) == sizeof(T)) {                         \
    ++size_right;                                       \
    printf("%20s, %20s:\tright size\n", SX, ST);        \
  } else {                                              \
    ++size_wrong;                                       \
    printf("%20s, %20s:\twrong size, %s, %zu != %zu\n", \
           SX, ST, #X, sizeof(X), sizeof(T));           \
  }                                                     \
 } while(0)

#define CHECK_EXACT_TYPE(T, X, ST, SX)                                  \
do {                                                                    \
  int type_x = TYPEID(X);                                               \
  int type_unpromoted = TYPEID((T)0);                                   \
  if (_Generic((X), T: 1, default: 0)) {                                \
    ++type_right;                                                       \
    printf("%20s, %20s:\tright type \"%s\"\n", SX, ST,                  \
           TYPENAME(type_x));                                           \
  } else {                                                              \
    ++type_wrong;                                                       \
    printf("%20s, %20s:\twrong type \"%s\", should be \"%s\"\n",        \
           SX, ST, TYPENAME(type_x), TYPENAME(type_unpromoted));        \
  }                                                                     \
 } while(0)

#define CHECK_SIGN(T, X, ST, SX)                                        \
do {                                                                    \
  _Bool ispromoted = (sizeof(T) != sizeof(+(T)0));                      \
  if (!ispromoted) {                                                    \
    _Bool issinged_T = (0 > (T)-1);                                     \
    _Bool issinged_x = (0 > (1 ? -1 : (X)));                            \
    if (issinged_x == issinged_T) {                                     \
      ++sign_right;                                                     \
    } else {                                                            \
      ++sign_wrong;                                                     \
      printf("%20s, %20s:\twrong sign, %ssigned instead of %ssigned\n", \
             SX, ST,                                                    \
             (issinged_x ? "" : "un"),                                  \
             (issinged_T ? "" : "un"));                                 \
    }                                                                   \
  }                                                                     \
 } while(0)

#if !defined(SKIP_GENERIC) && __STDC_VERSION__ > 201000L
# define CHECK_EXACT(T, X)                      \
  do {                                          \
    CHECK_EXACT_SIZE(T, X, #T, #X);             \
    CHECK_SIGN(T, X, #T, #X);                   \
    CHECK_EXACT_TYPE(T, X, #T, #X);             \
  } while (0)
#else
# define CHECK_EXACT(T, X)                      \
  do {                                          \
    CHECK_EXACT_SIZE(T, X, #T, #X);             \
    CHECK_SIGN(T, X, #T, #X);                   \
  } while (0)
#endif

#define CHECK_CONSTANT(T, X, ST, SX)            \
do {                                            \
  static T volatile const obj = X;              \
  (void)obj;                                    \
 } while (0)

#if !defined(SKIP_GENERIC) && __STDC_VERSION__ > 201000L
# define CHECK_UNORDERED(T, X)                  \
  do {                                          \
    CHECK_CONSTANT(T, X, #T, #X);               \
    CHECK_EXACT_SIZE(T, X, #T, #X);             \
    CHECK_EXACT_TYPE(T, X, #T, #X);             \
  } while (0)
#else
# define CHECK_UNORDERED(T, X)                  \
  do {                                          \
    CHECK_CONSTANT(T, X, #T, #X);               \
    CHECK_EXACT_SIZE(T, X, #T, #X);             \
  } while (0)
#endif

#define CHECK_PROMOTED_SIZE(T, X, ST, SX)               \
do {                                                    \
  if (sizeof(X) == sizeof(+(T)0)) {                     \
    ++size_right;                                       \
    printf("%20s, %20s:\tright size\n", SX, ST);        \
  } else {                                              \
    ++size_wrong;                                       \
    printf("%20s, %20s:\twrong size, %s, %zu != %zu\n", \
           SX, ST, #X, sizeof(X), sizeof(+(T)0));       \
  }                                                     \
 } while(0)

#define CHECK_PROMOTED_TYPE(T, X, ST, SX)                               \
do {                                                                    \
  bool unpromoted = _Generic(+(T)0, T: true, default: false);           \
  int type_x = TYPEID(X);                                               \
  int type_promoted = TYPEID(+(T)0);                                    \
  int type_unpromoted = TYPEID((T)0);                                   \
  bool correct = (unpromoted                                            \
                  /* an unpromoted type must match */                   \
                  ? _Generic((X), T: 1, default: 0)                     \
                  /* an promoted type mustn't */                        \
                  : type_x == type_promoted);                           \
  if (correct) {                                                        \
    ++type_right;                                                       \
    printf("%20s, %20s:\tright %spromoted type \"%s\"\n", SX, ST,       \
           (unpromoted ? "un" : ""),                                    \
           TYPENAME(type_promoted));                                    \
  } else {                                                              \
    ++type_wrong;                                                       \
    printf("%20s, %20s:\twrong type, has type \"%s\" should be %spromoted type \"%s\"\n", \
           SX, ST, TYPENAME(type_x),                                    \
           (unpromoted ? "un" : ""),                                    \
           (unpromoted                                                  \
            ? TYPENAME(type_unpromoted)                                 \
            : TYPENAME(type_promoted)));                                \
  }                                                                     \
 } while(0)

#if !defined(SKIP_GENERIC) && __STDC_VERSION__ > 201000L
# define CHECK_PROMOTED(T, X)                   \
  do {                                          \
  CHECK_PROMOTED_SIZE(T, X, #T, #X);            \
  CHECK_SIGN(T, X, #T, #X);                     \
  CHECK_PROMOTED_TYPE(T, X, #T, #X);            \
  } while (0)
#else
# define CHECK_PROMOTED(T, X)                   \
  do {                                          \
  CHECK_PROMOTED_SIZE(T, X, #T, #X);            \
  CHECK_SIGN(T, X, #T, #X);                     \
  } while (0)
#endif


#define TCMPLX(X, Y) (+(union { _Complex double _c; double _p[2]; }){ ._p = { [0] = (X), [1] = (Y) }}._c)

#define CHECK_COMPLEX(X, Y)                                     \
do {                                                            \
  _Complex double A = CMPLX((X), (Y));                          \
  _Complex double B = TCMPLX((X), (Y));                         \
  if (A != B) {                                                 \
    ++mismatch;                                                 \
    printf("complex (%s, %s): (%g, %g) != (%g, %g)\n",          \
           #X, #Y, creal(A), cimag(A), creal(B), cimag(B));     \
  }                                                             \
 } while(0)


int main(void) {

  /* types that must be unsigned */

#if false+1
  CHECK_PROMOTED(bool, false);
#endif
#if true+1
  CHECK_PROMOTED(bool, true);
#endif

#if UINT8_C(1) > 0
  CHECK_EXACT(uint_least8_t, UINT8_C(1));
#endif
#if UINT16_C(1) > 0
  CHECK_EXACT(uint_least16_t, UINT16_C(1));
#endif
#if UINT32_C(1) > 0
  CHECK_EXACT(uint_least32_t, UINT32_C(1));
#endif
#if UINT64_C(1) > 0
  CHECK_EXACT(uint_least64_t, UINT64_C(1));
#endif

#if UCHAR_MAX > 0
  CHECK_PROMOTED(unsigned char, UCHAR_MAX);
#endif
#if USHRT_MAX > 0
  CHECK_PROMOTED(unsigned short, USHRT_MAX);
#endif
#if UINT_MAX > 0
  CHECK_EXACT(unsigned int, UINT_MAX);
#endif
#if ULONG_MAX > 0
  CHECK_EXACT(unsigned long, ULONG_MAX);
#endif
#if ULLONG_MAX > 0
  CHECK_EXACT(unsigned long long, ULLONG_MAX);
#endif


#if UINT8_MAX > 0
  CHECK_PROMOTED(uint8_t, UINT8_MAX);
#endif
#if UINT16_MAX > 0
  CHECK_PROMOTED(uint16_t, UINT16_MAX);
#endif
#if UINT32_MAX > 0
  CHECK_PROMOTED(uint32_t, UINT32_MAX);
#endif
#if UINT64_MAX > 0
  CHECK_PROMOTED(uint64_t, UINT64_MAX);
#endif
#if UINT_LEAST8_MAX > 0
  CHECK_PROMOTED(uint_least8_t, UINT_LEAST8_MAX);
#endif
#if UINT_LEAST16_MAX > 0
  CHECK_PROMOTED(uint_least16_t, UINT_LEAST16_MAX);
#endif
#if UINT_LEAST32_MAX > 0
  CHECK_PROMOTED(uint_least32_t, UINT_LEAST32_MAX);
#endif
#if UINT_LEAST64_MAX > 0
  CHECK_PROMOTED(uint_least64_t, UINT_LEAST64_MAX);
#endif
#if UINT_FAST8_MAX > 0
  CHECK_PROMOTED(uint_fast8_t, UINT_FAST8_MAX);
#endif
#if UINT_FAST16_MAX > 0
  CHECK_PROMOTED(uint_fast16_t, UINT_FAST16_MAX);
#endif
#if UINT_FAST32_MAX > 0
  CHECK_PROMOTED(uint_fast32_t, UINT_FAST32_MAX);
#endif
#if UINT_FAST64_MAX > 0
  CHECK_PROMOTED(uint_fast64_t, UINT_FAST64_MAX);
#endif

#if UINTMAX_MAX > 0
  CHECK_EXACT(uintmax_t, UINTMAX_MAX);
#endif
#if UINPTR_MAX > 0
  CHECK_PROMOTED(uintptr_t, UINTPTR_MAX);
#endif
#if SIZE_MAX > 0
  CHECK_PROMOTED(size_t, SIZE_MAX);
#endif

  /* types that that maybe signed */

#if INT8_C(1) > 0
  CHECK_EXACT(int_least8_t, INT8_C(1));
#endif
#if INT16_C(1) > 0
  CHECK_EXACT(int_least16_t, INT16_C(1));
#endif
#if INT32_C(1) > 0
  CHECK_EXACT(int_least32_t, INT32_C(1));
#endif
#if INT64_C(1) > 0
  CHECK_EXACT(int_least64_t, INT64_C(1));
#endif

#if CHAR_MAX > 0
  CHECK_PROMOTED(char, CHAR_MAX);
#endif
#if SCHAR_MAX > 0
  CHECK_PROMOTED(signed char, SCHAR_MAX);
#endif
#if SHRT_MAX > 0
  CHECK_PROMOTED(signed short, SHRT_MAX);
#endif
#if INT_MAX > 0
  CHECK_EXACT(signed int, INT_MAX);
#endif
#if LONG_MAX > 0
  CHECK_EXACT(signed long, LONG_MAX);
#endif
#if LLONG_MAX > 0
  CHECK_EXACT(signed long long, LLONG_MAX);
#endif

#if INT8_MAX > 0
  CHECK_PROMOTED(int8_t, INT8_MAX);
#endif
#if INT16_MAX > 0
  CHECK_PROMOTED(int16_t, INT16_MAX);
#endif
#if INT32_MAX > 0
  CHECK_PROMOTED(int32_t, INT32_MAX);
#endif
#if INT64_MAX > 0
  CHECK_PROMOTED(int64_t, INT64_MAX);
#endif
#if INT_LEAST8_MAX > 0
  CHECK_PROMOTED(int_least8_t, INT_LEAST8_MAX);
#endif
#if INT_LEAST16_MAX > 0
  CHECK_PROMOTED(int_least16_t, INT_LEAST16_MAX);
#endif
#if INT_LEAST32_MAX > 0
  CHECK_PROMOTED(int_least32_t, INT_LEAST32_MAX);
#endif
#if INT_LEAST64_MAX > 0
  CHECK_PROMOTED(int_least64_t, INT_LEAST64_MAX);
#endif
#if INT_FAST8_MAX > 0
  CHECK_PROMOTED(int_fast8_t, INT_FAST8_MAX);
#endif
#if INT_FAST16_MAX > 0
  CHECK_PROMOTED(int_fast16_t, INT_FAST16_MAX);
#endif
#if INT_FAST32_MAX > 0
  CHECK_PROMOTED(int_fast32_t, INT_FAST32_MAX);
#endif
#if INT_FAST64_MAX > 0
  CHECK_PROMOTED(int_fast64_t, INT_FAST64_MAX);
#endif

#if INTMAX_MAX > 0
  CHECK_PROMOTED(intmax_t, INTMAX_MAX);
#endif
#if UINPTR_MAX > 0
  CHECK_PROMOTED(intptr_t, INTPTR_MAX);
#endif
#if PTRDIFF_MAX > 0
  CHECK_PROMOTED(ptrdiff_t, PTRDIFF_MAX);
#endif
#if SIG_ATOMIC_MAX > 0
  CHECK_PROMOTED(sig_atomic_t, SIG_ATOMIC_MAX);
#endif
#if WCHAR_MAX > 0
  CHECK_PROMOTED(wchar_t, WCHAR_MAX);
#endif
#if WINT_MAX > 0
  /* wint_t should not promote */
  CHECK_EXACT(wint_t, WINT_MAX);
#endif

#if CHAR_MIN < 1
  CHECK_PROMOTED(char, CHAR_MIN);
#endif
#if SCHAR_MIN < 1
  CHECK_PROMOTED(signed char, SCHAR_MIN);
#endif
#if SHRT_MIN < 1
  CHECK_PROMOTED(signed short, SHRT_MIN);
#endif
#if INT_MIN < 1
  CHECK_EXACT(signed int, INT_MIN);
#endif
#if LONG_MIN < 1
  CHECK_EXACT(signed long, LONG_MIN);
#endif
#if LLONG_MIN < 1
  CHECK_EXACT(signed long long, LLONG_MIN);
#endif

#if INT8_MIN < 1
  CHECK_PROMOTED(int8_t, INT8_MIN);
#endif
#if INT16_MIN < 1
  CHECK_PROMOTED(int16_t, INT16_MIN);
#endif
#if INT32_MIN < 1
  CHECK_PROMOTED(int32_t, INT32_MIN);
#endif
#if INT64_MIN < 1
  CHECK_PROMOTED(int64_t, INT64_MIN);
#endif
#if INT_LEAST8_MIN < 1
  CHECK_PROMOTED(int_least8_t, INT_LEAST8_MIN);
#endif
#if INT_LEAST16_MIN < 1
  CHECK_PROMOTED(int_least16_t, INT_LEAST16_MIN);
#endif
#if INT_LEAST32_MIN < 1
  CHECK_PROMOTED(int_least32_t, INT_LEAST32_MIN);
#endif
#if INT_LEAST64_MIN < 1
  CHECK_PROMOTED(int_least64_t, INT_LEAST64_MIN);
#endif
#if INT_FAST8_MIN < 1
  CHECK_PROMOTED(int_fast8_t, INT_FAST8_MIN);
#endif
#if INT_FAST16_MIN < 1
  CHECK_PROMOTED(int_fast16_t, INT_FAST16_MIN);
#endif
#if INT_FAST32_MIN < 1
  CHECK_PROMOTED(int_fast32_t, INT_FAST32_MIN);
#endif
#if INT_FAST64_MIN < 1
  CHECK_PROMOTED(int_fast64_t, INT_FAST64_MIN);
#endif

#if INTMAX_MIN < 1
  CHECK_PROMOTED(intmax_t, INTMAX_MIN);
#endif
#if UINPTR_MIN < 1
  CHECK_PROMOTED(intptr_t, INTPTR_MIN);
#endif
#if PTRDIFF_MIN < 1
  CHECK_PROMOTED(ptrdiff_t, PTRDIFF_MIN);
#endif
#if SIG_ATOMIC_MIN < 1
  CHECK_PROMOTED(sig_atomic_t, SIG_ATOMIC_MIN);
#endif
#if WCHAR_MIN < 1
  CHECK_PROMOTED(wchar_t, WCHAR_MIN);
#endif
#if EOF < 1 || EOF > 0
  CHECK_EXACT(int, EOF);
#endif
#if WINT_MIN < 1
  /* wint_t should not promote */
  CHECK_EXACT(wint_t, WINT_MIN);
#endif
#if WEOF < 1 || WEOF > 0
  /* wint_t should not promote */
  CHECK_EXACT(wint_t, WEOF);
#endif

  CHECK_UNORDERED(float, FLT_MAX);
  CHECK_UNORDERED(float, FLT_MIN);
  CHECK_UNORDERED(float, FLT_TRUE_MIN);
  CHECK_UNORDERED(float, FLT_EPSILON);
  CHECK_UNORDERED(float, HUGE_VALF);
  CHECK_UNORDERED(float, INFINITY);
#ifdef NAN
  CHECK_UNORDERED(float, NAN);
#endif

  CHECK_UNORDERED(double, DBL_MAX);
  CHECK_UNORDERED(double, DBL_MIN);
  CHECK_UNORDERED(double, DBL_TRUE_MIN);
  CHECK_UNORDERED(double, DBL_EPSILON);
  CHECK_UNORDERED(double, HUGE_VAL);

  CHECK_UNORDERED(long double, LDBL_MAX);
  CHECK_UNORDERED(long double, LDBL_MIN);
  CHECK_UNORDERED(long double, LDBL_TRUE_MIN);
  CHECK_UNORDERED(long double, LDBL_EPSILON);
  CHECK_UNORDERED(long double, HUGE_VALL);

#ifndef __STDC_NO_COMPLEX__
# ifdef imaginary
  CHECK_UNORDERED(_Imaginary float, I);
# else
  CHECK_UNORDERED(_Complex float, I);
# endif
  /* Notwithstanding the provisions of 7.1.3, a program may undefine
     and perhaps then redefine the macros complex, imaginary, and
     I. */
# undef imaginary
# undef complex
# undef I
  /* Try to invent the most stupid choices that an application could
     ever make. */
# define imaginary long double
# define complex long double
# define I 1.4L
  /* Now all other macros should still work. */
# ifdef _Imaginary_I
  CHECK_UNORDERED(_Imaginary float, _Imaginary_I);
# endif
  CHECK_UNORDERED(_Complex float, _Complex_I);
  CHECK_UNORDERED(_Complex float, 1.0F + _Complex_I);
  CHECK_UNORDERED(_Complex double, 1.0 + _Complex_I);
  CHECK_UNORDERED(_Complex long double, 1.0L + _Complex_I);
# ifdef CMPLXF
  CHECK_UNORDERED(_Complex float, CMPLXF(1.0L, 1.0L));
# else
  ++missing;
  puts("macro CMPLXF is missing");
# endif
# ifdef CMPLX
  CHECK_UNORDERED(_Complex double, CMPLX(1.0L, 1.0L));
# else
  ++missing;
  puts("macro CMPLX is missing");
# endif
# ifdef CMPLXL
  CHECK_UNORDERED(_Complex long double, CMPLXL(1.0F, 1.0F));
# else
  ++missing;
  puts("macro CMPLXL is missing");
# endif
#endif

  puts("\ncheck a set of literals that all should work, independent of the C library");
  CHECK_EXACT(int, 'a');
  CHECK_EXACT(wchar_t, L'a');
#if __STDC_VERSION__ > 201000L
  CHECK_EXACT(uint_least16_t, u'a');
  CHECK_EXACT(uint_least32_t, U'A');
#endif
#ifdef __SIZEOF_INT128__
  CHECK_EXACT(__int128, (__int128)0);
#endif
  CHECK_UNORDERED(float, 0.0F);
  CHECK_UNORDERED(double, 0.0);
  CHECK_UNORDERED(long double, 0.0L);

#ifdef CMPLX
  CHECK_COMPLEX(1.0, 0.0);
  CHECK_COMPLEX(0.0, 1.0);
  CHECK_COMPLEX(INFINITY, 0.0);
  CHECK_COMPLEX(0.0, INFINITY);
#endif

  printf("\nSummary:\t%zu/%zu sizes wrong\n", size_wrong, size_wrong+size_right);
  printf("\t\t%zu/%zu signedness wrong\n", sign_wrong, sign_wrong+sign_right);
#if __STDC_VERSION__ > 201000L
  printf("\t\t%zu/%zu types wrong\n", type_wrong, type_wrong+type_right);
#endif
  printf("\t\t%zu macros are missing\n", missing);
  printf("\t\t%zu mismatches of complex values\n", mismatch);

  int ret = type_wrong + size_wrong + sign_wrong + missing + mismatch;

  puts("\ncheck a set of mismatches that should error, independent of the C library");
  CHECK_UNORDERED(double, 0LL);
  CHECK_PROMOTED(double, 0LL);
#ifdef __SIZEOF_INT128__
  CHECK_EXACT(__int128, 0LL);
#endif

#if defined(NAN) && defined(CMPLX)
  puts("\nThe two following involve NAN, so comparison should always be false");
  CHECK_COMPLEX(INFINITY, NAN);
  CHECK_COMPLEX(NAN, INFINITY);
#endif

  return ret ? EXIT_FAILURE : EXIT_SUCCESS;
}

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

      reply	other threads:[~2014-11-26 13:06 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-11-25 14:45 Jens Gustedt
2014-11-26 13:06 ` Jens Gustedt [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1417007178.28402.106.camel@eris.loria.fr \
    --to=jens.gustedt@inria.fr \
    --cc=musl@lists.openwall.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).