aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Vakulenko <avakulenko@google.com>2016-01-04 20:09:16 +0000
committerandroid-build-merger <android-build-merger@google.com>2016-01-04 20:09:16 +0000
commit4118d02beeb19b87f11575b57877c69c13d9a40c (patch)
tree02dc0e9696579855b42296d94aaee90f1ea896f1
parent5493d1ee1bbff0ce1b848ff52a6669f031caff24 (diff)
parent4d8501c1f9689c833d38c9087df28b971a6ebe42 (diff)
downloadplatform_external_libbrillo-4118d02beeb19b87f11575b57877c69c13d9a40c.tar.gz
platform_external_libbrillo-4118d02beeb19b87f11575b57877c69c13d9a40c.tar.bz2
platform_external_libbrillo-4118d02beeb19b87f11575b57877c69c13d9a40c.zip
libbrillo: Remove RTTI from the library
am: 4d8501c1f9 * commit '4d8501c1f9689c833d38c9087df28b971a6ebe42': libbrillo: Remove RTTI from the library
-rw-r--r--Android.mk16
-rw-r--r--brillo/any.cc6
-rw-r--r--brillo/any.h22
-rw-r--r--brillo/any_internal_impl.h8
-rw-r--r--brillo/any_internal_impl_unittest.cc31
-rw-r--r--brillo/any_unittest.cc14
-rw-r--r--brillo/dbus/exported_property_set_unittest.cc2
-rw-r--r--brillo/type_name_undecorate.cc35
-rw-r--r--brillo/type_name_undecorate.h44
-rw-r--r--brillo/type_name_undecorate_unittest.cc61
-rw-r--r--libbrillo.gypi1
11 files changed, 175 insertions, 65 deletions
diff --git a/Android.mk b/Android.mk
index 2819b1c..2181a3a 100644
--- a/Android.mk
+++ b/Android.mk
@@ -122,6 +122,7 @@ libbrillo_test_sources := \
brillo/streams/stream_unittest.cc \
brillo/streams/stream_utils_unittest.cc \
brillo/strings/string_utils_unittest.cc \
+ brillo/type_name_undecorate_unittest.cc \
brillo/unittest_utils.cc \
brillo/url_utils_unittest.cc \
@@ -159,7 +160,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries)
LOCAL_STATIC_LIBRARIES := libmodpb64
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
@@ -175,7 +175,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) \
libbinder libutils
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
@@ -193,7 +192,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) libbrillo \
libchrome-dbus libdbus
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) external/dbus
include $(BUILD_SHARED_LIBRARY)
@@ -212,7 +210,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) libbrillo \
libminijail
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
@@ -228,7 +225,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) libbrillo \
libcrypto libssl
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
@@ -244,7 +240,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) libbrillo \
libbrillo-stream libcurl
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
@@ -259,7 +254,6 @@ LOCAL_C_INCLUDES := $(libbrillo_includes)
LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries)
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
@@ -276,7 +270,6 @@ LOCAL_STATIC_LIBRARIES := libmodpb64
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
LOCAL_CLANG := true
-LOCAL_RTTI_FLAG := -frtti
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_STATIC_LIBRARY)
@@ -293,7 +286,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) libbrillo libcurl \
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS) -Wno-sign-compare
LOCAL_CLANG := true
-LOCAL_RTTI_FLAG := -frtti
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_STATIC_LIBRARY)
@@ -308,7 +300,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries)
LOCAL_STATIC_LIBRARIES := libmodpb64-host
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_HOST_SHARED_LIBRARY)
@@ -326,7 +317,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) libbrillo \
libcrypto-host libssl-host
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_HOST_SHARED_LIBRARY)
@@ -342,7 +332,6 @@ LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) libbrillo \
libbrillo-stream libcurl-host
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS)
-LOCAL_RTTI_FLAG := -frtti
LOCAL_CLANG := true
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
include $(BUILD_HOST_SHARED_LIBRARY)
@@ -366,7 +355,7 @@ LOCAL_C_INCLUDES := \
LOCAL_STATIC_LIBRARIES := libgtest libchrome_test_helpers \
libbrillo-test-helpers libgmock libBionicGtestMain
LOCAL_SHARED_LIBRARIES := $(libbrillo_shared_libraries) libbrillo libcurl \
- libbrillo-http libbrillo-stream libcrypto libprotobuf-cpp-lite-rtti
+ libbrillo-http libbrillo-stream libcrypto libprotobuf-cpp-lite
ifeq ($(BRILLO_USE_DBUS),1)
LOCAL_SRC_FILES += $(libbrillo_dbus_test_sources)
LOCAL_STATIC_LIBRARIES += libchrome_dbus_test_helpers
@@ -375,7 +364,6 @@ endif # BRILLO_USE_DBUS == 1
LOCAL_CFLAGS := $(libbrillo_CFLAGS)
LOCAL_CPPFLAGS := $(libbrillo_CPPFLAGS) -Wno-sign-compare
LOCAL_CLANG := true
-LOCAL_RTTI_FLAG := -frtti
include $(BUILD_NATIVE_TEST)
# Run unit tests on target
diff --git a/brillo/any.cc b/brillo/any.cc
index d2313c5..f84badf 100644
--- a/brillo/any.cc
+++ b/brillo/any.cc
@@ -34,7 +34,7 @@ Any& Any::operator=(Any&& rhs) {
bool Any::operator==(const Any& rhs) const {
// Make sure both objects contain data of the same type.
- if (strcmp(GetTypeNameInternal(), rhs.GetTypeNameInternal()) != 0)
+ if (strcmp(GetTypeTagInternal(), rhs.GetTypeTagInternal()) != 0)
return false;
if (IsEmpty())
@@ -43,9 +43,9 @@ bool Any::operator==(const Any& rhs) const {
return data_buffer_.GetDataPtr()->CompareEqual(rhs.data_buffer_.GetDataPtr());
}
-const char* Any::GetTypeNameInternal() const {
+const char* Any::GetTypeTagInternal() const {
if (!IsEmpty())
- return data_buffer_.GetDataPtr()->GetTypeName();
+ return data_buffer_.GetDataPtr()->GetTypeTag();
return "";
}
diff --git a/brillo/any.h b/brillo/any.h
index feedc73..51016b5 100644
--- a/brillo/any.h
+++ b/brillo/any.h
@@ -83,8 +83,8 @@ class BRILLO_EXPORT Any final {
// to make sure the requested type matches the type of data actually stored,
// so this "canonical" type is used for type checking below.
using CanonicalDestType = typename std::decay<DestType>::type;
- const char* contained_type = GetTypeNameInternal();
- if (strcmp(typeid(CanonicalDestType).name(), contained_type) == 0)
+ const char* contained_type = GetTypeTagInternal();
+ if (strcmp(GetTypeTag<CanonicalDestType>(), contained_type) == 0)
return true;
if (!std::is_pointer<CanonicalDestType>::value)
@@ -97,17 +97,17 @@ class BRILLO_EXPORT Any final {
using NonPointer = typename std::remove_pointer<CanonicalDestType>::type;
using CanonicalDestTypeNoConst = typename std::add_pointer<
typename std::remove_const<NonPointer>::type>::type;
- if (strcmp(typeid(CanonicalDestTypeNoConst).name(), contained_type) == 0)
+ if (strcmp(GetTypeTag<CanonicalDestTypeNoConst>(), contained_type) == 0)
return true;
using CanonicalDestTypeNoVolatile = typename std::add_pointer<
typename std::remove_volatile<NonPointer>::type>::type;
- if (strcmp(typeid(CanonicalDestTypeNoVolatile).name(), contained_type) == 0)
+ if (strcmp(GetTypeTag<CanonicalDestTypeNoVolatile>(), contained_type) == 0)
return true;
using CanonicalDestTypeNoConstOrVolatile = typename std::add_pointer<
typename std::remove_cv<NonPointer>::type>::type;
- return strcmp(typeid(CanonicalDestTypeNoConstOrVolatile).name(),
+ return strcmp(GetTypeTag<CanonicalDestTypeNoConstOrVolatile>(),
contained_type) == 0;
}
@@ -162,13 +162,9 @@ class BRILLO_EXPORT Any final {
return TryGet<T>(typename std::decay<T>::type());
}
- // Returns the name of the type contained within Any. The string is a mangled
- // type name returned by type_info::name(). For most cases, instead of using
- // this function, you should be calling IsTypeCompatible<>().
- inline std::string GetTypeName() const { return GetTypeNameInternal(); }
// Returns the undecorated name of the type contained within Any.
inline std::string GetUndecoratedTypeName() const {
- return UndecorateTypeName(GetTypeNameInternal());
+ return GetUndecoratedTypeNameForTag(GetTypeTagInternal());
}
// Swaps the value of this object with that of |other|.
void Swap(Any& other);
@@ -196,9 +192,9 @@ class BRILLO_EXPORT Any final {
void AppendToDBusMessageWriter(dbus::MessageWriter* writer) const;
private:
- // Internal implementation of GetTypeName() which returns just a char* to
- // static type name buffer.
- const char* GetTypeNameInternal() const;
+ // Returns a pointer to a static buffer containing type tag (sort of a type
+ // name) of the contained value.
+ const char* GetTypeTagInternal() const;
// The data buffer for contained object.
internal_details::Buffer data_buffer_;
diff --git a/brillo/any_internal_impl.h b/brillo/any_internal_impl.h
index d4fa39e..0154d4d 100644
--- a/brillo/any_internal_impl.h
+++ b/brillo/any_internal_impl.h
@@ -142,8 +142,8 @@ class Buffer; // Forward declaration of data buffer container.
// Abstract base class for contained variant data.
struct Data {
virtual ~Data() {}
- // Returns the type name for the contained data.
- virtual const char* GetTypeName() const = 0;
+ // Returns the type tag (name) for the contained data.
+ virtual const char* GetTypeTag() const = 0;
// Copies the contained data to the output |buffer|.
virtual void CopyTo(Buffer* buffer) const = 0;
// Moves the contained data to the output |buffer|.
@@ -165,7 +165,7 @@ struct TypedData : public Data {
// NOLINTNEXTLINE(build/c++11)
explicit TypedData(T&& value) : value_(std::move(value)) {}
- const char* GetTypeName() const override { return typeid(T).name(); }
+ const char* GetTypeTag() const override { return brillo::GetTypeTag<T>(); }
void CopyTo(Buffer* buffer) const override;
void MoveTo(Buffer* buffer) override;
bool IsConvertibleToInteger() const override {
@@ -268,7 +268,7 @@ class Buffer final {
using Type = typename std::decay<T>::type;
using DataType = TypedData<Type>;
Data* ptr = GetDataPtr();
- if (ptr && strcmp(ptr->GetTypeName(), typeid(Type).name()) == 0) {
+ if (ptr && strcmp(ptr->GetTypeTag(), GetTypeTag<Type>()) == 0) {
// We assign the data to the variant container, which already
// has the data of the same type. Do fast copy/move with no memory
// reallocation.
diff --git a/brillo/any_internal_impl_unittest.cc b/brillo/any_internal_impl_unittest.cc
index 4f39939..6f7f512 100644
--- a/brillo/any_internal_impl_unittest.cc
+++ b/brillo/any_internal_impl_unittest.cc
@@ -8,6 +8,7 @@
#include <gtest/gtest.h>
using brillo::internal_details::Buffer;
+using brillo::GetTypeTag;
TEST(Buffer, Empty) {
Buffer buffer;
@@ -21,7 +22,7 @@ TEST(Buffer, Store_Int) {
buffer.Assign(2);
EXPECT_FALSE(buffer.IsEmpty());
EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_STREQ(typeid(int).name(), buffer.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<int>(), buffer.GetDataPtr()->GetTypeTag());
}
TEST(Buffer, Store_Double) {
@@ -29,7 +30,7 @@ TEST(Buffer, Store_Double) {
buffer.Assign(2.3);
EXPECT_FALSE(buffer.IsEmpty());
EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_STREQ(typeid(double).name(), buffer.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<double>(), buffer.GetDataPtr()->GetTypeTag());
}
TEST(Buffer, Store_Pointers) {
@@ -38,14 +39,14 @@ TEST(Buffer, Store_Pointers) {
buffer.Assign(nullptr);
EXPECT_FALSE(buffer.IsEmpty());
EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_STREQ(typeid(std::nullptr_t).name(),
- buffer.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<std::nullptr_t>(),
+ buffer.GetDataPtr()->GetTypeTag());
// char *
buffer.Assign("abcd");
EXPECT_FALSE(buffer.IsEmpty());
EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_STREQ(typeid(const char*).name(), buffer.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<const char*>(), buffer.GetDataPtr()->GetTypeTag());
// pointer to non-trivial object
class NonTrivial {
@@ -55,7 +56,7 @@ TEST(Buffer, Store_Pointers) {
buffer.Assign(&non_trivial);
EXPECT_FALSE(buffer.IsEmpty());
EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_STREQ(typeid(NonTrivial*).name(), buffer.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<NonTrivial*>(), buffer.GetDataPtr()->GetTypeTag());
}
TEST(Buffer, Store_NonTrivialObjects) {
@@ -67,7 +68,7 @@ TEST(Buffer, Store_NonTrivialObjects) {
buffer.Assign(non_trivial);
EXPECT_FALSE(buffer.IsEmpty());
EXPECT_EQ(Buffer::kExternal, buffer.storage_);
- EXPECT_STREQ(typeid(NonTrivial).name(), buffer.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<NonTrivial>(), buffer.GetDataPtr()->GetTypeTag());
}
TEST(Buffer, Store_Objects) {
@@ -79,7 +80,7 @@ TEST(Buffer, Store_Objects) {
buffer.Assign(small);
EXPECT_FALSE(buffer.IsEmpty());
EXPECT_EQ(Buffer::kContained, buffer.storage_);
- EXPECT_STREQ(typeid(Small).name(), buffer.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<Small>(), buffer.GetDataPtr()->GetTypeTag());
struct Large {
char c[20];
@@ -87,7 +88,7 @@ TEST(Buffer, Store_Objects) {
buffer.Assign(large);
EXPECT_FALSE(buffer.IsEmpty());
EXPECT_EQ(Buffer::kExternal, buffer.storage_);
- EXPECT_STREQ(typeid(Large).name(), buffer.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<Large>(), buffer.GetDataPtr()->GetTypeTag());
}
TEST(Buffer, Copy) {
@@ -98,8 +99,8 @@ TEST(Buffer, Copy) {
buffer1.CopyTo(&buffer2);
EXPECT_FALSE(buffer1.IsEmpty());
EXPECT_FALSE(buffer2.IsEmpty());
- EXPECT_STREQ(typeid(int).name(), buffer1.GetDataPtr()->GetTypeName());
- EXPECT_STREQ(typeid(int).name(), buffer2.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<int>(), buffer1.GetDataPtr()->GetTypeTag());
+ EXPECT_STREQ(GetTypeTag<int>(), buffer2.GetDataPtr()->GetTypeTag());
EXPECT_EQ(30, buffer1.GetData<int>());
EXPECT_EQ(30, buffer2.GetData<int>());
@@ -107,8 +108,8 @@ TEST(Buffer, Copy) {
buffer1.CopyTo(&buffer2);
EXPECT_FALSE(buffer1.IsEmpty());
EXPECT_FALSE(buffer2.IsEmpty());
- EXPECT_STREQ(typeid(std::string).name(), buffer1.GetDataPtr()->GetTypeName());
- EXPECT_STREQ(typeid(std::string).name(), buffer2.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<std::string>(), buffer1.GetDataPtr()->GetTypeTag());
+ EXPECT_STREQ(GetTypeTag<std::string>(), buffer2.GetDataPtr()->GetTypeTag());
EXPECT_EQ("abc", buffer1.GetData<std::string>());
EXPECT_EQ("abc", buffer2.GetData<std::string>());
}
@@ -128,7 +129,7 @@ TEST(Buffer, Move) {
// the data and any retains the actual type.
EXPECT_FALSE(buffer1.IsEmpty());
EXPECT_FALSE(buffer2.IsEmpty());
- EXPECT_STREQ(typeid(int).name(), buffer2.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<int>(), buffer2.GetDataPtr()->GetTypeTag());
EXPECT_EQ(30, buffer2.GetData<int>());
buffer1.Assign(std::string("abc"));
@@ -137,6 +138,6 @@ TEST(Buffer, Move) {
// This will make the source object effectively "Empty".
EXPECT_TRUE(buffer1.IsEmpty());
EXPECT_FALSE(buffer2.IsEmpty());
- EXPECT_STREQ(typeid(std::string).name(), buffer2.GetDataPtr()->GetTypeName());
+ EXPECT_STREQ(GetTypeTag<std::string>(), buffer2.GetDataPtr()->GetTypeTag());
EXPECT_EQ("abc", buffer2.GetData<std::string>());
}
diff --git a/brillo/any_unittest.cc b/brillo/any_unittest.cc
index 2af8845..db89884 100644
--- a/brillo/any_unittest.cc
+++ b/brillo/any_unittest.cc
@@ -305,20 +305,6 @@ TEST(Any, Compare_NonComparable) {
EXPECT_NE(person2, person3);
}
-TEST(Any, GetTypeName) {
- Any val;
- EXPECT_TRUE(val.GetTypeName().empty());
-
- val = 1;
- EXPECT_EQ(typeid(int).name(), val.GetTypeName());
-
- val = 3.1415926;
- EXPECT_EQ(typeid(double).name(), val.GetTypeName());
-
- val = std::string("blah");
- EXPECT_EQ(typeid(std::string).name(), val.GetTypeName());
-}
-
TEST(Any, GetUndecoratedTypeName) {
Any val;
EXPECT_TRUE(val.GetUndecoratedTypeName().empty());
diff --git a/brillo/dbus/exported_property_set_unittest.cc b/brillo/dbus/exported_property_set_unittest.cc
index c0deace..9233b4a 100644
--- a/brillo/dbus/exported_property_set_unittest.cc
+++ b/brillo/dbus/exported_property_set_unittest.cc
@@ -133,7 +133,7 @@ class ExportedPropertySetTest : public ::testing::Test {
void AssertMethodReturnsError(dbus::MethodCall* method_call) {
method_call->SetSerial(123);
auto response = testing::CallMethod(p_->dbus_object_, method_call);
- ASSERT_NE(dynamic_cast<dbus::ErrorResponse*>(response.get()), nullptr);
+ ASSERT_EQ(dbus::Message::MESSAGE_ERROR, response->GetMessageType());
}
std::unique_ptr<dbus::Response> GetPropertyOnInterface(
diff --git a/brillo/type_name_undecorate.cc b/brillo/type_name_undecorate.cc
index 9a1d6a1..b588170 100644
--- a/brillo/type_name_undecorate.cc
+++ b/brillo/type_name_undecorate.cc
@@ -4,6 +4,8 @@
#include <brillo/type_name_undecorate.h>
+#include <cstring>
+
#ifdef __GNUG__
#include <cstdlib>
#include <cxxabi.h>
@@ -30,4 +32,37 @@ std::string UndecorateTypeName(const char* type_name) {
#endif
}
+std::string GetUndecoratedTypeNameForTag(const char* type_tag) {
+#if defined(USE_RTTI_FOR_TYPE_TAGS) && \
+ (defined(__cpp_rtti) || defined(__GXX_RTTI))
+ return UndecorateTypeName(type_tag);
+#else
+ // The signature of type tag for, say, 'int' would be the following:
+ // const char *brillo::GetTypeTag() [T = int]
+ // So we just need to extract the type name between '[T = ' and ']'.
+ const char* token = " = ";
+ const char* pos = std::strstr(type_tag, token);
+ if (!pos)
+ return type_tag;
+ std::string name = pos + std::strlen(token);
+ if (!name.empty() && name.back() == ']')
+ name.pop_back();
+ return name;
+#endif
+}
+
+// Implementations of the explicitly instantiated GetTypeTag<T>() for common
+// types.
+template const char* GetTypeTag<int8_t>();
+template const char* GetTypeTag<uint8_t>();
+template const char* GetTypeTag<int16_t>();
+template const char* GetTypeTag<uint16_t>();
+template const char* GetTypeTag<int32_t>();
+template const char* GetTypeTag<uint32_t>();
+template const char* GetTypeTag<int64_t>();
+template const char* GetTypeTag<uint64_t>();
+template const char* GetTypeTag<bool>();
+template const char* GetTypeTag<double>();
+template const char* GetTypeTag<std::string>();
+
} // namespace brillo
diff --git a/brillo/type_name_undecorate.h b/brillo/type_name_undecorate.h
index 8cf9030..c750e58 100644
--- a/brillo/type_name_undecorate.h
+++ b/brillo/type_name_undecorate.h
@@ -10,16 +10,58 @@
#include <brillo/brillo_export.h>
+#if !defined(USE_RTTI_FOR_TYPE_TAGS) && !defined(__clang__)
+// When type information is used with RTTI disabled, we rely on
+// __PRETTY_FUNCTION__ macro for type tags. Unfortunately gcc and clang produce
+// different signatures for types that have optional template parameters, such
+// as std::vector and std::map. The problem arises when inter-operating between
+// libraries that are compiled with different compilers.
+// Since most of Brillo is compiled with clang, we choose clang here exclusively
+// and prevent this code from compiling with GCC to avoid hidden runtime errors.
+#error TypeInfo/Any with RTTI disabled is supported on clang compiler only.
+#endif
+
namespace brillo {
+template<typename T>
+const char* GetTypeTag() {
+#if defined(USE_RTTI_FOR_TYPE_TAGS) && \
+ (defined(__cpp_rtti) || defined(__GXX_RTTI))
+ return typeid(T).name();
+#else
+ // __PRETTY_FUNCTION__ would include the type T signature and therefore each
+ // instance of brillo::internal_details::GetTypeTag<T>() will have a different
+ // tag string.
+ return __PRETTY_FUNCTION__;
+#endif
+}
+
+// Explicitly instantiate GetTypeTag<T>() for common types to minimize static
+// data segment pollution.
+extern template BRILLO_EXPORT const char* GetTypeTag<int8_t>();
+extern template BRILLO_EXPORT const char* GetTypeTag<uint8_t>();
+extern template BRILLO_EXPORT const char* GetTypeTag<int16_t>();
+extern template BRILLO_EXPORT const char* GetTypeTag<uint16_t>();
+extern template BRILLO_EXPORT const char* GetTypeTag<int32_t>();
+extern template BRILLO_EXPORT const char* GetTypeTag<uint32_t>();
+extern template BRILLO_EXPORT const char* GetTypeTag<int64_t>();
+extern template BRILLO_EXPORT const char* GetTypeTag<uint64_t>();
+extern template BRILLO_EXPORT const char* GetTypeTag<bool>();
+extern template BRILLO_EXPORT const char* GetTypeTag<double>();
+extern template BRILLO_EXPORT const char* GetTypeTag<std::string>();
+
// Use brillo::UndecorateTypeName() to obtain human-readable type from
// the decorated/mangled type name returned by std::type_info::name().
BRILLO_EXPORT std::string UndecorateTypeName(const char* type_name);
+// Returns undecorated type name for the given type tag. This will extract the
+// actual type name from the type tag string.
+BRILLO_EXPORT std::string GetUndecoratedTypeNameForTag(const char* type_tag);
+
// A template helper function that returns the undecorated type name for type T.
template<typename T>
inline std::string GetUndecoratedTypeName() {
- return UndecorateTypeName(typeid(T).name());
+ return GetUndecoratedTypeNameForTag(GetTypeTag<T>());
}
} // namespace brillo
diff --git a/brillo/type_name_undecorate_unittest.cc b/brillo/type_name_undecorate_unittest.cc
new file mode 100644
index 0000000..04c1c5e
--- /dev/null
+++ b/brillo/type_name_undecorate_unittest.cc
@@ -0,0 +1,61 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <brillo/type_name_undecorate.h>
+
+#include <brillo/variant_dictionary.h>
+#include <gtest/gtest.h>
+
+namespace brillo {
+
+TEST(TypeTags, GetTypeTag) {
+ EXPECT_STREQ("const char *brillo::GetTypeTag() [T = int]", GetTypeTag<int>());
+ EXPECT_STREQ("const char *brillo::GetTypeTag() [T = std::__1::map<std::__1::"
+ "basic_string<char, std::__1::char_traits<char>, "
+ "std::__1::allocator<char> >, brillo::Any, std::__1::less<"
+ "std::__1::basic_string<char, std::__1::char_traits<char>, "
+ "std::__1::allocator<char> > >, std::__1::allocator<std::__1::"
+ "pair<const std::__1::basic_string<char, std::__1::char_traits"
+ "<char>, std::__1::allocator<char> >, brillo::Any> > >]",
+ GetTypeTag<VariantDictionary>());
+ EXPECT_STREQ("const char *brillo::GetTypeTag() [T = int []]",
+ GetTypeTag<int[]>());
+}
+
+TEST(TypeDecoration, UndecorateTypeName) {
+ EXPECT_EQ("int", UndecorateTypeName("i"));
+ EXPECT_EQ("char const* brillo::GetTypeTag<unsigned long long>()",
+ UndecorateTypeName("_ZN6brillo10GetTypeTagIyEEPKcv"));
+ EXPECT_EQ("std::__1::to_string(int)",
+ UndecorateTypeName("_ZNSt3__19to_stringEi"));
+}
+
+TEST(TypeDecoration, GetUndecoratedTypeNameForTag) {
+ EXPECT_EQ("int",
+ GetUndecoratedTypeNameForTag(
+ "const char *brillo::GetTypeTag() [T = int]"));
+ EXPECT_EQ("int []",
+ GetUndecoratedTypeNameForTag(
+ "const char *brillo::GetTypeTag() [T = int []]"));
+ EXPECT_EQ("foo::bar<int []>()",
+ GetUndecoratedTypeNameForTag(
+ "const char *brillo::GetTypeTag() [T = foo::bar<int []>()]"));
+}
+
+TEST(TypeDecoration, GetUndecoratedTypeName) {
+ EXPECT_EQ("int", GetUndecoratedTypeName<int>());
+ EXPECT_EQ("int *", GetUndecoratedTypeName<int*>());
+ EXPECT_EQ("const int *", GetUndecoratedTypeName<const int*>());
+ EXPECT_EQ("int []", GetUndecoratedTypeName<int[]>());
+ EXPECT_EQ("bool", GetUndecoratedTypeName<bool>());
+ EXPECT_EQ("char", GetUndecoratedTypeName<char>());
+ EXPECT_EQ("float", GetUndecoratedTypeName<float>());
+ EXPECT_EQ("double", GetUndecoratedTypeName<double>());
+ EXPECT_EQ("long", GetUndecoratedTypeName<long>());
+ EXPECT_EQ("std::__1::map<int, double, std::__1::less<int>, "
+ "std::__1::allocator<std::__1::pair<const int, double> > >",
+ (GetUndecoratedTypeName<std::map<int, double>>()));
+}
+
+} // namespace brillo
diff --git a/libbrillo.gypi b/libbrillo.gypi
index 6dec2e4..d39290f 100644
--- a/libbrillo.gypi
+++ b/libbrillo.gypi
@@ -353,6 +353,7 @@
'brillo/streams/stream_unittest.cc',
'brillo/streams/stream_utils_unittest.cc',
'brillo/strings/string_utils_unittest.cc',
+ 'brillo/type_name_undecorate_unittest.cc',
'brillo/unittest_utils.cc',
'brillo/url_utils_unittest.cc',
'brillo/variant_dictionary_unittest.cc',