Bug 48681 - static assertion using DBL_MIN/DBL_MAX/DBL_EPSILON doesn't work with g++-4.5
Summary: static assertion using DBL_MIN/DBL_MAX/DBL_EPSILON doesn't work with g++-4.5
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.5.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-04-19 08:49 UTC by stefan
Modified: 2011-04-19 09:54 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description stefan 2011-04-19 08:49:20 UTC
We're using static assertions (assertions that are checked at compile time) to validate certain properties for DBL_MIN/DBL_MAX/DBL_EPSILON in BEAST. I've isolated the code and made a standalone example. With g++-4.4, everything compiles fine, with g++-4.5, it doesn't compile any more. The code is:


/* sassert.cc */

#include "values.h"

#define BIRNET_CPP_PASTE2i(a,b)                 a ## b            /* twofold indirection is required to expand macros like __LINE__ */
#define BIRNET_CPP_PASTE2(a,b)                  BIRNET_CPP_PASTE2i (a,b)
#define BIRNET_STATIC_ASSERT_NAMED(expr,asname) typedef struct { char asname[(expr) ? 1 : -1]; } BIRNET_CPP_PASTE2 (Birnet_StaticAssertion_LINE, __LINE__)
#define BIRNET_STATIC_ASSERT(expr)              BIRNET_STATIC_ASSERT_NAMED (expr, compile_time_assertion_failed)

BIRNET_STATIC_ASSERT (FLT_MIN      <= 1E-37);
BIRNET_STATIC_ASSERT (FLT_MAX      >= 1E+37);
BIRNET_STATIC_ASSERT (FLT_EPSILON  <= 1E-5);
BIRNET_STATIC_ASSERT (DBL_MIN      <= 1E-37);
BIRNET_STATIC_ASSERT (DBL_MAX      >= 1E+37);
BIRNET_STATIC_ASSERT (DBL_EPSILON  <= 1E-9);

int
main()
{
  return 0;
}

# g++-4.4 sassert.cc
works

# g++-4.5 sassert.cc
sassert.cc:11:1: error: array bound is not an integer constant before ']' token
sassert.cc:12:1: error: array bound is not an integer constant before ']' token
sassert.cc:13:1: error: array bound is not an integer constant before ']' token

Preprocessed code for g++-4.4:
==============================
/* [...] */
typedef struct { char compile_time_assertion_failed[(1.17549435e-38F <= 1E-37) ? 1 : -1]; } Birnet_StaticAssertion_LINE8;
typedef struct { char compile_time_assertion_failed[(3.40282347e+38F >= 1E+37) ? 1 : -1]; } Birnet_StaticAssertion_LINE9;
typedef struct { char compile_time_assertion_failed[(1.19209290e-7F <= 1E-5) ? 1 : -1]; } Birnet_StaticAssertion_LINE10;
typedef struct { char compile_time_assertion_failed[(2.2250738585072014e-308 <= 1E-37) ? 1 : -1]; } Birnet_StaticAssertion_LINE11;
typedef struct { char compile_time_assertion_failed[(1.7976931348623157e+308 >= 1E+37) ? 1 : -1]; } Birnet_StaticAssertion_LINE12;
typedef struct { char compile_time_assertion_failed[(2.2204460492503131e-16 <= 1E-9) ? 1 : -1]; } Birnet_StaticAssertion_LINE13;

int
main()
{
  return 0;
}

Preprocessed code for g++-4.5:
==============================

typedef struct { char compile_time_assertion_failed[(1.17549435082228750797e-38F <= 1E-37) ? 1 : -1]; } Birnet_StaticAssertion_LINE8;
typedef struct { char compile_time_assertion_failed[(3.40282346638528859812e+38F >= 1E+37) ? 1 : -1]; } Birnet_StaticAssertion_LINE9;
typedef struct { char compile_time_assertion_failed[(1.19209289550781250000e-7F <= 1E-5) ? 1 : -1]; } Birnet_StaticAssertion_LINE10;
typedef struct { char compile_time_assertion_failed[(((double)2.22507385850720138309e-308L) <= 1E-37) ? 1 : -1]; } Birnet_StaticAssertion_LINE11;
typedef struct { char compile_time_assertion_failed[(((double)1.79769313486231570815e+308L) >= 1E+37) ? 1 : -1]; } Birnet_StaticAssertion_LINE12;
typedef struct { char compile_time_assertion_failed[(((double)2.22044604925031308085e-16L) <= 1E-9) ? 1 : -1]; } Birnet_StaticAssertion_LINE13;

int
main()
{
  return 0;
}

I'm not sure if this is to be considered a compiler bug (so it should be fixed in g++), or if the code in question is not valid C++ and should not be used (so it should be fixed in the application).
Comment 1 Richard Biener 2011-04-19 09:54:28 UTC
I think expressions involving floating point operations are never valid
integral constant expressions (at least not in C).

An EDG based frontend agrees with that:

t.C(2): error: expression must have integral or enum type
  compile_time_assertion_failed[(1.17549435082228750797e-38F <= 1E-37) ? 1 : -1];
                                 ^
...
t.C(13): error: type of cast must be integral or enum
  compile_time_assertion_failed[(((double)1.79769313486231570815e+308L) >= 1E+37)
                                   ^