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 | |
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
-rw-r--r-- | gcc/ChangeLog | 22 | ||||
-rw-r--r-- | gcc/config/i386/winnt.c | 195 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 72 |
3 files changed, 227 insertions, 62 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9616fcb..5457f7d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2003-07-04 Danny Smith <dannysmith@users.sourceforge.net> + + 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. + 2003-07-03 Uwe Stieber <uwe@kaos-group.de> * config/kaos.h (CPP_PREDEFINES): Delete. 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 () } } } - diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index e7e8712..dcefcdc 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -2563,6 +2563,67 @@ use the normal calling convention based on @code{jsr} and @code{rts}. This attribute can be used to cancel the effect of the @option{-mlong-calls} option. +@item dllimport +@cindex @code{__declspec(dllimport)} +On Windows targets, the @code{dllimport} attribute causes the compiler +to reference a function or variable via a global pointer to a pointer +that is set up by the Windows dll library. The pointer name is formed by +combining @code{_imp__} and the function or variable name. The attribute +implies @code{extern} storage. + +Currently, the attribute is ignored for inlined functions. If the +attribute is applied to a symbol @emph{definition}, an error is reported. +If a symbol previously declared @code{dllimport} is later defined, the +attribute is ignored in subsequent references, and a warning is emitted. +The attribute is also overriden by a subsequent declaration as +@code{dllexport}. + +When applied to C++ classes, the attribute marks non-inlined +member functions and static data members as imports. However, the +attribute is ignored for virtual methods to allow creation of vtables +using thunks. + +On cygwin, mingw and arm-pe targets, @code{__declspec(dllimport)} is +recognized as a synonym for @code{__attribute__ ((dllimport))} for +compatibility with other Windows compilers. + +The use of the @code{dllimport} attribute on functions is not necessary, +but provides a small performance benefit by eliminating a thunk in the +dll. The use of the @code{dllimport} attribute on imported variables was +required on older versions of GNU ld, but can now be avoided by passing +the @option{--enable-auto-import} switch to ld. As with functions, using +the attribute for a variable eliminates a thunk in the dll. + +One drawback to using this attribute is that a pointer to a function or +variable marked as dllimport cannot be used as a constant address. The +attribute can be disabled for functions by setting the +@option{-mnop-fun-dllimport} flag. + +@item dllexport +@cindex @code{__declspec(dllexport)} +On Windows targets the @code{dllexport} attribute causes the compiler to +provide a global pointer to a pointer in a dll, so that it can be +referenced with the @code{dllimport} attribute. The pointer name is +formed by combining @code{_imp__} and the function or variable name. + +Currently, the @code{dllexport}attribute is ignored for inlined +functions, but export can be forced by using the +@option{-fkeep-inline-functions} flag. The attribute is also ignored for +undefined symbols. + +When applied to C++ classes. the attribute marks defined non-inlined +member functions and static data members as exports. Static consts +initialized in-class are not marked unless they are also defined +out-of-class. + +On cygwin, mingw and arm-pe targets, @code{__declspec(dllexport)} is +recognized as a synonym for @code{__attribute__ ((dllexport))} for +compatibility with other Windows compilers. + +Alternative methods for including the symbol in the dll's export table +are to use a .def file with an @code{EXPORTS} section or, with GNU ld, +using the @option{--export-all} linker flag. + @end table You can specify multiple attributes in a declaration by separating them @@ -3163,7 +3224,7 @@ section, consider using the facilities of the linker instead. @item shared @cindex @code{shared} variable attribute -On Windows NT, in addition to putting variable definitions in a named +On Windows, in addition to putting variable definitions in a named section, the section can also be shared among all running copies of an executable or DLL@. For example, this small program defines shared data by putting it in a named section @code{shared} and marking the section @@ -3186,7 +3247,7 @@ You may only use the @code{shared} attribute along with @code{section} attribute with a fully initialized global definition because of the way linkers work. See @code{section} attribute for more information. -The @code{shared} attribute is only available on Windows NT@. +The @code{shared} attribute is only available on Windows@. @item tls_model ("@var{tls_model}") @cindex @code{tls_model} attribute @@ -3243,6 +3304,13 @@ the @code{int}. @item weak The @code{weak} attribute is described in @xref{Function Attributes}. + +@item dllimport +The @code{dllimport} attribute is described in @xref{Function Attributes}. + +@item dlexport +The @code{dllexport} attribute is described in @xref{Function Attributes}. + @end table @subsection M32R/D Variable Attributes |