Std :: make_unique, anonymous namespace and ODR

Please consider the following test test (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 rule of one definition?

gcc-6 now 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> ^ 
+8
c ++ gcc c ++ 14 one-definition-rule
source share
2 answers

This is a GCC bug (which was on the tree tree for only a few days). The problem was caused by another fix that caused GCC to treat implicit typedefs not anonymously, and thus external structures got the type combined (wrong). Now the test file has been fixed, I would be interested to hear more warnings that may seem fictitious.

+6
source share

You have two different class definitions. Compiling these two results leads to a direct conflict, unless the two fall into separate namespaces. I suppose that might be right.

What you might want is whether the two implementation functions are mutually exclusive. There may be two different source files with separate definitions, but there are times when two definitions may make sense (i.e. I have a stream processing API on Windows and Linux, and I need to have two different definitions based on my compilation settings) .

-2
source share

All Articles