Opened 9 years ago

Last modified 8 years ago

#9647 new Bugs

BOOST_MPL_ASSERT_RELATION fails to properly handle unsigned types

Reported by: Robert Ramey Owned by: Aleksey Gurtovoy
Milestone: To Be Determined Component: mpl
Version: Boost 1.54.0 Severity: Problem
Keywords: Cc:

Description

boost/integer_traits.hpp contains the following

template<>
class integer_traits<unsigned long>
  : public std::numeric_limits<unsigned long>,
    public detail::integer_traits_base<unsigned long, 0, ULONG_MAX>
{ };

Problem is that, at least on Clang ULONG_MAX resolves to (through <limits.h>) to be

#define ULONG_MAX (__LONG_MAX__ *2UL+1UL)

But when LONG_MAX resolves to long and the rules of arithmetic promotion result in the expression LONG_MAX *2UL+1UL being a long rather than unsigned long. This causes some funky behavior in cases like:

BOOST_MPL_ASSERT_RELATION(
    (boost::integer_traits<unsigned long>::const_max),
    >,
    (boost::integer_traits<unsigned char>::const_max)
);

which fails to compile with "Non-type template argument evaluates to 4294967295, which cannot be narrowed to type 'long'

Change History (6)

comment:1 by viboes, 8 years ago

Summary: boost_MPL_ASSERT_RELATION fails to properly handle unsigned typesBOOST_MPL_ASSERT_RELATION fails to properly handle unsigned types

Is this a problem with Clang, Boost.Mpl or Boost.Integer library?

comment:2 by viboes, 8 years ago

Owner: changed from Daryle Walker to viboes
Status: newassigned

comment:3 by Robert Ramey, 8 years ago

I'm thinking that this is libc++ version of limits.h

perhaps this is not the correct place to report this.

Robert Ramey

comment:4 by Robert Ramey, 8 years ago

I looked into this a little bit more.

First of all, my original guess about problematic type promotions was wrong - I don't think there is any issue with libc++ or anything else in the standard library.

The following test program illustrates my

#include <boost/integer_traits.hpp>
#include <boost/mpl/assert.hpp>

BOOST_MPL_ASSERT_RELATION(
    (boost::integer_traits<unsigned long>::const_max),
    >,
    (boost::integer_traits<unsigned char>::const_max)
); // compile error under clang

enum { x  = (
    (boost::integer_traits<unsigned long>::const_max)
    > 
    (boost::integer_traits<unsigned char>::const_max)
    )
}; // compiles OK - can't figure out why

constexpr bool result = (
    (boost::integer_traits<unsigned long>::const_max)
    > 
    (boost::integer_traits<unsigned char>::const_max)
    ); // compiles fine

static_assert(result, "compilation error");

int main(int argc, char * argv[]){
    return ! (boost::integer_traits<unsigned long>::const_max > boost::integer_traits<unsigned char>::const_max);
}

So I believe this is an issue with MPL_ASSERT_RELATION. I've believe the problem is found in boost/mpl/assert.hpp at the line #329: It's probably deeper than this but I didn't trace it further

Robert Ramey

comment:5 by viboes, 8 years ago

Component: integermpl

comment:6 by viboes, 8 years ago

Owner: changed from viboes to Aleksey Gurtovoy
Status: assignednew
Note: See TracTickets for help on using tickets.