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>
* config/kaos.h (CPP_PREDEFINES): Delete.
......
......@@ -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 ()
}
}
}
......@@ -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
......
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