Please consider the following testcase (reduced from LLVM source):
//% cat foo1.cpp
#include <memory>
namespace {
class A {
int i;
};
}
class G {
std::unique_ptr<A> foo() const;
};
std::unique_ptr<A> G::foo() const { return std::make_unique<A>(); }
and
//% cat foo2.cpp
#include <memory>
namespace {
class A {
bool a;
};
}
class H {
std::unique_ptr<A> bar() const;
};
std::unique_ptr<A> H::bar() const { return std::make_unique<A>(); }
Does this violate the One Definition Rule?
gcc-6 currently thinks so:
~ % g++ -flto -shared -std=c++14 foo1.cpp foo2.cpp
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:187:72: warning: type ‘struct _Base’ violates one definition rule [-Wodr]
typedef _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> _Base;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:187:72: note: a different type is defined in another translation unit
typedef _Head_base<_Idx, _Head, __empty_not_final<_Head>::value> _Base;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:147:13: note: the first difference of corresponding definitions is field ‘_M_head_impl’
_Head _M_head_impl;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:147:13: note: a field of same name but different type is defined in another translation unit
_Head _M_head_impl;
^
foo1.cpp:3:7: note: type ‘struct A’ defined in anonymous namespace can not match type ‘struct A’
class A {
^
foo2.cpp:3:7: note: the incompatible type defined in anonymous namespace in another translation unit
class A {
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:598:40: warning: type ‘struct _Inherited’ violates one definition rule [-Wodr]
typedef _Tuple_impl<0, _T1, _T2> _Inherited;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:598:40: note: a type with the same name but different base type is defined in another translation unit
typedef _Tuple_impl<0, _T1, _T2> _Inherited;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:102:12: note: type ‘struct _Head_base’ defined in anonymous namespace can not match type ‘struct _Head_base’
struct _Head_base<_Idx, _Head, false>
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:102:12: note: the incompatible type defined in anonymous namespace in another translation unit
struct _Head_base<_Idx, _Head, false>
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/bits/unique_ptr.h:151:41: warning: type ‘struct element_type’ violates one definition rule [-Wodr]
typedef _Tp element_type;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/bits/unique_ptr.h:151:41: note: a different type is defined in another translation unit
typedef _Tp element_type;
^
foo1.cpp:4:7: note: the first difference of corresponding definitions is field ‘i’
int i;
^
foo2.cpp:4:8: note: a field with different name is defined in another translation unit
bool a;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:598:40: warning: type ‘struct _Inherited’ violates one definition rule [-Wodr]
typedef _Tuple_impl<0, _T1, _T2> _Inherited;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:598:40: note: a type with the same name but different base type is defined in another translation unit
typedef _Tuple_impl<0, _T1, _T2> _Inherited;
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:102:12: note: type ‘struct _Head_base’ defined in anonymous namespace can not match type ‘struct _Head_base’
struct _Head_base<_Idx, _Head, false>
^
/home/trippels/gcc_test/usr/local/include/c++/6.0.0/tuple:102:12: note: the incompatible type defined in anonymous namespace in another translation unit
struct _Head_base<_Idx, _Head, false>
^
This was GCC bug (which was in the devel tree just for few days). The problem was caused by another fix that made GCC to consider implicit typedefs non-anonymous and thus the outer structures got type merged (incorrectly so). The testcase is fixed now, I would be interested to hear about more warnings that may appear bogus.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With