[go: nahoru, domu]

Bug 66180 - [6 Regression] many -Wodr false positives when building LLVM with -flto
Summary: [6 Regression] many -Wodr false positives when building LLVM with -flto
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: lto (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: 6.0
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-05-17 07:07 UTC by Markus Trippelsdorf
Modified: 2021-12-24 11:14 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Markus Trippelsdorf 2015-05-17 07:07:31 UTC
for example:
trippels@gcc2-power8 llvm_build % cmake -DCMAKE_INSTALL_PREFIX=~/llvm-install -DCMAKE_BUILD_TYPE=release -DLLVM_ENABLE_ASSERTIONS=on -DLLVM_TARGETS_TO_BUILD="PowerPC" -DCMAKE_CXX_FLAGS_RELEASE:STRING="-O3 -DNDEBUG -pipe -flto=60" -DCMAKE_EXE_LINKER_FLAGS="-Wl,-O1,--hash-style=gnu,--gc-sections,--icf=safe" -DENABLE_PIC=1 -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DLLVM_BINUTILS_INCDIR=/home/trippels/include -DCMAKE_C_COMPILER=/home/trippels/gcc_6/usr/local/bin/gcc -DCMAKE_CXX_COMPILER=/home/trippels/gcc_6/usr/local/bin/g++ ~/llvm

trippels@gcc2-power8 llvm_build % make -j120
...
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/ext/aligned_buffer.h:43:12: warning: type ‘struct __aligned_buffer’ violates one definition rule [-Wodr]
     struct __aligned_buffer
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/ext/aligned_buffer.h:43:12: note: a type with the same name but different base type is defined in another translation unit
     struct __aligned_buffer
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/type_traits:1985:12: note: type name ‘std::aligned_storage<104ul, 8ul>’ should match type name ‘std::aligned_storage<96ul, 8ul>’  
     struct aligned_storage
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/type_traits:1985:12: note: the incompatible type is defined here
     struct aligned_storage
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_tree.h:134:12: warning: type ‘struct _Rb_tree_node’ violates one definition rule [-Wodr]
     struct _Rb_tree_node : public _Rb_tree_node_base
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_tree.h:134:12: note: a different type is defined in another translation unit
     struct _Rb_tree_node : public _Rb_tree_node_base
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_tree.h:149:41: note: the first difference of corresponding definitions is field ‘_M_storage’
       __gnu_cxx::__aligned_buffer<_Val> _M_storage;
                                          ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_tree.h:149:41: note: a field of same name but different type is defined in another translation unit
       __gnu_cxx::__aligned_buffer<_Val> _M_storage;
                                          ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/ext/aligned_buffer.h:43:12: note: type ‘struct __aligned_buffer’ should match type ‘struct __aligned_buffer’ that itself violate one definition rule
     struct __aligned_buffer
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/ext/aligned_buffer.h:43:12: note: the incompatible type is defined here
     struct __aligned_buffer
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:96:12: warning: type ‘struct pair’ violates one definition rule [-Wodr]
     struct pair
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:96:12: note: a different type is defined in another translation unit
     struct pair
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:102:11: note: the first difference of corresponding definitions is field ‘second’
       _T2 second;                /// @c second is a copy of the second object
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:102:11: note: a field of same name but different type is defined in another translation unit
       _T2 second;                /// @c second is a copy of the second object
            ^
/home/trippels/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp:131:10: note: type ‘struct GroupInfo’ defined in anonymous namespace can not match type ‘struct GroupInfo’
   struct GroupInfo {
           ^
/home/trippels/llvm/tools/clang/utils/TableGen/ClangSACheckersEmitter.cpp:73:8: note: the incompatible type defined in anonymous namespace in another translation unit
 struct GroupInfo {
         ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:99:19: warning: type ‘struct second_type’ violates one definition rule [-Wodr]
       typedef _T2 second_type;   /// @c second_type is the second bound type
                    ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:99:19: note: a different type is defined in another translation unit
       typedef _T2 second_type;   /// @c second_type is the second bound type
                    ^
/home/trippels/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp:132:32: note: the first difference of corresponding definitions is field ‘DiagsInGroup’
     std::vector<const Record*> DiagsInGroup;
                                 ^
/home/trippels/llvm/tools/clang/utils/TableGen/ClangSACheckersEmitter.cpp:74:33: note: a field with different name is defined in another translation unit
   llvm::DenseSet<const Record*> Checkers;
                                  ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/ext/aligned_buffer.h:43:12: warning: type ‘struct __aligned_buffer’ violates one definition rule [-Wodr]
     struct __aligned_buffer
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/ext/aligned_buffer.h:43:12: note: a type with the same name but different base type is defined in another translation unit
     struct __aligned_buffer
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/type_traits:1985:12: note: type name ‘std::aligned_storage<96ul, 8ul>’ should match type name ‘std::aligned_storage<104ul, 8ul>’  
     struct aligned_storage
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/type_traits:1985:12: note: the incompatible type is defined here
     struct aligned_storage
             ^
...
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:102:12: warning: type ‘struct _Head_base’ violates one definition rule [-Wodr]
     struct _Head_base<_Idx, _Head, false>
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:102:12: note: a different type is defined in another translation unit
     struct _Head_base<_Idx, _Head, false>
             ^
/home/trippels/gcc_6/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_6/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;
              ^
/home/trippels/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp:28:7: note: type ‘struct FunctionArgEnumerator’ defined in anonymous namespace can not match type ‘struct FunctionArgEnumerator’
 class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> {
        ^
/home/trippels/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp:24:7: note: the incompatible type defined in anonymous namespace in another translation unit
 class FunctionArgEnumerator : public IPDBEnumSymbols {
        ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:180:12: warning: type ‘struct _Tuple_impl’ violates one definition rule [-Wodr]
     struct _Tuple_impl<_Idx, _Head, _Tail...>
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:180:12: note: a type with different bases is defined in another translation unit
     struct _Tuple_impl<_Idx, _Head, _Tail...>
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:596:11: warning: type ‘struct tuple’ violates one definition rule [-Wodr]
     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:596:11: note: a type with different bases is defined in another translation unit
     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:129:11: warning: type ‘struct unique_ptr’ violates one definition rule [-Wodr]
     class unique_ptr
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:129:11: note: a different type is defined in another translation unit
     class unique_ptr
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:147:57: note: the first difference of corresponding definitions is field ‘_M_t’
       __tuple_type                                      _M_t;
                                                          ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:147:57: note: a field of same name but different type is defined in another translation unit
       __tuple_type                                      _M_t;
                                                          ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:146:57: note: type ‘struct __tuple_type’ should match type ‘struct __tuple_type’ that itself violate one definition rule
       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
                                                          ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:146:57: note: the incompatible type is defined here
       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
                                                          ^
/home/trippels/gcc_6/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_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:151:41: note: a type with the same name but different base type is defined in another translation unit
       typedef _Tp                       element_type;
                                          ^
/home/trippels/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h:18:37: note: type name ‘llvm::IPDBEnumChildren<llvm::PDBSymbol>’ should match type name ‘llvm::IPDBEnumChildren<llvm::PDBSymbolData>’
 template <typename ChildType> class IPDBEnumChildren {
                                      ^
/home/trippels/llvm/include/llvm/DebugInfo/PDB/IPDBEnumChildren.h:18:37: note: the incompatible type is defined here
 template <typename ChildType> class IPDBEnumChildren {
                                      ^
etc.
Comment 1 Andrew Pinski 2015-05-17 07:12:43 UTC
Some look real to me due to anonymous namespace usage.
Comment 2 Markus Trippelsdorf 2015-05-17 07:19:46 UTC
(In reply to Andrew Pinski from comment #1)
> Some look real to me due to anonymous namespace usage.

Can you elaborate on that? I always thought that anonymous namespaces
where a good tool for fixing ODR issues?
Comment 3 Markus Trippelsdorf 2015-05-17 07:29:45 UTC
BTW gcc-5 crashes when building LLVM with lto (looks like
a dup of PR66027):

Linking CXX executable ../../../../bin/clang
 <nullptr_type 0x3fff800abda8 decltype(nullptr) unsigned DI
    size <integer_cst 0x3fff7f7b1158 type <integer_type 0x3fff7f7e02a0 bitsizetype> constant 64>
    unit size <integer_cst 0x3fff7f7b1170 type <integer_type 0x3fff7f7e01f8 sizetype> constant 8>
    align 8 symtab 0 alias set -1 canonical type 0x3fff7fddac98>
lto1: internal compiler error: in odr_types_equivalent_p, at ipa-devirt.c:1543
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Comment 4 Jan Hubicka 2015-05-19 17:56:20 UTC
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:96:12: warning: type ‘struct pair’ violates one definition rule [-Wodr]
     struct pair
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:96:12: note: a different type is defined in another translation unit
     struct pair
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:102:11: note: the first difference of corresponding definitions is field ‘second’
       _T2 second;                /// @c second is a copy of the second object
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/stl_pair.h:102:11: note: a field of same name but different type is defined in another translation unit
       _T2 second;                /// @c second is a copy of the second object
            ^
/home/trippels/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp:131:10: note: type ‘struct GroupInfo’ defined in anonymous namespace can not match type ‘struct GroupInfo’
   struct GroupInfo {
           ^
/home/trippels/llvm/tools/clang/utils/TableGen/ClangSACheckersEmitter.cpp:73:8: note: the incompatible type defined in anonymous namespace in another translation unit
 struct GroupInfo {
         ^

This looks like a real LLVM bug.  If you do 

class bar {
  anonymous_namespace_type foo; 
}

then definin bar in non-anonymous namespace in more than one unit is ODR violation (because the type of field FOO is different in each of units).  I think that it is what the warning is about: the instantiation is non-anonymous of type _T2=GroupInfo that is anonymous.
Comment 5 Markus Trippelsdorf 2015-05-19 21:26:03 UTC
For example:

 % 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>(); }

 % 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>(); }

 % g++ -flto -shared -std=c++14 foo1.cpp foo2.cpp
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:102:12: warning: type ‘struct _Head_base’ violates one definition rule [-Wodr]
     struct _Head_base<_Idx, _Head, false>
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:102:12: note: a different type is defined in another translation unit
     struct _Head_base<_Idx, _Head, false>
             ^
/home/trippels/gcc_6/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_6/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_6/usr/local/include/c++/6.0.0/tuple:180:12: warning: type ‘struct _Tuple_impl’ violates one definition rule [-Wodr]
     struct _Tuple_impl<_Idx, _Head, _Tail...>
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:180:12: note: a type with different bases is defined in another translation unit
     struct _Tuple_impl<_Idx, _Head, _Tail...>
             ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:596:11: warning: type ‘struct tuple’ violates one definition rule [-Wodr]
     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/tuple:596:11: note: a type with different bases is defined in another translation unit
     class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:129:11: warning: type ‘struct unique_ptr’ violates one definition rule [-Wodr]
     class unique_ptr
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:129:11: note: a different type is defined in another translation unit
     class unique_ptr
            ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:147:57: note: the first difference of corresponding definitions is field ‘_M_t’
       __tuple_type                                      _M_t;
                                                          ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:147:57: note: a field of same name but different type is defined in another translation unit
       __tuple_type                                      _M_t;
                                                          ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:146:57: note: type ‘struct __tuple_type’ should match type ‘struct __tuple_type’ that itself violate one definition rule
       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
                                                          ^
/home/trippels/gcc_6/usr/local/include/c++/6.0.0/bits/unique_ptr.h:146:57: note: the incompatible type is defined here
       typedef std::tuple<typename _Pointer::type, _Dp>  __tuple_type;
                                                          ^
/home/trippels/gcc_6/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_6/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;
         ^
Comment 6 Jan Hubicka 2015-05-19 22:35:44 UTC
Thank you for the testcase! With the fix for anonymous types I don't seem to get the warnings.  Can you, please, check if that works for you and commit it?
Comment 7 Markus Trippelsdorf 2015-05-20 05:31:13 UTC
(In reply to Jan Hubicka from comment #6)
> Thank you for the testcase! With the fix for anonymous types I don't seem to
> get the warnings.  Can you, please, check if that works for you and commit
> it?

I still get the warnings after r223415, but I'm not 100% sure if they
are valid or not.
Comment 8 Markus Trippelsdorf 2015-05-20 14:16:44 UTC
If I change foo1.cpp from comment5 to:

#include <memory>
namespace first{
class A {
  int i;
};
}
using namespace first;
class G {
  std::unique_ptr<A> foo() const;
};
std::unique_ptr<A> G::foo() const { return std::make_unique<A>(); }

it works fine. So it looks like a bug after all, because an anonymous namespace should be equivalent to:

namespace _compiler_generated_name {
...
}
using namespace _compiler_generated_name;
Comment 9 Jan Hubicka 2015-05-21 05:06:54 UTC
I can reproduce these now, too.  Indeed it is a bug - there is template instantiated with anonymous namespace parameter that makes it also anonymous.
Sadly my fix for the false positives of type_in_anonymous_namespace_p also introduces false negatives.
We really need a decision on
https://gcc.gnu.org/ml/gcc-patches/2015-05/msg01245.html
Comment 10 Jan Hubicka 2015-05-24 19:38:45 UTC
Author: hubicka
Date: Sun May 24 19:38:14 2015
New Revision: 223633

URL: https://gcc.gnu.org/viewcvs?rev=223633&root=gcc&view=rev
Log:

	PR lto/66180
	* ipa-devirt.c (type_with_linkage): Check that TYPE_STUB_DECL
	is set; check for assembler name at LTO time.
	(type_in_anonymous_namespace): Remove hacks, check that all
	anonymous types are called "<anon>"
	(odr_type_p): Simplify; add check for "<anon>"
	(odr_subtypes_equivalent): Add odr_type_p check.
	* tree.c (need_assembler_name_p): Even anonymous namespace needs
	assembler name.
	* mangle.c (mangle_decl): Mangle anonymous namespace types as
	"<anon>".
	* g++.dg/lto/pr66180_0.C: New testcase.
	* g++.dg/lto/pr66180_1.C: New testcase.

Added:
    trunk/gcc/testsuite/g++.dg/lto/pr66180_0.C
    trunk/gcc/testsuite/g++.dg/lto/pr66180_1.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cp/ChangeLog
    trunk/gcc/cp/mangle.c
    trunk/gcc/ipa-devirt.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree.c
Comment 11 Markus Trippelsdorf 2015-05-25 05:53:57 UTC
Fixed. LLVM now builds without any warnings. Thanks.