diff options
author | Danny Smith <dannysmith@users.sourceforge.net> | 2003-07-04 07:42:11 +0000 |
---|---|---|
committer | Danny Smith <dannysmith@gcc.gnu.org> | 2003-07-04 07:42:11 +0000 |
commit | 6b6cb52e94e6edcd7469d0f688c352676499556a (patch) | |
tree | f65870e0bd14c239781b3852c0315e7496177c07 /gcc/config | |
parent | 369b78b0e49eece1fb58e75ad5bf1c7659f78efe (diff) | |
download | gcc-6b6cb52e94e6edcd7469d0f688c352676499556a.zip gcc-6b6cb52e94e6edcd7469d0f688c352676499556a.tar.gz gcc-6b6cb52e94e6edcd7469d0f688c352676499556a.tar.bz2 |
PR c++/5287, PR c++/7910, PR c++/11021
PR c++/5287, PR c++/7910, PR c++/11021
* config/i386/winnt.c (ix86_handle_dll_attribute): Don't add
dllimport attribute if function is defined at declaration, but
report error instead. Likewise for dllimport'd variable
definitions. Set implicit TREE_PUBLIC for dllimport'd variables
declared within functions, Report error if dllimport or dllexport
symbol is not global.
(i386_pe_dllimport_p): Ignore dllimport attribute of functions
if defined after declaration or if inlined. Don't allow definition
of static data members of C++ classes. Don't dllimport virtual
methods.
(i386_pe_mark_dllexport): Warn about inconsistent dll attributes.
(i386_pe_mark_dllimport): Remove unnecessary checks.
(i386_pe_encode_section_info): Warn if the dllimport attribute
and symbol prefix have been instantiated and then overridden.
* doc/extend.texi: Document dllimport and dllexport attributes.
* config/i386/winnt.c (i386_pe_output_labelref): Fix indents.
From-SVN: r68916
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/i386/winnt.c | 195 |
1 files changed, 135 insertions, 60 deletions
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c index 97cea6c..9c5763c 100644 --- a/gcc/config/i386/winnt.c +++ b/gcc/config/i386/winnt.c @@ -3,19 +3,20 @@ Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. -GNU CC is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. You should have received a copy of the GNU General Public License + along with GNU CC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -66,16 +67,18 @@ void i386_pe_mark_dllimport PARAMS ((tree)); /* Handle a "dllimport" or "dllexport" attribute; arguments as in struct attribute_spec.handler. */ tree -ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs) - tree *node; +ix86_handle_dll_attribute (pnode, name, args, flags, no_add_attrs) + tree * pnode; tree name; tree args; int flags; bool *no_add_attrs; { + tree node = *pnode; + /* These attributes may apply to structure and union types being created, but otherwise should pass to the declaration involved. */ - if (!DECL_P (*node)) + if (!DECL_P (node)) { if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT | (int) ATTR_FLAG_ARRAY_NEXT)) @@ -83,20 +86,58 @@ ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs) *no_add_attrs = true; return tree_cons (name, args, NULL_TREE); } - if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) + if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE) { warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); *no_add_attrs = true; } + + return NULL_TREE; + } + + /* Report error on dllimport ambiguities seen now before they cause + any damage. */ + else if (is_attribute_p ("dllimport", name)) + { + /* 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, but just ignore it in i386_pe_dllimport_p. */ + if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node) + && !DECL_INLINE (node)) + { + error ("%Hfunction `%D' definition is marked dllimport.", + &DECL_SOURCE_LOCATION (node), node); + *no_add_attrs = true; + } + + else if (TREE_CODE (node) == VAR_DECL) + { + if (DECL_INITIAL (node)) + { + error ("%Hvariable `%D' definition is marked dllimport.", + &DECL_SOURCE_LOCATION (node), node); + *no_add_attrs = true; + } + + /* `extern' needn't be specified with dllimport. + Specify `extern' now and hope for the best. Sigh. */ + DECL_EXTERNAL (node) = 1; + /* Also, implicitly give dllimport'd variables declared within + a function global scope, unless declared static. */ + if (current_function_decl != NULL_TREE && !TREE_STATIC (node)) + TREE_PUBLIC (node) = 1; + } } - /* `extern' needn't be specified with dllimport. - Specify `extern' now and hope for the best. Sigh. */ - else if (TREE_CODE (*node) == VAR_DECL - && is_attribute_p ("dllimport", name)) + /* Report error if symbol is not accessible at global scope. */ + if (!TREE_PUBLIC (node) + && (TREE_CODE (node) == VAR_DECL + || TREE_CODE (node) == FUNCTION_DECL)) { - DECL_EXTERNAL (*node) = 1; - TREE_PUBLIC (*node) = 1; + error ("%Hexternal linkage required for symbol '%D' because of '%s' attribute.", + &DECL_SOURCE_LOCATION (node), node, IDENTIFIER_POINTER (name)); + *no_add_attrs = true; } return NULL_TREE; @@ -181,6 +222,7 @@ i386_pe_dllimport_p (decl) tree decl; { tree imp; + int context_imp = 0; if (TREE_CODE (decl) == FUNCTION_DECL && TARGET_NOP_FUN_DLLIMPORT) @@ -189,17 +231,65 @@ i386_pe_dllimport_p (decl) if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) return 0; + imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); - if (imp) - return 1; /* Class members get the dllimport status of their class. */ - if (associated_type (decl)) + if (!imp && associated_type (decl)) { imp = lookup_attribute ("dllimport", TYPE_ATTRIBUTES (associated_type (decl))); if (imp) - return 1; + context_imp = 1; + } + + if (imp) + { + /* Don't mark defined functions as dllimport. If the definition + itself was marked with dllimport, than ix86_handle_dll_attribute + reports an error. This handles the case when the definition + overrides an earlier declaration. */ + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl) + && !DECL_INLINE (decl)) + { + /* Don't warn about artificial methods. */ + if (!DECL_ARTIFICIAL (decl)) + warning ("%H function '%D' is defined after prior declaration as dllimport: attribute ignored", + &DECL_SOURCE_LOCATION (decl), decl); + return 0; + } + + /* We ignore the dllimport attribute for inline member functions. + This differs from MSVC behaviour which treats it like GNUC + 'extern inline' extension. */ + else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl)) + { + if (extra_warnings) + warning ("%Hinline function '%D' is declared as dllimport: attribute ignored.", + &DECL_SOURCE_LOCATION (decl), decl); + return 0; + } + + /* Don't allow definitions of static data members in dllimport class, + Just ignore attribute for vtable data. */ + else if (TREE_CODE (decl) == VAR_DECL + && TREE_STATIC (decl) && TREE_PUBLIC (decl) + && !DECL_EXTERNAL (decl) && context_imp) + { + if (!DECL_VIRTUAL_P (decl)) + error ("%Hdefinition of static data member '%D' of dllimport'd class.", + &DECL_SOURCE_LOCATION (decl), decl); + return 0; + } + + /* Since we can't treat a pointer to a dllimport'd symbol as a + constant address, we turn off the attribute on C++ virtual + methods to allow creation of vtables using thunks. */ + else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE + && (DECL_VIRTUAL_P (decl))) + return 0; + + return 1; } return 0; @@ -246,10 +336,15 @@ i386_pe_mark_dllexport (decl) else abort (); if (i386_pe_dllimport_name_p (oldname)) - /* Remove DLL_IMPORT_PREFIX. */ - oldname += strlen (DLL_IMPORT_PREFIX); + { + warning ("%Hinconsistent dll linkage for '%D, dllexport assumed.", + &DECL_SOURCE_LOCATION (decl), decl); + /* Remove DLL_IMPORT_PREFIX. */ + oldname += strlen (DLL_IMPORT_PREFIX); + DECL_NON_ADDR_CONST_P (decl) = 0; + } else if (i386_pe_dllexport_name_p (oldname)) - return; /* already done */ + return; /* already done */ newname = alloca (strlen (DLL_EXPORT_PREFIX) + strlen (oldname) + 1); sprintf (newname, "%s%s", DLL_EXPORT_PREFIX, oldname); @@ -291,41 +386,16 @@ i386_pe_mark_dllimport (decl) } else if (i386_pe_dllimport_name_p (oldname)) { - /* Already done, but force correct linkage since the redeclaration - might have omitted explicit extern. Sigh. */ - if (TREE_CODE (decl) == VAR_DECL - /* ??? Is this test for vtables needed? */ - && !DECL_VIRTUAL_P (decl)) + /* Already done, but do a sanity check to prevent assembler errors. */ + if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) { - DECL_EXTERNAL (decl) = 1; - TREE_PUBLIC (decl) = 1; + error ("%Hfailure in redeclaration of '%D': dllimport'd symbol lacks external linkage.", + &DECL_SOURCE_LOCATION (decl), decl); + abort(); } return; } - /* ??? One can well ask why we're making these checks here, - and that would be a good question. */ - - /* Imported variables can't be initialized. Note that C++ classes - are marked initial, so we need to check. */ - if (TREE_CODE (decl) == VAR_DECL - && !DECL_VIRTUAL_P (decl) - && (DECL_INITIAL (decl) - && ! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))) - { - error_with_decl (decl, "initialized variable `%s' is marked dllimport"); - return; - } - /* Nor can they be static. */ - if (TREE_CODE (decl) == VAR_DECL - /* ??? Is this test for vtables needed? */ - && !DECL_VIRTUAL_P (decl) - && 0 /*???*/) - { - error_with_decl (decl, "static variable `%s' is marked dllimport"); - return; - } - newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1); sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname); @@ -443,7 +513,7 @@ i386_pe_encode_section_info (decl, rtl, first) /* Mark the decl so we can tell from the rtl whether the object is dllexport'd or dllimport'd. This also handles dllexport/dllimport - override semantics. */ + override semantics. */ if (i386_pe_dllexport_p (decl)) i386_pe_mark_dllexport (decl); @@ -466,6 +536,12 @@ i386_pe_encode_section_info (decl, rtl, first) tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX)); rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); + warning ("%H%s '%D' %s after being referenced with dllimport linkage.", + &DECL_SOURCE_LOCATION (decl), + TREE_CODE (decl) == VAR_DECL ? "variable" : "function", + decl, (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl)) + ? "defined locally" : "redeclared without dllimport attribute"); + XEXP (DECL_RTL (decl), 0) = newrtl; DECL_NON_ADDR_CONST_P (decl) = 0; @@ -519,8 +595,8 @@ void i386_pe_output_labelref (stream, name) { if (strncmp (name, DLL_IMPORT_PREFIX, strlen (DLL_IMPORT_PREFIX)) == 0) - /* A dll import */ - { + /* A dll import */ + { if (name[strlen (DLL_IMPORT_PREFIX)] == FASTCALL_PREFIX) /* A dllimport fastcall symbol. */ { @@ -796,4 +872,3 @@ i386_pe_file_end () } } } - |