[Boost-bugs] [Boost C++ Libraries] #11310: is_virtual_base_of has false positives caused by sizeof alignment

Subject: [Boost-bugs] [Boost C++ Libraries] #11310: is_virtual_base_of has false positives caused by sizeof alignment
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2015-05-15 06:14:11


#11310: is_virtual_base_of has false positives caused by sizeof alignment
----------------------------------+-------------------------
 Reporter: leandro.gracia.gil@… | Owner: johnmaddock
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: type_traits
  Version: Boost 1.57.0 | Severity: Problem
 Keywords: |
----------------------------------+-------------------------
 The is_virtual_base_of<Base, Derived> type trait can report virtual bases
 in situations when there isn't any. Here's an example code snippet where
 it fails:

 {{{
 #include <iomanip>
 #include <iostream>
 #include <boost/type_traits.hpp>

 struct A { int a; };
 struct B : public virtual A {};
 struct C : public A { virtual ~C() {} };

 int main() {
   std::cout << std::boolalpha;
   std::cout << "Is A a virtual base of B? " <<
 boost::is_virtual_base_of<A, B>::value << std::endl;
   std::cout << "Is A a virtual base of C? " <<
 boost::is_virtual_base_of<A, C>::value << std::endl;
   return 0;
 }
 }}}

 In the above code both checks are true despite A being a non-virtual base
 of C. The reason for this is that alignment is affecting the results from
 sizeof and it’s making two different sizes seem equal.

 In particular:
 {{{
 sizeof(is_virtual_base_of_impl<A, C,
 mpl::true_>::boost_type_traits_internal_struct_X) == 16
 sizeof(is_virtual_base_of_impl<A, C,
 mpl::true_>::boost_type_traits_internal_struct_Y) == 16
 }}}

 However, if we redefine C as packed (example for gcc / clang):
 {{{
 struct C : public A { virtual ~C() {} } __attribute__((packed);
 }}}

 Then the sizes do mismatch as expected and the result is correct:
 {{{
 sizeof(is_virtual_base_of_impl<A, C,
 mpl::true_>::boost_type_traits_internal_struct_X) == 16
 sizeof(is_virtual_base_of_impl<A, C,
 mpl::true_>::boost_type_traits_internal_struct_Y) == 12
 }}}

 The solution for this problem would be to define the auxiliary types
 ''boost_type_traits_internal_struct_X'' and
 ''boost_type_traits_internal_struct_Y'' as packed in such a way that works
 across all supported compilers. This might be some combination of ''_
 _attribute_ _((packed))'' for gcc/clang, ''#pragma pack'' for the Visual
 C++ compiler and others.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/11310>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:18 UTC