googletest icon indicating copy to clipboard operation
googletest copied to clipboard

GCC 11 enum class operator<< overload in a namespace doesn't work in INSTANTIATE_TEST_SUITE_P

Open BewareMyPower opened this issue 2 years ago • 4 comments

Describe the bug

See the code in the next section. It works well in Ubuntu 20.04 (GCC 9.4.0 and libgtest-dev from apt source), but it doesn't work on Ubuntu 22.04 (GCC 11.3.0 and libgtest-dev from the apt source).

Steps to reproduce the bug

#include <gtest/gtest.h>

#include <iostream>

namespace xyz {

enum class Color
{
    RED,
    GREEN
};

}  // namespace xyz

std::ostream& operator<<(std::ostream& os, const xyz::Color& color);

class ColorTest : public testing::TestWithParam<xyz::Color> {};

TEST_P(ColorTest, test) {}

INSTANTIATE_TEST_SUITE_P(Test, ColorTest, testing::Values(xyz::Color::RED, xyz::Color::GREEN));

int main(int argc, char* argv[]) {
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}

std::ostream& operator<<(std::ostream& os, const xyz::Color& color) {
    return (os << (static_cast<int>(color) + 100));
}

Install g++ and libgtest-dev inside a ubuntu:22.04 docker container. Then compile the code above with:

g++ main.cc  /usr/lib/x86_64-linux-gnu/libgtest.a -pthread

Does the bug persist in the most recent commit?

Not verified yet.

What operating system and version are you using?

The ubuntu:22.04 docker container.

What compiler and version are you using?

g++ (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

What build system are you using?

Additional context

There are various workarounds.

  1. Removing the namespace.
5,6d4
< namespace xyz {
<
13,15c11
< }  // namespace xyz
<
< std::ostream& operator<<(std::ostream& os, const xyz::Color& color);
---
> std::ostream& operator<<(std::ostream& os, const Color& color);
17c13
< class ColorTest : public testing::TestWithParam<xyz::Color> {};
---
> class ColorTest : public testing::TestWithParam<Color> {};
21c17
< INSTANTIATE_TEST_SUITE_P(Test, ColorTest, testing::Values(xyz::Color::RED, xyz::Color::GREEN));
---
> INSTANTIATE_TEST_SUITE_P(Test, ColorTest, testing::Values(Color::RED, Color::GREEN));
28c24
< std::ostream& operator<<(std::ostream& os, const xyz::Color& color) {
---
> std::ostream& operator<<(std::ostream& os, const Color& color) {
  1. Use enum instead of enum class
7c7
< enum class Color
---
> enum Color

BewareMyPower avatar Dec 01 '22 05:12 BewareMyPower

Adding an inline overload also works:

16a17,20
> inline std::ostream& operator<<(std::ostream& os, xyz::Color color) {
>     return (os << static_cast<int>(color));
> }
>

However, it's an ambiguous overload. If we use GetParam() in the test body, the compilation will fail.

TEST_P(ColorTest, test) { std::cout << GetParam() << std::endl; }

BewareMyPower avatar Dec 01 '22 05:12 BewareMyPower

I tried building the master with GCC 9, it also works.

BewareMyPower avatar Dec 01 '22 05:12 BewareMyPower

@BewareMyPower is it known which version of gtest introduces and fixes this?

neheb avatar Aug 24 '23 22:08 neheb

I don't know.

BewareMyPower avatar Aug 25 '23 01:08 BewareMyPower