Apply patch for [CVE-2012-2677][boost] ordered_malloc() overflow
[external/boost.git] / boost / python / type_id.hpp
1 // Copyright David Abrahams 2002.
2 // Distributed under the Boost Software License, Version 1.0. (See
3 // accompanying file LICENSE_1_0.txt or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 #ifndef TYPE_ID_DWA2002517_HPP
6 # define TYPE_ID_DWA2002517_HPP
7
8 # include <boost/python/detail/prefix.hpp>
9
10 # include <boost/python/detail/msvc_typeinfo.hpp>
11 # include <boost/operators.hpp>
12 # include <typeinfo>
13 # include <cstring>
14 # include <ostream>
15 # include <boost/static_assert.hpp>
16 # include <boost/detail/workaround.hpp>
17 # include <boost/type_traits/same_traits.hpp>
18 # include <boost/type_traits/broken_compiler_spec.hpp>
19
20 #  ifndef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
21 #   if defined(__GNUC__)                                                \
22     && ((__GNUC__ > 3) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))   \
23     && !defined(__EDG_VERSION__)
24 #    define BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
25 #   endif
26 #  endif
27
28 namespace boost { namespace python { 
29
30 // for this compiler at least, cross-shared-library type_info
31 // comparisons don't work, so use typeid(x).name() instead. It's not
32 // yet clear what the best default strategy is.
33 # if (defined(__GNUC__) && __GNUC__ >= 3) \
34  || defined(_AIX) \
35  || (   defined(__sgi) && defined(__host_mips)) \
36  || (defined(__hpux) && defined(__HP_aCC)) \
37  || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
38 #  define BOOST_PYTHON_TYPE_ID_NAME
39 # endif 
40
41 #ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
42 // Runtime detection of broken cxxabi::__cxa_demangle versions,
43 // to avoid #ifdef clutter.
44 bool cxxabi_cxa_demangle_is_broken();
45 #define BOOST_PYTHON_HAVE_CXXABI_CXA_DEMANGLE_IS_BROKEN
46 #endif
47
48 // type ids which represent the same information as std::type_info
49 // (i.e. the top-level reference and cv-qualifiers are stripped), but
50 // which works across shared libraries.
51 struct type_info : private totally_ordered<type_info>
52 {
53     inline type_info(std::type_info const& = typeid(void));
54     
55     inline bool operator<(type_info const& rhs) const;
56     inline bool operator==(type_info const& rhs) const;
57
58     char const* name() const;
59     friend BOOST_PYTHON_DECL std::ostream& operator<<(
60         std::ostream&, type_info const&);
61     
62  private: // data members
63 #  ifdef BOOST_PYTHON_TYPE_ID_NAME
64     typedef char const* base_id_t;
65 #  else
66     typedef std::type_info const* base_id_t;
67 #  endif
68     
69     base_id_t m_base_type;
70 };
71
72 #  ifdef BOOST_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS
73 #   define BOOST_PYTHON_EXPLICIT_TT_DEF(T) ::boost::type<T>*
74 #  else
75 #   define BOOST_PYTHON_EXPLICIT_TT_DEF(T)
76 #  endif
77
78 template <class T>
79 inline type_info type_id(BOOST_EXPLICIT_TEMPLATE_TYPE(T))
80 {
81     return type_info(
82 #  if !defined(_MSC_VER)                                       \
83       || (!BOOST_WORKAROUND(BOOST_MSVC, <= 1300)                \
84           && !BOOST_WORKAROUND(BOOST_INTEL_CXX_VERSION, <= 700))
85         typeid(T)
86 #  else // strip the decoration which msvc and Intel mistakenly leave in
87         python::detail::msvc_typeid((boost::type<T>*)0)
88 #  endif 
89         );
90 }
91
92 #  if (defined(__EDG_VERSION__) && __EDG_VERSION__ < 245) \
93    || (defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 744)
94 // Older EDG-based compilers seems to mistakenly distinguish "int" from
95 // "signed int", etc., but only in typeid() expressions. However
96 // though int == signed int, the "signed" decoration is propagated
97 // down into template instantiations. Explicit specialization stops
98 // that from taking hold.
99
100 #   define BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(T)              \
101 template <>                                                     \
102 inline type_info type_id<T>(BOOST_PYTHON_EXPLICIT_TT_DEF(T))    \
103 {                                                               \
104     return type_info(typeid(T));                                \
105 }
106
107 BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(short)
108 BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(int)
109 BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long)
110 // using Python's macro instead of Boost's - we don't seem to get the
111 // config right all the time.
112 #   ifdef HAVE_LONG_LONG
113 BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID(long long)
114 #   endif
115 #   undef BOOST_PYTHON_SIGNED_INTEGRAL_TYPE_ID
116 #  endif
117
118 //
119 inline type_info::type_info(std::type_info const& id)
120     : m_base_type(
121 #  ifdef BOOST_PYTHON_TYPE_ID_NAME
122         id.name()
123 #  else
124         &id
125 #  endif
126         )
127 {
128 }
129
130 inline bool type_info::operator<(type_info const& rhs) const
131 {
132 #  ifdef BOOST_PYTHON_TYPE_ID_NAME
133     return std::strcmp(m_base_type, rhs.m_base_type) < 0;
134 #  else
135     return m_base_type->before(*rhs.m_base_type);
136 #  endif 
137 }
138
139 inline bool type_info::operator==(type_info const& rhs) const
140 {
141 #  ifdef BOOST_PYTHON_TYPE_ID_NAME
142     return !std::strcmp(m_base_type, rhs.m_base_type);
143 #  else
144     return *m_base_type == *rhs.m_base_type;
145 #  endif 
146 }
147
148 #  ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
149 namespace detail
150 {
151   BOOST_PYTHON_DECL char const* gcc_demangle(char const*);
152 }
153 #  endif
154     
155 inline char const* type_info::name() const
156 {
157     char const* raw_name
158         = m_base_type
159 #  ifndef BOOST_PYTHON_TYPE_ID_NAME
160           ->name()
161 #  endif
162         ;
163     
164 #  ifdef BOOST_PYTHON_HAVE_GCC_CP_DEMANGLE
165     return detail::gcc_demangle(raw_name);
166 #  else
167     return raw_name;
168 #  endif 
169 }
170
171
172 BOOST_PYTHON_DECL std::ostream& operator<<(std::ostream&, type_info const&);
173
174 #  if !BOOST_WORKAROUND(BOOST_MSVC, == 1200)
175 template<>
176 inline type_info type_id<void>(BOOST_PYTHON_EXPLICIT_TT_DEF(void))
177 {
178     return type_info (typeid (void *));
179 }
180 #   ifndef BOOST_NO_CV_VOID_SPECIALIZATIONS
181 template<>
182 inline type_info type_id<const volatile void>(BOOST_PYTHON_EXPLICIT_TT_DEF(const volatile void))
183 {
184     return type_info (typeid (void *));
185 }
186 #  endif
187
188 # endif 
189
190 }} // namespace boost::python
191
192 #endif // TYPE_ID_DWA2002517_HPP