google / googletest

GoogleTest - Google Testing and Mocking Framework
https://google.github.io/googletest/
BSD 3-Clause "New" or "Revised" License
33.78k stars 10k forks source link

[Bug]: ::testing::Types<T> doesn't work when T is _Float16 #4369

Closed jiawen closed 10 months ago

jiawen commented 10 months ago

Describe the issue

Half-precision floating point is widely used in image processing and is well supported by [GCC](https://gcc.gnu.org/onlinedocs/gcc/Half-Precision.html] and Clang as _Float16. However, it appears to be incompatible with TYPED_TEST_SUITE.

Steps to reproduce the problem

Use TYPED_TEST_SUITE with _Float16 like below:

template <typename T>
class MyTest : public ::testing::Test {};

using ElemTypes = ::testing::Types<float, _Float16, uint16_t>;
TYPED_TEST_SUITE(MyTest, ElemTypes);

This results in the following error on my arm64 Mac.

Undefined symbols for architecture arm64:
  "typeinfo for _Float16", referenced from:
      std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>> testing::internal::GetTypeName<_Float16>() in gaussian_pyramid_test.o
ld: symbol(s) not found for architecture arm64

What version of GoogleTest are you using?

1.11.0

What operating system and version are you using?

MacOS Ventura 13.4

What compiler and version are you using?

$ clang -v
Apple clang version 14.0.3 (clang-1403.0.22.14.1)
Target: arm64-apple-darwin22.5.0
Thread model: posix
InstalledDir: /Applications/Xcode_14.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

What build system are you using?

bazel 6.1.1

Additional context

I assume the problem is because _Float16 is a "primitive" or "trivial" type for which GoogleTest expects std::string testing::internal::GetTypeName<T>() to have specializations. And that it is not a problem for other custom types like a struct.

Indeed, if I add this terrible hack / workaround, the problem goes away:

namespace testing {
namespace internal {

template <>
std::string GetTypeName<_Float16>() {
  return "_Float16";
}

}  // namespace internal
}  // namespace testing

The test runs and I get something that looks like:

[----------] 3 tests from MyTest/1, where TypeParam = _Float16
derekmauro commented 10 months ago

It seems that compilers were missing complete support for this until recently. It works with GCC 12+ and Clang 15+.

jiawen commented 10 months ago

Ah good to know. Xcode 15 should come with Clang 15. Thanks. I'll close this.

jiawen commented 4 months ago

FYI, this still doesn't work with Xcode 15.2 (Apple clang version 15.0.0 (clang-1500.1.0.2.5)).