diff options
author | Danny Smith <dannysmith@users.sourceforge.net> | 2005-10-12 20:54:50 +0000 |
---|---|---|
committer | Danny Smith <dannysmith@gcc.gnu.org> | 2005-10-12 20:54:50 +0000 |
commit | 43d9ad1dbd24f0dbb1ee8fbb8978acc1019a67f8 (patch) | |
tree | 18c5c3123c37f3bfc1dcf357bb32d0289c2b8bb8 /gcc/tree.c | |
parent | bce71376125366159e33e872d5d34eff3112dd4b (diff) | |
download | gcc-43d9ad1dbd24f0dbb1ee8fbb8978acc1019a67f8.zip gcc-43d9ad1dbd24f0dbb1ee8fbb8978acc1019a67f8.tar.gz gcc-43d9ad1dbd24f0dbb1ee8fbb8978acc1019a67f8.tar.bz2 |
re PR target/21275 (gcc 4.0.0 crash with mingw when using stdout in global var)
PR middle-end/21275
PR middle-end/21766
* target.h (struct gcc_target): Add valid_dllimport_attribute_p
target hook.
(struct cxx): Add adjust_class_at_definition target hook.
* target-def.h: (TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): New define,
defaulting to hook_bool_tree_true. Add to TARGET_INITIALIZER
(TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): New define, defaulting to
hook_void_tree. Add to TARGET_CXX.
* tree.h (struct decl_with_vis): Rename non_addr_const_p field to
dllimport_flag.
(DECL_NON_ADDR_CONSTANT_P): Replace with DECL_DLLIMPORT_P macro.
* tree.c (merge_dllimport_decl_attributes): Check DECL_DLLIMPORT_P
instead of attribute. Check for dllexport override. Warn if
inconsistent dll linkage. Don't lose old dllimport if decl has
had address referenced. Tweak lookup of dllimport atribute.
(handle_dll_attribute): Check targetm.valid_dllimport_attribute_p
for target specific rules. Don't add dllimport attribute if
DECL_DECLARED_INLINE_P. Set DECL_DLLIMPORT_P when adding
dllimport attribute.
(staticp): Replace DECL_NON_ADDR_CONSTANT_P with DECL_DLLIMPORT_P.
* varasm.c (initializer_constant_valid_p): Replace
DECL_NON_ADDR_CONSTANT_P with DECL_DLLIMPORT_P
PR target/21801
PR target/23589
* config.gcc (i[34567]86-*-cygwin*): Add winnt-cxx.o to
'cxx_target_objs', winnt-stubs,o to 'extra_objs'.
(i[34567]86-*-mingw32*): Likewise.
* doc/tm.texi (TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): Document.
(TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): Document.
* config/i386/winnt.c (i386_pe_dllimport_p): Factor out
C++-specific code. Change return value to bool.
(i386_pe_dllimport_p): Likewise.
(associated_type): Simplify and make language-independent
(i386_pe_encode_section_info): Replace override of ambiguous
dllimport symbol refs with a gcc_assert.
(i386_pe_valid_dllimport_attribute_p): Define.
* config/i386/winnt-cxx.c: New file. Define C++ versions of
i386_pe_type_dllimport_p, i386_pe_type_dllexport_p,
i386_pe_adjust_class_at_definition.
* config/i386/winnt-stubs.c: New file. Define stub versions of
lang-specific functions.
* config/i386/i386-protos.h: Declare winnt-[cxx|stubs].c functions
i386_pe_type_dllimport_p, i386_pe_type_dllexport_p,
i386_pe_adjust_class_at_definition.
(i386_pe_valid_dllimport_attribute_p): Declare.
* config/i386/cygming.h (TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): Define.
(TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): Define.
* config/i386/t-cygming: Add rules for winnt-cxx.o, winnt-stubs.o.
PR target/19704
* config/i386/i386.c (ix86_function_ok_for_sibcall): Replace test for
dllimport attribute with test of DECL_DLLIMPORT_P.
cp
PR target/21801
PR target/23589
* class.c (finish_struct_1): Call
targetm.cxx.adjust_class_at_definition.
testsuite
* gcc.dg/dll-2.c: Add tests for warnings.
* gcc.dg/dll-3.c: Likewise.
* gcc.dg/dll-4.c: Likewise.
* g++.dg/ext/dllimport1.C: Adjust tests for warnings.
* g++.dg/ext/dllimport2.C: Likewise.
* g++.dg/ext/dllimport3.C: Likewise.
* g++.dg/ext/dllimport7.C: Likewise.
* g++.dg/ext/dllimport8.C: Likewise.
* g++.dg/ext/dllimport9.C: Likewise.
From-SVN: r105332
Diffstat (limited to 'gcc/tree.c')
-rw-r--r-- | gcc/tree.c | 84 |
1 files changed, 65 insertions, 19 deletions
@@ -1797,7 +1797,7 @@ staticp (tree arg) case VAR_DECL: return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg)) && ! DECL_THREAD_LOCAL_P (arg) - && ! DECL_NON_ADDR_CONST_P (arg) + && ! DECL_DLLIMPORT_P (arg) ? arg : NULL); case CONST_DECL: @@ -3478,31 +3478,66 @@ tree merge_dllimport_decl_attributes (tree old, tree new) { tree a; - int delete_dllimport_p; - - old = DECL_ATTRIBUTES (old); - new = DECL_ATTRIBUTES (new); + int delete_dllimport_p = 1; /* What we need to do here is remove from `old' dllimport if it doesn't appear in `new'. dllimport behaves like extern: if a declaration is marked dllimport and a definition appears later, then the object - is not dllimport'd. */ - if (lookup_attribute ("dllimport", old) != NULL_TREE - && lookup_attribute ("dllimport", new) == NULL_TREE) - delete_dllimport_p = 1; + is not dllimport'd. We also remove a `new' dllimport if the old list + contains dllexport: dllexport always overrides dllimport, regardless + of the order of declaration. */ + if (!VAR_OR_FUNCTION_DECL_P (new)) + delete_dllimport_p = 0; + else if (DECL_DLLIMPORT_P (new) + && lookup_attribute ("dllexport", DECL_ATTRIBUTES (old))) + { + DECL_DLLIMPORT_P (new) = 0; + warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: " + "dllimport ignored", new); + } + else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new)) + { + /* Warn about overriding a symbol that has already been used. eg: + extern int __attribute__ ((dllimport)) foo; + int* bar () {return &foo;} + int foo; + */ + if (TREE_USED (old)) + { + warning (0, "%q+D redeclared without dllimport attribute " + "after being referenced with dll linkage", new); + /* If we have used a variable's address with dllimport linkage, + keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the + decl may already have had TREE_INVARIANT and TREE_CONSTANT + computed. + We still remove the attribute so that assembler code refers + to '&foo rather than '_imp__foo'. */ + if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old)) + DECL_DLLIMPORT_P (new) = 1; + } + + /* Let an inline definition silently override the external reference, + but otherwise warn about attribute inconsistency. */ + else if (TREE_CODE (new) == VAR_DECL + || !DECL_DECLARED_INLINE_P (new)) + warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: " + "previous dllimport ignored", new); + } else delete_dllimport_p = 0; - a = merge_attributes (old, new); + a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new)); - if (delete_dllimport_p) + if (delete_dllimport_p) { tree prev, t; - + const size_t attr_len = strlen ("dllimport"); + /* Scan the list for dllimport and delete it. */ for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t)) { - if (is_attribute_p ("dllimport", TREE_PURPOSE (t))) + if (is_attribute_with_length_p ("dllimport", attr_len, + TREE_PURPOSE (t))) { if (prev == NULL_TREE) a = TREE_CHAIN (a); @@ -3549,18 +3584,26 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, any damage. */ if (is_attribute_p ("dllimport", name)) { + /* Honor any target-specific overides. */ + if (!targetm.valid_dllimport_attribute_p (node)) + *no_add_attrs = true; + + else if (TREE_CODE (node) == FUNCTION_DECL + && DECL_DECLARED_INLINE_P (node)) + { + warning (OPT_Wattributes, "inline function %q+D declared as " + " dllimport: attribute ignored", node); + *no_add_attrs = true; + } /* Like MS, treat definition of dllimported variables and - non-inlined functions on declaration as syntax errors. We - allow the attribute for function definitions if declared - inline. */ - if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) - && !DECL_DECLARED_INLINE_P (node)) + non-inlined functions on declaration as syntax errors. */ + else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node)) { error ("function %q+D definition is marked dllimport", node); *no_add_attrs = true; } - else if (TREE_CODE (node) == VAR_DECL) + else if (TREE_CODE (node) == VAR_DECL) { if (DECL_INITIAL (node)) { @@ -3577,6 +3620,9 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags, if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) TREE_PUBLIC (node) = 1; } + + if (*no_add_attrs == false) + DECL_DLLIMPORT_P (node) = 1; } /* Report error if symbol is not accessible at global scope. */ |