diff options
-rw-r--r-- | gcc/common.opt | 4 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 8 | ||||
-rw-r--r-- | gcc/ipa-devirt.c | 113 | ||||
-rw-r--r-- | gcc/ipa-utils.h | 7 | ||||
-rw-r--r-- | gcc/lto/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/lto/lto-symtab.c | 160 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/lto/20120723_0.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/lto/20091028-1_1.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/lto/20091028-2_1.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/lto/pr41521_0.f90 | 9 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/lto/pr41576_0.f90 | 2 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/lto/pr41576_1.f90 | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/lto/pr60635_0.f90 | 1 | ||||
-rw-r--r-- | gcc/tree.c | 3 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
16 files changed, 269 insertions, 78 deletions
diff --git a/gcc/common.opt b/gcc/common.opt index 859488f7a1c..562d34a05ae 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -607,6 +607,10 @@ Woverflow Common Var(warn_overflow) Init(1) Warning Warn about overflow in arithmetic expressions +Wlto-type-mismatch +Common Var(warn_lto_type_mismatch) Init(1) Warning +During link time optimization warn about mismatched types of global declarations + Wpacked Common Var(warn_packed) Warning Warn when the packed attribute has no effect on struct layout diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 117b5d99dfc..1e484232b2b 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -2698,6 +2698,14 @@ In this case, @code{PRId64} is treated as a separate preprocessing token. This warning is enabled by default. +@item -Wlto-type-mismatch +@opindex Wlto-type-mismatch +@opindex Wno-lto-type-mistmach + +During the link-time optimization warn about type mismatches in between +global declarations from different compilation units. +Requires @option{-flto} to be enabled. Enabled by default. + @item -Wnarrowing @r{(C++ and Objective-C++ only)} @opindex Wnarrowing @opindex Wno-narrowing diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c index c073ac879b2..bf43859f47e 100644 --- a/gcc/ipa-devirt.c +++ b/gcc/ipa-devirt.c @@ -247,9 +247,14 @@ struct GTY(()) odr_type_d /* Return true if T is a type with linkage defined. */ -static bool +bool type_with_linkage_p (const_tree t) { + /* Builtin types do not define linkage, their TYPE_CONTEXT is NULL. */ + if (!TYPE_CONTEXT (t) + || !TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL) + return false; + return (RECORD_OR_UNION_TYPE_P (t) || TREE_CODE (t) == ENUMERAL_TYPE); } @@ -261,12 +266,21 @@ bool type_in_anonymous_namespace_p (const_tree t) { gcc_assert (type_with_linkage_p (t)); - /* TREE_PUBLIC of TYPE_STUB_DECL may not be properly set for - backend produced types (such as va_arg_type); those have CONTEXT NULL - and never are considered anonymoius. */ - if (!TYPE_CONTEXT (t)) - return false; - return (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t))); + + if (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t))) + { + tree ctx = DECL_CONTEXT (TYPE_NAME (t)); + while (ctx) + { + if (TREE_CODE (ctx) == NAMESPACE_DECL) + return !TREE_PUBLIC (ctx); + if (TREE_CODE (ctx) == BLOCK) + ctx = BLOCK_SUPERCONTEXT (ctx); + else + ctx = get_containing_scope (ctx); + } + } + return false; } /* Return true of T is type with One Definition Rule info attached. @@ -589,6 +603,59 @@ types_must_be_same_for_odr (tree t1, tree t2) return TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2); } +/* If T is compound type, return type it is based on. */ + +static tree +compound_type_base (const_tree t) +{ + if (TREE_CODE (t) == ARRAY_TYPE + || POINTER_TYPE_P (t) + || TREE_CODE (t) == COMPLEX_TYPE + || VECTOR_TYPE_P (t)) + return TREE_TYPE (t); + if (TREE_CODE (t) == METHOD_TYPE) + return TYPE_METHOD_BASETYPE (t); + if (TREE_CODE (t) == OFFSET_TYPE) + return TYPE_OFFSET_BASETYPE (t); + return NULL_TREE; +} + +/* Return true if T is either ODR type or compound type based from it. + If the function return true, we know that T is a type originating from C++ + source even at link-time. */ + +bool +odr_or_derived_type_p (const_tree t) +{ + do + { + if (odr_type_p (t)) + return true; + /* Function type is a tricky one. Basically we can consider it + ODR derived if return type or any of the parameters is. + We need to check all parameters because LTO streaming merges + common types (such as void) and they are not considered ODR then. */ + if (TREE_CODE (t) == FUNCTION_TYPE) + { + if (TYPE_METHOD_BASETYPE (t)) + t = TYPE_METHOD_BASETYPE (t); + else + { + if (TREE_TYPE (t) && odr_or_derived_type_p (TREE_TYPE (t))) + return true; + for (t = TYPE_ARG_TYPES (t); t; t = TREE_CHAIN (t)) + if (odr_or_derived_type_p (TREE_VALUE (t))) + return true; + return false; + } + } + else + t = compound_type_base (t); + } + while (t); + return t; +} + /* Compare types T1 and T2 and return true if they are equivalent. */ @@ -1223,6 +1290,16 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, return false; } + if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1)) + || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2))) + { + /* We can not trip this when comparing ODR types, only when trying to + match different ODR derivations from different declarations. + So WARN should be always false. */ + gcc_assert (!warn); + return false; + } + if (comp_type_attributes (t1, t2) != 1) { warn_odr (t1, t2, NULL, NULL, warn, warned, @@ -1625,6 +1702,20 @@ odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, return true; } +/* Return true if TYPE1 and TYPE2 are equivalent for One Definition Rule. */ + +bool +odr_types_equivalent_p (tree type1, tree type2) +{ + hash_set<type_pair,pair_traits> visited; + +#ifdef ENABLE_CHECKING + gcc_assert (odr_or_derived_type_p (type1) && odr_or_derived_type_p (type2)); +#endif + return odr_types_equivalent_p (type1, type2, false, NULL, + &visited); +} + /* TYPE is equivalent to VAL by ODR, but its tree representation differs from VAL->type. This may happen in LTO where tree merging did not merge all variants of the same type or due to ODR violation. @@ -1749,12 +1840,8 @@ add_type_duplicate (odr_type val, tree type) base_mismatch = true; } else - { - hash_set<type_pair,pair_traits> visited; - if (!odr_types_equivalent_p (type1, type2, false, NULL, - &visited)) - base_mismatch = true; - } + if (!odr_types_equivalent_p (type1, type2)) + base_mismatch = true; if (base_mismatch) { if (!warned && !val->odr_violated) diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h index 13c59a830ba..3378f6946f9 100644 --- a/gcc/ipa-utils.h +++ b/gcc/ipa-utils.h @@ -63,7 +63,9 @@ possible_polymorphic_call_targets (tree, HOST_WIDE_INT, void **cache_token = NULL, bool speuclative = false); odr_type get_odr_type (tree, bool insert = false); -bool odr_type_p (const_tree t); +bool type_in_anonymous_namespace_p (const_tree); +bool type_with_linkage_p (const_tree); +bool odr_type_p (const_tree); bool possible_polymorphic_call_target_p (tree ref, gimple stmt, struct cgraph_node *n); void dump_possible_polymorphic_call_targets (FILE *, tree, HOST_WIDE_INT, const ipa_polymorphic_call_context &); @@ -85,6 +87,9 @@ bool types_must_be_same_for_odr (tree, tree); bool types_odr_comparable (tree, tree, bool strict = false); cgraph_node *try_speculative_devirtualization (tree, HOST_WIDE_INT, ipa_polymorphic_call_context); +void warn_types_mismatch (tree t1, tree t2); +bool odr_or_derived_type_p (const_tree t); +bool odr_types_equivalent_p (tree type1, tree type2); /* Return vector containing possible targets of polymorphic call E. If COMPLETEP is non-NULL, store true if the list is complete. diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog index ff8a213ab62..3725d1a25eb 100644 --- a/gcc/lto/ChangeLog +++ b/gcc/lto/ChangeLog @@ -1,3 +1,10 @@ +2015-05-17 Jan Hubicka <hubicka@ucw.cz> + + * lto-symtab.c (warn_type_compatibility_p): Break out from ...; + compare ODR types (if available) and function types. + (lto_symtab_merge): ... here; output ODR violation warnings + and call warn_types_mismatch. + 2015-04-29 Jan Hubicka <hubicka@ucw.cz> * lto.c (lto_fixup_state): Call verify_type. diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c index 396d3e27f23..995c7c98c75 100644 --- a/gcc/lto/lto-symtab.c +++ b/gcc/lto/lto-symtab.c @@ -56,6 +56,7 @@ along with GCC; see the file COPYING3. If not see #include "ipa-prop.h" #include "ipa-inline.h" #include "builtins.h" +#include "print-tree.h" /* Replace the cgraph node NODE with PREVAILING_NODE in the cgraph, merging all edges and removing the old node. */ @@ -203,45 +204,49 @@ lto_varpool_replace_node (varpool_node *vnode, vnode->remove (); } -/* Merge two variable or function symbol table entries PREVAILING and ENTRY. - Return false if the symbols are not fully compatible and a diagnostic - should be emitted. */ +/* Return non-zero if we want to output waring about T1 and T2. + Return value is a bitmask of reasons of violation: + Bit 0 indicates that types are not compatible of memory layout. + Bot 1 indicates that types are not compatible because of C++ ODR rule. */ -static bool -lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) +static int +warn_type_compatibility_p (tree prevailing_type, tree type) { - tree prevailing_decl = prevailing->decl; - tree decl = entry->decl; - tree prevailing_type, type; - - if (prevailing_decl == decl) - return true; - - /* Merge decl state in both directions, we may still end up using - the new decl. */ - TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl); - TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl); - - /* The linker may ask us to combine two incompatible symbols. - Detect this case and notify the caller of required diagnostics. */ - - if (TREE_CODE (decl) == FUNCTION_DECL) + int lev = 0; + /* C++ provide a robust way to check for type compatibility via the ODR + rule. */ + if (odr_or_derived_type_p (prevailing_type) && odr_type_p (type) + && !odr_types_equivalent_p (prevailing_type, type)) + lev = 2; + + /* Function types needs special care, because types_compatible_p never + thinks prototype is compatible to non-prototype. */ + if ((TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE) + && TREE_CODE (type) == TREE_CODE (prevailing_type)) { - if (!types_compatible_p (TREE_TYPE (prevailing_decl), - TREE_TYPE (decl))) - /* If we don't have a merged type yet...sigh. The linker - wouldn't complain if the types were mismatched, so we - probably shouldn't either. Just use the type from - whichever decl appears to be associated with the - definition. If for some odd reason neither decl is, the - older one wins. */ - (void) 0; - - return true; + lev |= warn_type_compatibility_p (TREE_TYPE (prevailing_type), + TREE_TYPE (type)); + if (TREE_CODE (type) == METHOD_TYPE) + lev |= warn_type_compatibility_p (TYPE_METHOD_BASETYPE (prevailing_type), + TYPE_METHOD_BASETYPE (type)); + if (prototype_p (prevailing_type) && prototype_p (type) + && TYPE_ARG_TYPES (prevailing_type) != TYPE_ARG_TYPES (type)) + { + tree parm1, parm2; + for (parm1 = TYPE_ARG_TYPES (prevailing_type), + parm2 = TYPE_ARG_TYPES (type); + parm1 && parm2; + parm1 = TREE_CHAIN (prevailing_type), + parm2 = TREE_CHAIN (type)) + lev |= warn_type_compatibility_p (TREE_VALUE (parm1), + TREE_VALUE (parm2)); + if (parm1 || parm2) + lev = 3; + } + if (comp_type_attributes (prevailing_type, type) == 0) + lev = 3; + return lev; } - - /* Now we exclusively deal with VAR_DECLs. */ - /* Sharing a global symbol is a strong hint that two types are compatible. We could use this information to complete incomplete pointed-to types more aggressively here, ignoring @@ -254,19 +259,22 @@ lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) ??? In principle we might want to only warn for structurally incompatible types here, but unless we have protective measures for TBAA in place that would hide useful information. */ - prevailing_type = TYPE_MAIN_VARIANT (TREE_TYPE (prevailing_decl)); - type = TYPE_MAIN_VARIANT (TREE_TYPE (decl)); + prevailing_type = TYPE_MAIN_VARIANT (prevailing_type); + type = TYPE_MAIN_VARIANT (type); if (!types_compatible_p (prevailing_type, type)) { - if (COMPLETE_TYPE_P (type)) - return false; + if (TREE_CODE (prevailing_type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE) + return 1 | lev; + if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (prevailing_type)) + return 1 | lev; /* If type is incomplete then avoid warnings in the cases that TBAA handles just fine. */ if (TREE_CODE (prevailing_type) != TREE_CODE (type)) - return false; + return 1 | lev; if (TREE_CODE (prevailing_type) == ARRAY_TYPE) { @@ -280,10 +288,10 @@ lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) } if (TREE_CODE (tem1) != TREE_CODE (tem2)) - return false; + return 1 | lev; if (!types_compatible_p (tem1, tem2)) - return false; + return 1 | lev; } /* Fallthru. Compatible enough. */ @@ -292,6 +300,43 @@ lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) /* ??? We might want to emit a warning here if type qualification differences were spotted. Do not do this unconditionally though. */ + return lev; +} + +/* Merge two variable or function symbol table entries PREVAILING and ENTRY. + Return false if the symbols are not fully compatible and a diagnostic + should be emitted. */ + +static bool +lto_symtab_merge (symtab_node *prevailing, symtab_node *entry) +{ + tree prevailing_decl = prevailing->decl; + tree decl = entry->decl; + + if (prevailing_decl == decl) + return true; + + /* Merge decl state in both directions, we may still end up using + the new decl. */ + TREE_ADDRESSABLE (prevailing_decl) |= TREE_ADDRESSABLE (decl); + TREE_ADDRESSABLE (decl) |= TREE_ADDRESSABLE (prevailing_decl); + + /* The linker may ask us to combine two incompatible symbols. + Detect this case and notify the caller of required diagnostics. */ + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl), + TREE_TYPE (decl))) + return false; + + return true; + } + + if (warn_type_compatibility_p (TREE_TYPE (prevailing_decl), + TREE_TYPE (decl))) + return false; + /* There is no point in comparing too many details of the decls here. The type compatibility checks or the completing of types has properly dealt with most issues. */ @@ -483,24 +528,39 @@ lto_symtab_merge_decls_2 (symtab_node *first, bool diagnosed_p) /* Diagnose all mismatched re-declarations. */ FOR_EACH_VEC_ELT (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); - + int level = warn_type_compatibility_p (TREE_TYPE (prevailing->decl), + TREE_TYPE (decl)); + if (level) + { + bool diag = false; + if (level > 1) + 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)); + 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), 0, + diagnosed_p |= warning_at (DECL_SOURCE_LOCATION (decl), + OPT_Wlto_type_mismatch, "alignment of %qD is bigger than " "original declaration", decl); } } if (diagnosed_p) inform (DECL_SOURCE_LOCATION (prevailing->decl), - "previously declared here"); + "%qD was previously declared here", prevailing->decl); mismatches.release (); } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6732ed6dc04..5133549afed 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2015-05-16 Jan Hubica <hubicka@ucw.cz> + + * gfortran.dg/lto/20091028-2_1.c: Fix return value. + * gfortran.dg/lto/pr41576_1.f90: Add interface. + * gfortran.dg/lto/pr41521_0.f90: Disable lto-type-mismatch + * gfortran.dg/lto/pr60635_0.f90: Disable lto-type-mismatch. + * gfortran.dg/lto/20091028-1_1.c: Fix return type. + * gcc.dg/lto/20120723_0.c: Disbale lto-type-mismatch. + 2015-05-16 Jerry DeLisle <jvdelisle@gcc.gnu.org> PR fortran/65903 diff --git a/gcc/testsuite/gcc.dg/lto/20120723_0.c b/gcc/testsuite/gcc.dg/lto/20120723_0.c index 78cfdf77c5b..77694d8503a 100644 --- a/gcc/testsuite/gcc.dg/lto/20120723_0.c +++ b/gcc/testsuite/gcc.dg/lto/20120723_0.c @@ -3,7 +3,7 @@ ??? This testcase is invalid C and can only pass on specific platforms. */ /* { dg-lto-do run } */ /* { dg-skip-if "" { { sparc*-*-* } && ilp32 } { "*" } { "" } } */ -/* { dg-lto-options { {-O3 -fno-early-inlining -flto}} } */ +/* { dg-lto-options { {-O3 -fno-early-inlining -flto -Wno-lto-type-mismatch}} } */ extern void abort (void); diff --git a/gcc/testsuite/gfortran.dg/lto/20091028-1_1.c b/gcc/testsuite/gfortran.dg/lto/20091028-1_1.c index b3afc23fb8e..2db8438bc49 100644 --- a/gcc/testsuite/gfortran.dg/lto/20091028-1_1.c +++ b/gcc/testsuite/gfortran.dg/lto/20091028-1_1.c @@ -1,9 +1,9 @@ extern void bcopy(const void *, void *, __SIZE_TYPE__ n); char *p; -int int_gen_ti_header_c_ (char * hdrbuf, int * hdrbufsize, - int * itypesize, int * typesize, - int * DataHandle, char * Data, - int * Count, int * code) +void int_gen_ti_header_c_ (char * hdrbuf, int * hdrbufsize, + int * itypesize, int * typesize, + int * DataHandle, char * Data, + int * Count, int * code) { bcopy (typesize, p, sizeof(int)) ; bcopy (Data, p, *Count * *typesize) ; diff --git a/gcc/testsuite/gfortran.dg/lto/20091028-2_1.c b/gcc/testsuite/gfortran.dg/lto/20091028-2_1.c index 496aaf11220..e4718c214e0 100644 --- a/gcc/testsuite/gfortran.dg/lto/20091028-2_1.c +++ b/gcc/testsuite/gfortran.dg/lto/20091028-2_1.c @@ -1,9 +1,9 @@ extern void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n); char *p; -int int_gen_ti_header_c_ (char * hdrbuf, int * hdrbufsize, - int * itypesize, int * typesize, - int * DataHandle, char * Data, - int * Count, int * code) +void int_gen_ti_header_c_ (char * hdrbuf, int * hdrbufsize, + int * itypesize, int * typesize, + int * DataHandle, char * Data, + int * Count, int * code) { memcpy (typesize, p, sizeof(int)) ; memcpy (Data, p, *Count * *typesize) ; diff --git a/gcc/testsuite/gfortran.dg/lto/pr41521_0.f90 b/gcc/testsuite/gfortran.dg/lto/pr41521_0.f90 index d882779263d..9ec8d370561 100644 --- a/gcc/testsuite/gfortran.dg/lto/pr41521_0.f90 +++ b/gcc/testsuite/gfortran.dg/lto/pr41521_0.f90 @@ -1,9 +1,16 @@ ! { dg-lto-do link } -! { dg-lto-options {{-g -flto} {-g -O -flto}} } +! { dg-lto-options {{-g -flto -Wno-lto-type-mismatch} {-g -O -flto -Wno-lto-type-mismatch}} } program species integer spk(2) real eval(2) spk = 2 call atom(1.1,spk,eval) end program +interface + subroutine atom(sol,k,eval) + real, intent(in) :: sol + integer, intent(in) :: k(2) + real, intent(out) :: eval(2) + end subroutine +end interface diff --git a/gcc/testsuite/gfortran.dg/lto/pr41576_0.f90 b/gcc/testsuite/gfortran.dg/lto/pr41576_0.f90 index feda0b174cb..609c17ed20a 100644 --- a/gcc/testsuite/gfortran.dg/lto/pr41576_0.f90 +++ b/gcc/testsuite/gfortran.dg/lto/pr41576_0.f90 @@ -1,5 +1,5 @@ ! { dg-lto-do run } -! { dg-lto-options { { -O2 -flto -Werror } } } +! { dg-lto-options { { -O2 -flto -Werror -Wno-lto-type-mismatch } } } subroutine foo common /bar/ a, b diff --git a/gcc/testsuite/gfortran.dg/lto/pr41576_1.f90 b/gcc/testsuite/gfortran.dg/lto/pr41576_1.f90 index 6aefcc875e3..877e044af1a 100644 --- a/gcc/testsuite/gfortran.dg/lto/pr41576_1.f90 +++ b/gcc/testsuite/gfortran.dg/lto/pr41576_1.f90 @@ -5,3 +5,8 @@ program test if (c/=1 .or. d/=2) call abort end program test +interface + subroutine foo() + end subroutine +end interface + diff --git a/gcc/testsuite/gfortran.dg/lto/pr60635_0.f90 b/gcc/testsuite/gfortran.dg/lto/pr60635_0.f90 index e1218798590..37d084d802a 100644 --- a/gcc/testsuite/gfortran.dg/lto/pr60635_0.f90 +++ b/gcc/testsuite/gfortran.dg/lto/pr60635_0.f90 @@ -1,4 +1,5 @@ ! { dg-lto-do link } +! { dg-lto-options {{ -Wno-lto-type-mismatch }} } program test use iso_fortran_env diff --git a/gcc/tree.c b/gcc/tree.c index ae2cfdd3eba..6297f04865c 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -5182,8 +5182,7 @@ need_assembler_name_p (tree decl) && DECL_NAME (decl) && decl == TYPE_NAME (TREE_TYPE (decl)) && !TYPE_ARTIFICIAL (TREE_TYPE (decl)) - && (((RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl)) - || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE) + && ((type_with_linkage_p (TREE_TYPE (decl)) && !type_in_anonymous_namespace_p (TREE_TYPE (decl))) || TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE) && !variably_modified_type_p (TREE_TYPE (decl), NULL_TREE)) diff --git a/gcc/tree.h b/gcc/tree.h index 6d5254dcb43..912b05405d8 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4544,7 +4544,6 @@ extern tree obj_type_ref_class (tree ref); extern bool types_same_for_odr (const_tree type1, const_tree type2, bool strict=false); extern bool contains_bitfld_component_ref_p (const_tree); -extern bool type_in_anonymous_namespace_p (const_tree); extern bool block_may_fallthru (const_tree); extern void using_eh_for_cleanups (void); extern bool using_eh_for_cleanups_p (void); |