static void lto_symtab_merge_decls_2 (symtab_node first, bool diagnosed_p) { symtab_node prevailing, e; vec<tree> mismatches = vNULL; unsigned i; tree decl; /* Nothing to do for a single entry. */ prevailing = first; if (!prevailing->symbol.next_sharing_asm_name) return; /* Try to merge each entry with the prevailing one. */ for (e = prevailing->symbol.next_sharing_asm_name; e; e = e->symbol.next_sharing_asm_name) if (TREE_PUBLIC (e->symbol.decl)) { if (!lto_symtab_merge (prevailing, e) && !diagnosed_p) mismatches.safe_push (e->symbol.decl); } if (mismatches.is_empty ()) return; /* Diagnose all mismatched re-declarations. */ FOR_EACH_VEC_ELT (mismatches, i, decl) { if (!types_compatible_p (TREE_TYPE (prevailing->symbol.decl), TREE_TYPE (decl))) diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0, "type of %qD does not match original " "declaration", decl); else if ((DECL_USER_ALIGN (prevailing->symbol.decl) && DECL_USER_ALIGN (decl)) && DECL_ALIGN (prevailing->symbol.decl) < DECL_ALIGN (decl)) { diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0, "alignment of %qD is bigger than " "original declaration", decl); } } if (diagnosed_p) inform (DECL_SOURCE_LOCATION (prevailing->symbol.decl), "previously declared here"); mismatches.release (); }
static void lto_symtab_merge_decls_2 (void **slot, bool diagnosed_p) { lto_symtab_entry_t prevailing, e; VEC(tree, heap) *mismatches = NULL; unsigned i; tree decl; /* Nothing to do for a single entry. */ prevailing = (lto_symtab_entry_t) *slot; if (!prevailing->next) return; /* Try to merge each entry with the prevailing one. */ for (e = prevailing->next; e; e = e->next) { if (!lto_symtab_merge (prevailing, e) && !diagnosed_p) VEC_safe_push (tree, heap, mismatches, e->decl); } if (VEC_empty (tree, mismatches)) return; /* Diagnose all mismatched re-declarations. */ FOR_EACH_VEC_ELT (tree, mismatches, i, decl) { if (!types_compatible_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl))) diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0, "type of %qD does not match original " "declaration", decl); else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl)) && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl)) { diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), 0, "alignment of %qD is bigger than " "original declaration", decl); } } if (diagnosed_p) inform (DECL_SOURCE_LOCATION (prevailing->decl), "previously declared here"); VEC_free (tree, heap, mismatches); }
static void lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p) { symtab_node *prevailing; symtab_node *e; vec<tree> mismatches = vNULL; unsigned i; tree decl; bool tbaa_p = false; /* Nothing to do for a single entry. */ prevailing = first; if (!prevailing->next_sharing_asm_name) return; /* Try to merge each entry with the prevailing one. */ symtab_node *last_prevailing = prevailing, *next; for (e = prevailing->next_sharing_asm_name; e; e = next) { next = e->next_sharing_asm_name; /* Skip non-LTO symbols and symbols whose declaration we already visited. */ if (lto_symtab_prevailing_decl (e->decl) != e->decl || !lto_symtab_symbol_p (e) || e->decl == prevailing->decl) continue; if (!lto_symtab_merge (prevailing, e) && !diagnosed_p && !DECL_ARTIFICIAL (e->decl)) mismatches.safe_push (e->decl); symtab_node *this_prevailing; for (this_prevailing = prevailing; ; this_prevailing = this_prevailing->next_sharing_asm_name) { if (this_prevailing->decl != e->decl && lto_symtab_merge_p (this_prevailing->decl, e->decl)) break; if (this_prevailing == last_prevailing) { this_prevailing = NULL; break; } } if (this_prevailing) lto_symtab_prevail_decl (this_prevailing->decl, e->decl); /* Maintain LRU list: relink the new prevaililng symbol just after previaling node in the chain and update last_prevailing. Since the number of possible declarations of a given symbol is small, this should be faster than building a hash. */ else if (e == prevailing->next_sharing_asm_name) last_prevailing = e; else { if (e->next_sharing_asm_name) e->next_sharing_asm_name->previous_sharing_asm_name = e->previous_sharing_asm_name; e->previous_sharing_asm_name->next_sharing_asm_name = e->next_sharing_asm_name; e->previous_sharing_asm_name = prevailing; e->next_sharing_asm_name = prevailing->next_sharing_asm_name; prevailing->next_sharing_asm_name->previous_sharing_asm_name = e; prevailing->next_sharing_asm_name = e; if (last_prevailing == prevailing) last_prevailing = e; } } if (mismatches.is_empty ()) return; /* Diagnose all mismatched re-declarations. */ FOR_EACH_VEC_ELT (mismatches, i, decl) { int level = warn_type_compatibility_p (TREE_TYPE (prevailing->decl), TREE_TYPE (decl), DECL_COMDAT (decl)); if (level) { bool diag = false; if (level & 2) diag = warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wodr, "%qD violates the C++ One Definition Rule ", decl); if (!diag && (level & 1)) diag = warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wlto_type_mismatch, "type of %qD does not match original " "declaration", decl); if (diag) { warn_types_mismatch (TREE_TYPE (prevailing->decl), TREE_TYPE (decl), DECL_SOURCE_LOCATION (prevailing->decl), DECL_SOURCE_LOCATION (decl)); if ((level & 4) && !TREE_READONLY (prevailing->decl)) tbaa_p = true; } diagnosed_p |= diag; } else if ((DECL_USER_ALIGN (prevailing->decl) && DECL_USER_ALIGN (decl)) && DECL_ALIGN (prevailing->decl) < DECL_ALIGN (decl)) { diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wlto_type_mismatch, "alignment of %qD is bigger than " "original declaration", decl); } else diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wlto_type_mismatch, "size of %qD differ from the size of " "original declaration", decl); }