summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/doc/invoke.texi8
-rw-r--r--gcc/ipa-devirt.c113
-rw-r--r--gcc/ipa-utils.h7
-rw-r--r--gcc/lto/ChangeLog7
-rw-r--r--gcc/lto/lto-symtab.c160
-rw-r--r--gcc/testsuite/ChangeLog9
-rw-r--r--gcc/testsuite/gcc.dg/lto/20120723_0.c2
-rw-r--r--gcc/testsuite/gfortran.dg/lto/20091028-1_1.c8
-rw-r--r--gcc/testsuite/gfortran.dg/lto/20091028-2_1.c8
-rw-r--r--gcc/testsuite/gfortran.dg/lto/pr41521_0.f909
-rw-r--r--gcc/testsuite/gfortran.dg/lto/pr41576_0.f902
-rw-r--r--gcc/testsuite/gfortran.dg/lto/pr41576_1.f905
-rw-r--r--gcc/testsuite/gfortran.dg/lto/pr60635_0.f901
-rw-r--r--gcc/tree.c3
-rw-r--r--gcc/tree.h1
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);