From 6af608a82734c9fd297a6c0239ed01e97f13470d Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Sun, 4 May 2014 20:28:45 +0400 Subject: [PATCH] =?UTF-8?q?Fixed=20notes=20mentioned=20by=20Klaim=20-=20Jo?= =?UTF-8?q?=C3=ABl=20Lamotte=20during=20review?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/type_index.qbk | 40 ++++++++++++++++---- examples/demangled_names.cpp | 38 ++++++++++++++++--- include/boost/type_index/ctti_type_index.hpp | 2 +- include/boost/type_index/stl_type_index.hpp | 2 +- test/Jamfile.v2 | 6 +++ test/test_lib_anonymous.cpp | 19 ++++++++++ test/test_lib_anonymous.hpp | 34 +++++++++++++++++ test/testing_crossmodule_anonymous.cpp | 28 ++++++++++++++ 8 files changed, 154 insertions(+), 15 deletions(-) create mode 100644 test/test_lib_anonymous.cpp create mode 100644 test/test_lib_anonymous.hpp create mode 100644 test/testing_crossmodule_anonymous.cpp diff --git a/doc/type_index.qbk b/doc/type_index.qbk index b0c484a..fc24a70 100644 --- a/doc/type_index.qbk +++ b/doc/type_index.qbk @@ -180,6 +180,9 @@ will be used. `BOOST_TYPE_INDEX_REGISTER_CLASS` macro is a helper macro that places some virtual helper functions or expands to nothing. +Issues with cross module type comparison on a bugged compilers are bypassed by directly comparing strings with type +(latest versions of those compilers resolved that issue using exactly the same approach). + [endsect] [section Examples] @@ -262,19 +265,23 @@ i [endsect] -[section Compiler support] +[section RTTI emulation limitations] -TypeIndex has been tested and successfully work on MSVC2010, GCC-4.6, Clang-2.9. If your compiler is not -in a list of tested compilers, you must correctly define `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE`, -`BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` macroses: +TypeIndex has been tested and successfully work on many compilers. + +If `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE` macro is not defined or +`BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` +are defined to zero then you are using a compiler that was not tested with this library. +In that case if you wish to use this library with RTTI off, you must correctly define +`BOOST_TYPE_INDEX_FUNCTION_SIGNATURE`, `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and +`BOOST_TYPE_INDEX_CTTI_END_SKIP` macros: # define `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE` to a compiler specific macro, that outputs the *whole* function signature, including template parameters -# define `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `0` -# get the output of `boost::template_id().name()` +# get the output of `boost::typeindex::ctti_type_index::type_id().name()` # set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` equal to characters count before last occurrence of `int` in output # set `BOOST_TYPE_INDEX_CTTI_END_SKIP` equal to characters count after last occurrence of `int` in output -# check that `boost::template_id().name_demangled()` returns "int" +# check that `boost::typeindex::ctti_type_index::type_id().name_demangled()` returns "int" # (optional, but highly recomended) [@http://www.boost.org/support/bugs.html create ticket] with feature request to add your compiler to supported compilers list. Include `BOOST_TYPE_INDEX_FUNCTION_SIGNATURE`, `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and @@ -288,6 +295,25 @@ With `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` set `BOOST_TYPE_INDEX_CTTI_BEGIN_SKIP` to `sizeof("const char *__cdecl boost::detail::ctti<") - 1` and `BOOST_TYPE_INDEX_CTTI_END_SKIP` to `sizeof(">::n(void)") - 1`. +[warning + With RTTI off classes with exactly the same names defined in different modules in anonymous namespaces may collapse: + ``` + // In A.cpp + namespace { struct user_defined{}; } + type_index foo_a() { return type_id(); } + + // In B.cpp + namespace { struct user_defined{}; } + type_index foo_b() { return type_id(); } + + // In main.cpp + assert(foo_a() != foo_b()); // will fail on some compilers + ``` + + *Compilers that have that limitation:* GCC, CLANG. +] + + [endsect] [section Mixing sources with RTTI on and RTTI off] diff --git a/examples/demangled_names.cpp b/examples/demangled_names.cpp index 11f561d..d148b5d 100644 --- a/examples/demangled_names.cpp +++ b/examples/demangled_names.cpp @@ -23,28 +23,54 @@ void foo(T) { struct user_defined_type{}; +namespace ns1 { namespace ns2 { + struct user_defined_type{}; +}} // namespace ns1::ns2 + +namespace { + struct in_anon_type{}; +} // anonymous namespace + int main() { // Call to foo(1); // will output something like this: // - // (RTTI on) (RTTI off) - // Short name: i Short name: int] - // Readable name: int Readable name: int + // (RTTI on) (RTTI off) + // Short name: i Short name: int] + // Readable name: int Readable name: int user_defined_type t; foo(t); // Will output: // - // (RTTI on) (RTTI off) - // Short name: 17user_defined_type user_defined_type] - // Readable name: user_defined_type user_defined_type + // (RTTI on) (RTTI off) + // Short name: 17user_defined_type user_defined_type] + // Readable name: user_defined_type user_defined_type + + ns1::ns2::user_defined_type t_in_ns; + foo(t_in_ns); + // Will output: + // + // (RTTI on) (RTTI off) + // Short name: N3ns13ns217user_defined_typeE ns1::ns2::user_defined_type] + // Readable name: ns1::ns2::user_defined_type ns1::ns2::user_defined_type + + in_anon_type anon_t; + foo(anon_t); + // Will output: + // + // (RTTI on) (RTTI off) + // Short name: N12_GLOBAL__N_112in_anon_typeE {anonymous}::in_anon_type] + // Readable name: (anonymous namespace)::in_anon_type {anonymous}::in_anon_type } /*` Short names are very compiler dependant: some compiler will output `.H`, others `i`. Readable names may also differ between compilers: `struct user_defined_type`, `user_defined_type`. + + [warning With RTTI off different classes with same names in anonymous namespace may collapse. See 'RTTI emulation limitations'. ] */ //] [/type_index_names_example] diff --git a/include/boost/type_index/ctti_type_index.hpp b/include/boost/type_index/ctti_type_index.hpp index 21a9970..120514f 100644 --- a/include/boost/type_index/ctti_type_index.hpp +++ b/include/boost/type_index/ctti_type_index.hpp @@ -70,7 +70,7 @@ inline const detail::ctti_data& ctti_construct() BOOST_NOEXCEPT { /// \class ctti_type_index /// This class is a wrapper that pretends to work exactly like stl_type_index, but does -/// not require RTTI support. For description of functions see type_index_facade. +/// not require RTTI support. \b For \b description \b of \b functions \b see type_index_facade. /// /// This class produces slightly longer type names, so consider using stl_type_index /// in situations when typeid() is working. diff --git a/include/boost/type_index/stl_type_index.hpp b/include/boost/type_index/stl_type_index.hpp index 538aa7d..25a77f6 100644 --- a/include/boost/type_index/stl_type_index.hpp +++ b/include/boost/type_index/stl_type_index.hpp @@ -62,7 +62,7 @@ namespace boost { namespace typeindex { /// \class stl_type_index /// This class is a wrapper around std::type_info, that workarounds issues and provides -/// much more rich interface. For description of functions see type_index_facade. +/// much more rich interface. \b For \b description \b of \b functions \b see type_index_facade. /// /// This class requires typeid() to work. For cases when RTTI is disabled see ctti_type_index. class stl_type_index diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 8690b14..c87713e 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -20,10 +20,14 @@ nortti = gcc:-fno-rtti clang:-fno-rtti shared off ; +obj test_lib_anonymous_nortti-obj : test_lib_anonymous.cpp : shared off ; lib test_lib_nortti : test_lib_nortti-obj : shared off ; +lib test_lib_anonymous_nortti : test_lib_anonymous_nortti-obj : shared off ; obj test_lib_rtti-obj : test_lib.cpp : shared ; +obj test_lib_anonymous_rtti-obj : test_lib_anonymous.cpp : shared ; lib test_lib_rtti : test_lib_rtti-obj : shared ; +lib test_lib_anonymous_rtti : test_lib_anonymous_rtti-obj : shared ; # Making libraries that can work between rtti-on/rtti-off modules obj test_lib_nortti_compat-obj : test_lib.cpp : shared $(nortti) $(compat) ; @@ -38,6 +42,8 @@ test-suite type_index [ run type_index_test.cpp $(tlib) : : : off : type_index_test_no_rtti ] [ run testing_crossmodule.cpp test_lib_rtti $(tlib) ] [ run testing_crossmodule.cpp test_lib_nortti $(tlib) : : : off : testing_crossmodule_no_rtti ] + [ run testing_crossmodule_anonymous.cpp test_lib_anonymous_rtti $(tlib) ] + [ run testing_crossmodule_anonymous.cpp test_lib_anonymous_nortti $(tlib) : : : off : testing_crossmodule_anonymous_no_rtti ] [ compile-fail type_index_test_ctti_copy_fail.cpp ] [ compile-fail type_index_test_ctti_construct_fail.cpp ] [ compile type_index_test_ctti_alignment.cpp ] diff --git a/test/test_lib_anonymous.cpp b/test/test_lib_anonymous.cpp new file mode 100644 index 0000000..8d14a4b --- /dev/null +++ b/test/test_lib_anonymous.cpp @@ -0,0 +1,19 @@ +#define TEST_LIB_SOURCE +#include "test_lib_anonymous.hpp" + +namespace { + class user_defined{}; +} // anonymous namespace + +namespace test_lib { + +boost::typeindex::type_index get_anonymous_user_defined_class() { + return boost::typeindex::type_id(); +} + +boost::typeindex::type_index get_const_anonymous_user_defined_class() { + return boost::typeindex::type_id_with_cvr(); +} + +} + diff --git a/test/test_lib_anonymous.hpp b/test/test_lib_anonymous.hpp new file mode 100644 index 0000000..e18ffe7 --- /dev/null +++ b/test/test_lib_anonymous.hpp @@ -0,0 +1,34 @@ +// +// Copyright (c) Antony Polukhin, 2012-2014. +// +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// + +#ifndef BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP +#define BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP + +// MS compatible compilers support #pragma once +#if defined(_MSC_VER) +# pragma once +#endif + +#include + +// This is ALWAYS a dynamic library +#if defined(TEST_LIB_SOURCE) +# define TEST_LIB_DECL BOOST_SYMBOL_EXPORT +# else +# define TEST_LIB_DECL BOOST_SYMBOL_IMPORT +# endif + +namespace test_lib { + +TEST_LIB_DECL boost::typeindex::type_index get_anonymous_user_defined_class(); +TEST_LIB_DECL boost::typeindex::type_index get_const_anonymous_user_defined_class(); + +} + +#endif // BOOST_TYPE_INDEX_TESTS_TEST_LIB_ANONYMOUS_HPP + diff --git a/test/testing_crossmodule_anonymous.cpp b/test/testing_crossmodule_anonymous.cpp new file mode 100644 index 0000000..d9e2b0e --- /dev/null +++ b/test/testing_crossmodule_anonymous.cpp @@ -0,0 +1,28 @@ +// +// Copyright Antony Polukhin, 2012-2014. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#define BOOST_TEST_MODULE testing_crossmodule_anon_module +#include + +#include +#include "test_lib_anonymous.hpp" + +namespace { + class user_defined{}; +} + +BOOST_AUTO_TEST_CASE(comparing_anonymous_types_between_modules) +{ + boost::typeindex::type_index t_const_userdef = boost::typeindex::type_id_with_cvr(); + boost::typeindex::type_index t_userdef = boost::typeindex::type_id(); + + BOOST_CHECK_NE(t_userdef, test_lib::get_anonymous_user_defined_class()); + BOOST_CHECK_NE(t_const_userdef, test_lib::get_const_anonymous_user_defined_class()); + BOOST_CHECK_NE(t_const_userdef, test_lib::get_anonymous_user_defined_class()); + BOOST_CHECK_NE(t_userdef, test_lib::get_const_anonymous_user_defined_class()); +} +