Commit 6b6cb52e by Danny Smith Committed by Danny Smith

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
parent 369b78b0
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> 2003-07-03 Uwe Stieber <uwe@kaos-group.de>
* config/kaos.h (CPP_PREDEFINES): Delete. * config/kaos.h (CPP_PREDEFINES): Delete.
......
...@@ -3,19 +3,20 @@ ...@@ -3,19 +3,20 @@
Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc. 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 GCC is free software; you can redistribute it and/or modify it under
it under the terms of the GNU General Public License as published by the terms of the GNU General Public License as published by the Free
the Free Software Foundation; either version 2, or (at your option) Software Foundation; either version 2, or (at your option) any later
any later version. version.
GNU CC is distributed in the hope that it will be useful, GCC is distributed in the hope that it will be useful, but WITHOUT ANY
but WITHOUT ANY WARRANTY; without even the implied warranty of WARRANTY; without even the implied warranty of MERCHANTABILITY or
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
GNU General Public License for more details. for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with GNU CC; see the file COPYING. If not, write to along with GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330, the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */ Boston, MA 02111-1307, USA. */
...@@ -66,16 +67,18 @@ void i386_pe_mark_dllimport PARAMS ((tree)); ...@@ -66,16 +67,18 @@ void i386_pe_mark_dllimport PARAMS ((tree));
/* Handle a "dllimport" or "dllexport" attribute; /* Handle a "dllimport" or "dllexport" attribute;
arguments as in struct attribute_spec.handler. */ arguments as in struct attribute_spec.handler. */
tree tree
ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs) ix86_handle_dll_attribute (pnode, name, args, flags, no_add_attrs)
tree *node; tree * pnode;
tree name; tree name;
tree args; tree args;
int flags; int flags;
bool *no_add_attrs; bool *no_add_attrs;
{ {
tree node = *pnode;
/* These attributes may apply to structure and union types being created, /* These attributes may apply to structure and union types being created,
but otherwise should pass to the declaration involved. */ 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 if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
| (int) ATTR_FLAG_ARRAY_NEXT)) | (int) ATTR_FLAG_ARRAY_NEXT))
...@@ -83,20 +86,58 @@ ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs) ...@@ -83,20 +86,58 @@ ix86_handle_dll_attribute (node, name, args, flags, no_add_attrs)
*no_add_attrs = true; *no_add_attrs = true;
return tree_cons (name, args, NULL_TREE); 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)); warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
*no_add_attrs = true; *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. /* `extern' needn't be specified with dllimport.
Specify `extern' now and hope for the best. Sigh. */ Specify `extern' now and hope for the best. Sigh. */
else if (TREE_CODE (*node) == VAR_DECL DECL_EXTERNAL (node) = 1;
&& is_attribute_p ("dllimport", name)) /* 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;
}
}
/* 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; error ("%Hexternal linkage required for symbol '%D' because of '%s' attribute.",
TREE_PUBLIC (*node) = 1; &DECL_SOURCE_LOCATION (node), node, IDENTIFIER_POINTER (name));
*no_add_attrs = true;
} }
return NULL_TREE; return NULL_TREE;
...@@ -181,6 +222,7 @@ i386_pe_dllimport_p (decl) ...@@ -181,6 +222,7 @@ i386_pe_dllimport_p (decl)
tree decl; tree decl;
{ {
tree imp; tree imp;
int context_imp = 0;
if (TREE_CODE (decl) == FUNCTION_DECL if (TREE_CODE (decl) == FUNCTION_DECL
&& TARGET_NOP_FUN_DLLIMPORT) && TARGET_NOP_FUN_DLLIMPORT)
...@@ -189,16 +231,64 @@ i386_pe_dllimport_p (decl) ...@@ -189,16 +231,64 @@ i386_pe_dllimport_p (decl)
if (TREE_CODE (decl) != VAR_DECL if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL) && TREE_CODE (decl) != FUNCTION_DECL)
return 0; return 0;
imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)); imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
if (imp)
return 1;
/* Class members get the dllimport status of their class. */ /* Class members get the dllimport status of their class. */
if (associated_type (decl)) if (!imp && associated_type (decl))
{ {
imp = lookup_attribute ("dllimport", imp = lookup_attribute ("dllimport",
TYPE_ATTRIBUTES (associated_type (decl))); TYPE_ATTRIBUTES (associated_type (decl)));
if (imp) if (imp)
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 1;
} }
...@@ -246,8 +336,13 @@ i386_pe_mark_dllexport (decl) ...@@ -246,8 +336,13 @@ i386_pe_mark_dllexport (decl)
else else
abort (); abort ();
if (i386_pe_dllimport_name_p (oldname)) if (i386_pe_dllimport_name_p (oldname))
{
warning ("%Hinconsistent dll linkage for '%D, dllexport assumed.",
&DECL_SOURCE_LOCATION (decl), decl);
/* Remove DLL_IMPORT_PREFIX. */ /* Remove DLL_IMPORT_PREFIX. */
oldname += strlen (DLL_IMPORT_PREFIX); oldname += strlen (DLL_IMPORT_PREFIX);
DECL_NON_ADDR_CONST_P (decl) = 0;
}
else if (i386_pe_dllexport_name_p (oldname)) else if (i386_pe_dllexport_name_p (oldname))
return; /* already done */ return; /* already done */
...@@ -291,41 +386,16 @@ i386_pe_mark_dllimport (decl) ...@@ -291,41 +386,16 @@ i386_pe_mark_dllimport (decl)
} }
else if (i386_pe_dllimport_name_p (oldname)) else if (i386_pe_dllimport_name_p (oldname))
{ {
/* Already done, but force correct linkage since the redeclaration /* Already done, but do a sanity check to prevent assembler errors. */
might have omitted explicit extern. Sigh. */ if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
if (TREE_CODE (decl) == VAR_DECL
/* ??? Is this test for vtables needed? */
&& !DECL_VIRTUAL_P (decl))
{ {
DECL_EXTERNAL (decl) = 1; error ("%Hfailure in redeclaration of '%D': dllimport'd symbol lacks external linkage.",
TREE_PUBLIC (decl) = 1; &DECL_SOURCE_LOCATION (decl), decl);
abort();
} }
return; 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); newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname); sprintf (newname, "%s%s", DLL_IMPORT_PREFIX, oldname);
...@@ -466,6 +536,12 @@ i386_pe_encode_section_info (decl, rtl, first) ...@@ -466,6 +536,12 @@ i386_pe_encode_section_info (decl, rtl, first)
tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX)); tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp)); 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; XEXP (DECL_RTL (decl), 0) = newrtl;
DECL_NON_ADDR_CONST_P (decl) = 0; DECL_NON_ADDR_CONST_P (decl) = 0;
...@@ -796,4 +872,3 @@ i386_pe_file_end () ...@@ -796,4 +872,3 @@ i386_pe_file_end ()
} }
} }
} }
...@@ -2563,6 +2563,67 @@ use the normal calling convention based on @code{jsr} and @code{rts}. ...@@ -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} This attribute can be used to cancel the effect of the @option{-mlong-calls}
option. 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 @end table
You can specify multiple attributes in a declaration by separating them You can specify multiple attributes in a declaration by separating them
...@@ -3163,7 +3224,7 @@ section, consider using the facilities of the linker instead. ...@@ -3163,7 +3224,7 @@ section, consider using the facilities of the linker instead.
@item shared @item shared
@cindex @code{shared} variable attribute @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 section, the section can also be shared among all running copies of an
executable or DLL@. For example, this small program defines shared data executable or DLL@. For example, this small program defines shared data
by putting it in a named section @code{shared} and marking the section 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} ...@@ -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 attribute with a fully initialized global definition because of the way
linkers work. See @code{section} attribute for more information. 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}") @item tls_model ("@var{tls_model}")
@cindex @code{tls_model} attribute @cindex @code{tls_model} attribute
...@@ -3243,6 +3304,13 @@ the @code{int}. ...@@ -3243,6 +3304,13 @@ the @code{int}.
@item weak @item weak
The @code{weak} attribute is described in @xref{Function Attributes}. 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 @end table
@subsection M32R/D Variable Attributes @subsection M32R/D Variable Attributes
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment