When building gdb with -O2 -flto -Wall, I run into a cluster of odr violations in dir opcodes: ... /labs/tdevries/gdb/src/gdb/../opcodes/mep-desc.h:250:14: warning: type 'cgen_operand_type' violates the C++ One Definition Rule [-Wodr] typedef enum cgen_operand_type { ^ /labs/tdevries/gdb/src/gdb/../opcodes/or1k-desc.h:624:14: note: an enum with different value name is defined in another translation unit typedef enum cgen_operand_type { ^ /labs/tdevries/gdb/src/gdb/../opcodes/mep-desc.h:212:14: warning: type 'cgen_hw_type' violates the C++ One Definition Rule [-Wodr] typedef enum cgen_hw_type { ^ /labs/tdevries/gdb/src/gdb/../opcodes/or1k-desc.h:433:14: note: an enum with different value name is defined in another translation unit typedef enum cgen_hw_type { ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:778:3: warning: type 'struct CGEN_OPINST' violates the C++ One Definition Rule [-Wodr] } CGEN_OPINST; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:778:3: note: a different type is defined in another translation unit } CGEN_OPINST; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:754:21: note: the first difference of corresponding definitions is field 'hw_type' enum cgen_hw_type hw_type; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:754:21: note: a field of same name but different type is defined in another translation unit enum cgen_hw_type hw_type; ^ /labs/tdevries/gdb/src/gdb/../opcodes/mep-desc.h:212:14: note: type 'cgen_hw_type' itself violates the C++ One Definition Rule typedef enum cgen_hw_type { ^ /labs/tdevries/gdb/src/gdb/../opcodes/or1k-desc.h:433:14: note: the incompatible type is defined here typedef enum cgen_hw_type { ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:827:16: warning: type 'struct cgen_ifld' violates the C++ One Definition Rule [-Wodr] typedef struct cgen_ifld { ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:827:16: note: a type with different size is defined in another translation unit typedef struct cgen_ifld { ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:885:3: warning: type 'struct CGEN_IFMT_IFLD' violates the C++ One Definition Rule [-Wodr] } CGEN_IFMT_IFLD; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:885:3: note: a different type is defined in another translation unit } CGEN_IFMT_IFLD; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:883:20: note: the first difference of corresponding definitions is field 'ifld' const CGEN_IFLD *ifld; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:883:20: note: a field of same name but different type is defined in another translation unit const CGEN_IFLD *ifld; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:859:3: note: type 'const struct CGEN_IFLD' should match type 'const struct CGEN_IFLD' } CGEN_IFLD; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:978:48: warning: type 'struct CGEN_INSN_ATTR_TYPE' violates the C++ One Definition Rule [-Wodr] typedef CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) CGEN_INSN_ATTR_TYPE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:978:48: note: a different type is defined in another translation unit typedef CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) CGEN_INSN_ATTR_TYPE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:978:9: note: the first difference of corresponding definitions is field 'nonbool' typedef CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) CGEN_INSN_ATTR_TYPE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:978:9: note: a field of same name but different type is defined in another translation unit typedef CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) CGEN_INSN_ATTR_TYPE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:978:48: note: array types have different bounds typedef CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) CGEN_INSN_ATTR_TYPE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1041:3: warning: type 'struct CGEN_IBASE' violates the C++ One Definition Rule [-Wodr] } CGEN_IBASE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1041:3: note: a different type is defined in another translation unit } CGEN_IBASE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1034:23: note: the first difference of corresponding definitions is field 'attrs' CGEN_INSN_ATTR_TYPE attrs; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1034:23: note: a field of same name but different type is defined in another translation unit CGEN_INSN_ATTR_TYPE attrs; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:978:48: note: type 'struct CGEN_INSN_ATTR_TYPE' itself violates the C++ One Definition Rule typedef CGEN_ATTR_TYPE (CGEN_INSN_NBOOL_ATTRS) CGEN_INSN_ATTR_TYPE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1050:8: warning: type 'struct cgen_insn' violates the C++ One Definition Rule [-Wodr] struct cgen_insn ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1050:8: note: a different type is defined in another translation unit struct cgen_insn ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1056:21: note: the first difference of corresponding definitions is field 'base' const CGEN_IBASE *base; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1056:21: note: a field of same name but different type is defined in another translation unit const CGEN_IBASE *base; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1041:3: note: type 'const struct CGEN_IBASE' should match type 'const struct CGEN_IBASE' } CGEN_IBASE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1069:16: warning: type 'struct cgen_insn_list' violates the C++ One Definition Rule [-Wodr] typedef struct cgen_insn_list ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1069:16: note: a different type is defined in another translation unit typedef struct cgen_insn_list ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1072:20: note: the first difference of corresponding definitions is field 'insn' const CGEN_INSN *insn; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1072:20: note: a field of same name but different type is defined in another translation unit const CGEN_INSN *insn; ^ /labs/tdevries/gdb/src/gdb/../opcodes/mep-opc.h:347:8: warning: type 'struct cgen_fields' violates the C++ One Definition Rule [-Wodr] struct cgen_fields ^ /labs/tdevries/gdb/src/gdb/../opcodes/or1k-opc.h:93:8: note: a different type is defined in another translation unit struct cgen_fields ^ /labs/tdevries/gdb/src/gdb/../opcodes/mep-opc.h:352:8: note: the first difference of corresponding definitions is field 'f_major' long f_major; ^ /labs/tdevries/gdb/src/gdb/../opcodes/or1k-opc.h:98:8: note: a field with different name is defined in another translation unit long f_opcode; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1083:3: warning: type 'struct CGEN_INSN_TABLE' violates the C++ One Definition Rule [-Wodr] } CGEN_INSN_TABLE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1083:3: note: a different type is defined in another translation unit } CGEN_INSN_TABLE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1079:20: note: the first difference of corresponding definitions is field 'init_entries' const CGEN_INSN *init_entries; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1079:20: note: a field of same name but different type is defined in another translation unit const CGEN_INSN *init_entries; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:702:3: warning: type 'struct CGEN_OPERAND' violates the C++ One Definition Rule [-Wodr] } CGEN_OPERAND; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:702:3: note: a different type is defined in another translation unit } CGEN_OPERAND; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:659:26: note: the first difference of corresponding definitions is field 'type' enum cgen_operand_type type; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:659:26: note: a field of same name but different type is defined in another translation unit enum cgen_operand_type type; ^ /labs/tdevries/gdb/src/gdb/../opcodes/mep-desc.h:250:14: note: type 'cgen_operand_type' itself violates the C++ One Definition Rule typedef enum cgen_operand_type { ^ /labs/tdevries/gdb/src/gdb/../opcodes/or1k-desc.h:624:14: note: the incompatible type is defined here typedef enum cgen_operand_type { ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:725:3: warning: type 'struct CGEN_OPERAND_TABLE' violates the C++ One Definition Rule [-Wodr] } CGEN_OPERAND_TABLE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:725:3: note: a different type is defined in another translation unit } CGEN_OPERAND_TABLE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:715:23: note: the first difference of corresponding definitions is field 'init_entries' const CGEN_OPERAND *init_entries; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:715:23: note: a field of same name but different type is defined in another translation unit const CGEN_OPERAND *init_entries; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:702:3: note: type 'const struct CGEN_OPERAND' should match type 'const struct CGEN_OPERAND' } CGEN_OPERAND; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:451:3: warning: type 'struct CGEN_HW_ENTRY' violates the C++ One Definition Rule [-Wodr] } CGEN_HW_ENTRY; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:451:3: note: a different type is defined in another translation unit } CGEN_HW_ENTRY; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:441:21: note: the first difference of corresponding definitions is field 'type' enum cgen_hw_type type; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:441:21: note: a field of same name but different type is defined in another translation unit enum cgen_hw_type type; ^ /labs/tdevries/gdb/src/gdb/../opcodes/mep-desc.h:212:14: note: type 'cgen_hw_type' itself violates the C++ One Definition Rule typedef enum cgen_hw_type { ^ /labs/tdevries/gdb/src/gdb/../opcodes/or1k-desc.h:433:14: note: the incompatible type is defined here typedef enum cgen_hw_type { ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:473:3: warning: type 'struct CGEN_HW_TABLE' violates the C++ One Definition Rule [-Wodr] } CGEN_HW_TABLE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:473:3: note: a different type is defined in another translation unit } CGEN_HW_TABLE; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:463:24: note: the first difference of corresponding definitions is field 'init_entries' const CGEN_HW_ENTRY *init_entries; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:463:24: note: a field of same name but different type is defined in another translation unit const CGEN_HW_ENTRY *init_entries; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:451:3: note: type 'const struct CGEN_HW_ENTRY' should match type 'const struct CGEN_HW_ENTRY' } CGEN_HW_ENTRY; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1199:16: warning: type 'struct cgen_cpu_desc' violates the C++ One Definition Rule [-Wodr] typedef struct cgen_cpu_desc ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1199:16: note: a different type is defined in another translation unit typedef struct cgen_cpu_desc ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1252:17: note: the first difference of corresponding definitions is field 'hw_table' CGEN_HW_TABLE hw_table; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:1252:17: note: a field of same name but different type is defined in another translation unit CGEN_HW_TABLE hw_table; ^ /labs/tdevries/gdb/src/gdb/../include/opcode/cgen.h:473:3: note: type 'struct CGEN_HW_TABLE' itself violates the C++ One Definition Rule } CGEN_HW_TABLE; ^ ...
According to opcodes/MAINTAINTERS, the dir is maintained by the binutils maintainers, so I tried building with lto some non-gdb components that use the opcodes dir to reproduce this problem, such that I could file a corresponding binutils PR, but sofar that didn't trigger the same warnings.
Filed binutils counterpart PR30758.
https://sourceware.org/pipermail/gdb-patches/2023-August/201703.html
The master branch has been updated by Tom de Vries <vries@sourceware.org>: https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=883d90a0ff6b1dbacf654f5a8db2350030b4df00 commit 883d90a0ff6b1dbacf654f5a8db2350030b4df00 Author: Tom de Vries <tdevries@suse.de> Date: Tue Aug 22 19:35:52 2023 +0200 [gdb/build] Work around cgen odr violations When building gdb with -flto -O2, I run into: ... opcodes/mep-desc.h:250:14: warning: type 'cgen_operand_type' violates the \ C++ One Definition Rule [-Wodr] typedef enum cgen_operand_type { ^ opcodes/or1k-desc.h:624:14: note: an enum with different value name is \ defined in another translation unit typedef enum cgen_operand_type { ^ opcodes/mep-desc.h:212:14: warning: type 'cgen_hw_type' violates the C++ One \ Definition Rule [-Wodr] typedef enum cgen_hw_type { ^ opcodes/or1k-desc.h:433:14: note: an enum with different value name is \ defined in another translation unit typedef enum cgen_hw_type { ^ ... Fix this by making the conflicting type names unique, adding a target-specific prefix using a define before the include: ... #define cgen_operand_type <target-name>_cgen_operand_type #define cgen_hw_type <target-name>_cgen_hw_type #include "opcodes/<target-name>-desc.h" ... and move those defines into a new file cgen-remap.h, similar to how that's done for yacc in yy-remap.h. Likewise for targets frv and lm32, the two other targets that include opcodes/<target-name>-desc.h. Likewise for more cgen symbols that I got the same warning for when using -flto-partition=one. A PR has been filed to take care of this in the opcodes dir instead (PR30758). Tested on x86_64-linux. Approved-By: Tom Tromey <tom@tromey.com> PR build/30757 Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30757
Fixed.