mailing list of musl libc
 help / color / mirror / code / Atom feed
From: Jens Gustedt <jens.gustedt@inria.fr>
To: musl@lists.openwall.com
Subject: type verification for number macros
Date: Tue, 25 Nov 2014 15:45:56 +0100	[thread overview]
Message-ID: <1416926756.16006.922.camel@eris.loria.fr> (raw)


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

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: 22788 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;

#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 __STDC_VERSION__ > 201100L
# 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 __STDC_VERSION__ > 201100L
# 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 __STDC_VERSION__ > 201100L
# 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

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

  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__ > 201100L
  printf("\t\t%zu/%zu types wrong\n", type_wrong, type_wrong+type_right);
#endif
  printf("\t\t%zu macros are missing\n", missing);

  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__ > 201100L
  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);

  int ret = type_wrong + size_wrong + sign_wrong + missing;

  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

  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-25 14:45 UTC|newest]

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

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=1416926756.16006.922.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).