From 5fcffe51f0feba3b795e6668582c63760db8389a Mon Sep 17 00:00:00 2001 From: Markus Trippelsdorf Date: Fri, 17 Oct 2014 05:10:07 +0000 Subject: Fix pr61848, linux kernel miscompile This patch cures the linux kernel boot failure when compiled using trunk gcc. At its heart, the problem is caused by merge_decls merging from the old decl to the new decl, then copying back to the old decl and discarding the new. When Jan moved some fields to the symtab, "copying back to the old decl" was lost for those fields. Really, it would be best if merge_decls was rewritten to merge everything to the kept decl, but here I'm just doing that for fields accessed via decl_with_vis.symtab_node. 2014-10-17 Alan Modra gcc/c/ PR middle-end/61848 * c-decl.c (merge_decls): Don't merge section name or tls model to newdecl symtab node, instead merge to olddecl. Override existing olddecl section name. Set tls_model for all thread-local vars, not just OMP thread-private ones. Remove incorrect comment. gcc/cp/ PR middle-end/61848 * decl.c (merge_decls): Don't merge section name, comdat group or tls model to newdecl symtab node, instead merge to olddecl. Override existing olddecl section name. Set tls_model for all thread-local vars, not just OMP thread-private ones. Remove incorrect comment. 2014-10-17 Markus Trippelsdorf PR middle-end/61848 * g++.dg/torture/pr61848.C: New testcase. * gcc.c-torture/compile/pr61848.c: New testcase. From-SVN: r216361 --- gcc/c/c-decl.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'gcc/c') diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index fb16be6..839c67b 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -2297,22 +2297,10 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) /* Merge the threadprivate attribute. */ if (TREE_CODE (olddecl) == VAR_DECL && C_DECL_THREADPRIVATE_P (olddecl)) - { - set_decl_tls_model (newdecl, DECL_TLS_MODEL (olddecl)); - C_DECL_THREADPRIVATE_P (newdecl) = 1; - } + C_DECL_THREADPRIVATE_P (newdecl) = 1; if (CODE_CONTAINS_STRUCT (TREE_CODE (olddecl), TS_DECL_WITH_VIS)) { - /* Merge the section attribute. - We want to issue an error if the sections conflict but that - must be done later in decl_attributes since we are called - before attributes are assigned. */ - if ((DECL_EXTERNAL (olddecl) || TREE_PUBLIC (olddecl) || TREE_STATIC (olddecl)) - && DECL_SECTION_NAME (newdecl) == NULL - && DECL_SECTION_NAME (olddecl)) - set_decl_section_name (newdecl, DECL_SECTION_NAME (olddecl)); - /* Copy the assembler name. Currently, it can only be defined in the prototype. */ COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl); @@ -2522,6 +2510,20 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) (char *) newdecl + sizeof (struct tree_decl_common), tree_code_size (TREE_CODE (olddecl)) - sizeof (struct tree_decl_common)); olddecl->decl_with_vis.symtab_node = snode; + + if ((DECL_EXTERNAL (olddecl) + || TREE_PUBLIC (olddecl) + || TREE_STATIC (olddecl)) + && DECL_SECTION_NAME (newdecl) != NULL) + set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl)); + + /* This isn't quite correct for something like + int __thread x attribute ((tls_model ("local-exec"))); + extern int __thread x; + as we'll lose the "local-exec" model. */ + if (TREE_CODE (olddecl) == VAR_DECL + && DECL_THREAD_LOCAL_P (newdecl)) + set_decl_tls_model (olddecl, DECL_TLS_MODEL (newdecl)); break; } -- cgit v1.1