Opened 7 years ago

Closed 7 years ago

#11309 closed Bugs (fixed)

is_virtual_base_of has false positives caused by sizeof alignment

Reported by: leandro.gracia.gil@… Owned by: John Maddock
Milestone: To Be Determined Component: type_traits
Version: Boost 1.57.0 Severity: Problem
Keywords: Cc:

Description

The is_virtual_base_of type<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.

Change History (1)

comment:1 by John Maddock, 7 years ago

Resolution: fixed
Status: newclosed
Note: See TracTickets for help on using tickets.