Open Quuxplusone opened 12 years ago
Bugzilla Link | PR12727 |
Status | NEW |
Importance | P normal |
Reported by | Luc Bourhis (luc_j_bourhis@mac.com) |
Reported on | 2012-05-02 11:40:59 -0700 |
Last modified on | 2012-05-05 21:58:08 -0700 |
Version | trunk |
Hardware | PC All |
CC | dgregor@apple.com, efriedma@quicinc.com, llvm-bugs@lists.llvm.org, mimomorin@gmail.com |
Fixed by commit(s) | |
Attachments | |
Blocks | |
Blocked by | |
See also |
Thanks Luc for pointing this out. My intention of the change to Boost.TypeTraits
-# if has_feature(is_pod) && defined(_LIBCPP_VERSION) +# if (has_feature(is_pod) && defined(_LIBCPP_VERSION)) || has_feature(__is_pod)
was to allow the use of clang's __is_pod
type traits intrinsic
when used with libstdc++ newer than 4.2.
But it seems that this introduces some subtlety when used with libstdc++ 4.2.
Here is a minimal code which fails to compile with libstdc++ 4.2.
#if __has_feature(__is_pod__)
# define MY_IS_POD(T) __is_pod(T)
#else
# define MY_IS_POD(T) false
#endif
// The following include brings libstdc++'s `struct __is_pod`;
// this turns off clang's `__is_pod` type traits intrinsic.
#include <iostream>
template <typename T>
struct my_is_pod
{
// Here, clang's `__is_pod` type traits intrinsic is turned off;
// `__is_pod` is considered as libstdc++'s `struct __is_pod`.
static const bool value = MY_IS_POD(T);
};
int main (int argc, char* argv[])
{
std::cout << my_is_pod<int>::value << std::endl; // --> error
return 0;
}
The problem in the code is that detection of __is_pod
intrinsics is done
before libstdc++'s struct __is_pod
is introduced,
but the use of __is_pod
intrinsics is done
after libstdc++'s struct __is_pod
is introduced.
The following two variants of the codes compile fine with libstdc++ 4.2.
A.
#if __has_feature(__is_pod__)
# define MY_IS_POD(T) __is_pod(T)
#else
# define MY_IS_POD(T) false
#endif
template <typename T>
struct my_is_pod
{
static const bool value = MY_IS_POD(T);
};
int main (int argc, char* argv[])
{
std::cout << my_is_pod<int>::value << std::endl; // --> 0
return 0;
}
B.
# define MY_IS_POD(T) __is_pod(T)
#else
# define MY_IS_POD(T) false
#endif
template <typename T>
struct my_is_pod
{
static const bool value = MY_IS_POD(T);
};
#include <iostream>
int main (int argc, char* argv[])
{
std::cout << my_is_pod<int>::value << std::endl; // --> 1
return 0;
}
I can work around the issue by adding the following code to the Boost's type traits intrinsics detection code:
#if __has_include(<bits/cpp_type_traits.h>)
# include <bits/cpp_type_traits.h>
#endif
This ensures that libstdc++'s struct __is_pod
is introduced before
the type traits intrinsics detection.
Thoughts?
Fixed Boost.TypeTraits (unconditionally disallow the use of clang's __is_pod
and __is_empty intrinsics when used with libstdc++ 4.2):
https://svn.boost.org/trac/boost/changeset/78344
Thanks Luc for reporting. Also, thanks Eli for Cc'ing me.