diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a976d536649..98e91f68a55 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,4 +1,20 @@ -2009-10-07 Ben Elliston + +2009-10-07 Danny Smith + + PR target/41512 + * config/i386/winnt.c (i386_pe_determine_dllexport_p): Don't propagate + dllexport to class members here. + (i386_pe_determine_dllimport_p): Only check static class data for + definition. + (i386_pe_encode_section_info): Don't recheck DECL_DLLIMPORT_P. + * config/i386/winnt-cxx.c (i386_pe_type_dllimport_p): Only check + functions for vague linkage. + (i386_pe_type_dllexport_p): Fix formatting. + (maybe_add_dllexport) New function. + (i386_pe_adjust_class_at_definition): Use it to propagate dllexport + to class members. + + 2009-10-07 Ben Elliston * config/rs6000/a2.md: Remove duplicated lines. diff --git a/gcc/config/i386/winnt-cxx.c b/gcc/config/i386/winnt-cxx.c index 9df7cf645bb..48518adc765 100644 --- a/gcc/config/i386/winnt-cxx.c +++ b/gcc/config/i386/winnt-cxx.c @@ -1,7 +1,6 @@ /* Target support for C++ classes on Windows. Contributed by Danny Smith (dannysmith@users.sourceforge.net) - Copyright (C) 2005, 2007 - Free Software Foundation, Inc. + Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc. This file is part of GCC. @@ -28,7 +27,7 @@ along with GCC; see the file COPYING3. If not see #include "hard-reg-set.h" #include "output.h" #include "tree.h" -#include "cp/cp-tree.h" /* this is why we're a separate module */ +#include "cp/cp-tree.h" /* This is why we're a separate module. */ #include "flags.h" #include "tm_p.h" #include "toplev.h" @@ -52,49 +51,44 @@ i386_pe_type_dllimport_p (tree decl) || DECL_TEMPLATE_INSTANTIATION (decl) || DECL_ARTIFICIAL (decl))) return false; - - - /* Don't mark defined functions as dllimport. This code will only be - reached if we see a non-inline function defined out-of-class. */ - else if (TREE_CODE (decl) == FUNCTION_DECL - && (DECL_INITIAL (decl))) - return false; - - /* Don't allow definitions of static data members in dllimport class, - If vtable data is marked as DECL_EXTERNAL, import it; otherwise just - ignore the class attribute. */ - else if (TREE_CODE (decl) == VAR_DECL - && TREE_STATIC (decl) && TREE_PUBLIC (decl) - && !DECL_EXTERNAL (decl)) - { - if (!DECL_VIRTUAL_P (decl)) - error ("definition of static data member %q+D of " - "dllimport'd class", decl); - return false; - } - + + /* Overrides of the class dllimport decls by out-of-class definitions are + handled by tree.c:merge_dllimport_decl_attributes. */ return true; } - bool i386_pe_type_dllexport_p (tree decl) { - gcc_assert (TREE_CODE (decl) == VAR_DECL - || TREE_CODE (decl) == FUNCTION_DECL); - /* Avoid exporting compiler-generated default dtors and copy ctors. - The only artificial methods that need to be exported are virtual - and non-virtual thunks. */ - if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE - && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl)) - return false; - return true; + gcc_assert (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL); + + /* Avoid exporting compiler-generated default dtors and copy ctors. + The only artificial methods that need to be exported are virtual + and non-virtual thunks. */ + if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE + && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl)) + return false; + return true; } static inline void maybe_add_dllimport (tree decl) { if (i386_pe_type_dllimport_p (decl)) - DECL_DLLIMPORT_P (decl) = 1; + DECL_DLLIMPORT_P (decl) = 1; +} + +static inline void maybe_add_dllexport (tree decl) +{ + if (i386_pe_type_dllexport_p (decl)) + { + tree decl_attrs = DECL_ATTRIBUTES (decl); + if (lookup_attribute ("dllexport", decl_attrs) != NULL_TREE) + /* Already done. */ + return; + DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("dllexport"), + NULL_TREE, decl_attrs); + } } void @@ -103,41 +97,69 @@ i386_pe_adjust_class_at_definition (tree t) tree member; gcc_assert (CLASS_TYPE_P (t)); - - /* We only look at dllimport. The only thing that dllexport does is - add stuff to a '.drectiv' section at end-of-file, so no need to do - anything for dllexport'd classes until we generate RTL. */ - if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE) - return; - - /* We don't actually add the attribute to the decl, just set the flag - that signals that the address of this symbol is not a compile-time - constant. Any subsequent out-of-class declaration of members wil - cause the DECL_DLLIMPORT_P flag to be unset. - (See tree.c: merge_dllimport_decl_attributes). - That is just right since out-of class declarations can only be a - definition. We recheck the class members at RTL generation to - emit warnings if this has happened. Definition of static data member - of dllimport'd class always causes an error (as per MS compiler). - */ - - /* Check static VAR_DECL's. */ - for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) - if (TREE_CODE (member) == VAR_DECL) - maybe_add_dllimport (member); - - /* Check FUNCTION_DECL's. */ - for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member)) - if (TREE_CODE (member) == FUNCTION_DECL) - maybe_add_dllimport (member); - /* Check vtables */ - for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member)) - if (TREE_CODE (member) == VAR_DECL) - maybe_add_dllimport (member); + + if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (t)) != NULL_TREE) + { + /* Check static VAR_DECL's. */ + for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) + if (TREE_CODE (member) == VAR_DECL) + maybe_add_dllexport (member); + + /* Check FUNCTION_DECL's. */ + for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member)) + if (TREE_CODE (member) == FUNCTION_DECL) + { + tree thunk; + maybe_add_dllexport (member); + + /* Also add the attribute to its thunks. */ + for (thunk = DECL_THUNKS (member); thunk; + thunk = TREE_CHAIN (thunk)) + maybe_add_dllexport (thunk); + } + /* Check vtables */ + for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member)) + if (TREE_CODE (member) == VAR_DECL) + maybe_add_dllexport (member); + } -/* We leave typeinfo tables alone. We can't mark TI objects as - dllimport, since the address of a secondary VTT may be needed - for static initialization of a primary VTT. VTT's of - dllimport'd classes should always be link-once COMDAT. */ + else if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) != NULL_TREE) + { + /* We don't actually add the attribute to the decl, just set the flag + that signals that the address of this symbol is not a compile-time + constant. Any subsequent out-of-class declaration of members wil + cause the DECL_DLLIMPORT_P flag to be unset. + (See tree.c: merge_dllimport_decl_attributes). + That is just right since out-of class declarations can only be a + definition. */ + + /* Check static VAR_DECL's. */ + for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) + if (TREE_CODE (member) == VAR_DECL) + maybe_add_dllimport (member); + + /* Check FUNCTION_DECL's. */ + for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member)) + if (TREE_CODE (member) == FUNCTION_DECL) + { + tree thunk; + maybe_add_dllimport (member); + + /* Also add the attribute to its thunks. */ + for (thunk = DECL_THUNKS (member); thunk; + thunk = TREE_CHAIN (thunk)) + maybe_add_dllimport (thunk); + } + + /* Check vtables */ + for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member)) + if (TREE_CODE (member) == VAR_DECL) + maybe_add_dllimport (member); + + /* We leave typeinfo tables alone. We can't mark TI objects as + dllimport, since the address of a secondary VTT may be needed + for static initialization of a primary VTT. VTT's of + dllimport'd classes should always be link-once COMDAT. */ + } } diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 7069c40846f..f8dcaa9673a 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -102,8 +102,6 @@ associated_type (tree decl) static bool i386_pe_determine_dllexport_p (tree decl) { - tree assoc; - if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return false; @@ -114,11 +112,6 @@ i386_pe_determine_dllexport_p (tree decl) if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) return true; - /* Also mark class members of exported classes with dllexport. */ - assoc = associated_type (decl); - if (assoc && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (assoc))) - return i386_pe_type_dllexport_p (decl); - return false; } @@ -132,18 +125,23 @@ i386_pe_determine_dllimport_p (tree decl) if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return false; - /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag. - We may need to override an earlier decision. */ if (DECL_DLLIMPORT_P (decl)) return true; /* The DECL_DLLIMPORT_P flag was set for decls in the class definition by targetm.cxx.adjust_class_at_definition. Check again to emit - warnings if the class attribute has been overridden by an - out-of-class definition. */ + error message if the class attribute has been overridden by an + out-of-class definition of static data. */ assoc = associated_type (decl); - if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc))) - return i386_pe_type_dllimport_p (decl); + if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc)) + && TREE_CODE (decl) == VAR_DECL + && TREE_STATIC (decl) && TREE_PUBLIC (decl) + && !DECL_EXTERNAL (decl) + /* vtable's are linkonce constants, so defining a vtable is not + an error as long as we don't try to import it too. */ + && !DECL_VIRTUAL_P (decl)) + error ("definition of static data member %q+D of " + "dllimport'd class", decl); return false; } @@ -308,17 +306,8 @@ i386_pe_encode_section_info (tree decl, rtx rtl, int first) if (i386_pe_determine_dllexport_p (decl)) flags |= SYMBOL_FLAG_DLLEXPORT; else if (i386_pe_determine_dllimport_p (decl)) - { - flags |= SYMBOL_FLAG_DLLIMPORT; - /* If we went through the associated_type path, this won't already - be set. Though, frankly, this seems wrong, and should be fixed - elsewhere. */ - if (!DECL_DLLIMPORT_P (decl)) - { - DECL_DLLIMPORT_P (decl) = 1; - flags &= ~SYMBOL_FLAG_LOCAL; - } - } + flags |= SYMBOL_FLAG_DLLIMPORT; + SYMBOL_REF_FLAGS (symbol) = flags; }