Opened 9 years ago

Last modified 8 years ago

#9925 new Bugs

operators_test.cpp test_left_shiftable is failing due to invalid parameters

Reported by: chris.cooper@… Owned by: No-Maintainer
Milestone: To Be Determined Component: utility
Version: Boost 1.54.0 Severity: Problem
Keywords: Cc:

Description

In libs/utility/operators_test.cpp, test_left_shiftable is checking whether one random value shifted by a second random value, is the same whether called directly or via the Wrapper2<> and Wrapper1<> template classes.

However, according to C++ ISO specification (INCITS/ISO/IEC 14882-2011\[2012\]), section 5.8.2 (which I don't have, but is referenced at http: / / msdn.microsoft.com/en-us/library/336xbhcz.aspx), left-shifting a signed value has undefined behavior (which is much more unpleasant than implementation-defined behavior) if the result doesn't fit in an unsigned value of the same size.

With the clang compiler that comes with Xcode 5.1 ("Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)"), the results of such left-shifts are seemingly random - this code:

long b1 = 48271;
int s = 1291394886; 
std::cout << (b1 << s) << std::endl;
std::cout << (b1 << s)<< std::endl;
std::cout << (b1 << s)<< std::endl;

prints three different numbers.

Change History (4)

comment:1 by chris.cooper@…, 9 years ago

This behavior causes the regression test to fail inaccurately.

Unfortunately, it's a bit of a pain to easily modify this regression test to limit the input parameters to test_left_shiftable() to ones that will not encounter the compiler's "undefined behavior". Consider removing test_left_shiftable() from test_all() and make a special testing loop that calls it, passing a different set of random numbers guaranteed to be valid left-shift parameters ...

comment:2 by chris.cooper@…, 9 years ago

The same problem occurs with test_right_shiftable().

comment:3 by chris.cooper@…, 9 years ago

One solution: change the end of test_all() to look like this:

        test_incrementable( x1, x2 );
        test_decrementable( x1, x2 );
        
        // Make sure the right-hand operator to the shift operator is not out-of-range.
        if (true_value(y1) < 0)
            y1 = Y1(-true_value(y1));
        unsigned long m1 = sizeof(true_value(x1)) * 8 - 1;
        if (true_value(y1) > m1)
            y1 = Y1(true_value(y1) & m1);
        
        if (y2 < 0)
            y2 = -y2;
        unsigned long m2 = sizeof(true_value(x2)) * 8 - 1;
        if (y2 > m2)
            y2 = y2 & m2;
       
        test_left_shiftable( x1, y1, x2, y2 );
        test_right_shiftable( x1, y1, x2, y2 );

comment:4 by Niklas Angare <li51ckf02@…>, 8 years ago

Component: Regression Testingutility
Owner: changed from René Rivera to No-Maintainer
Note: See TracTickets for help on using tickets.