This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/9738. c++/5287, c++/7910, c++/11021 ] [3.3 regression] [mingw]: Patch
- From: Danny Smith <danny_r_smith_2001 at yahoo dot co dot nz>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, gcc-bugzilla at gcc dot gnu dot org
- Cc: Christopher Faylor <cgf at redhat dot com>
- Date: Fri, 11 Jul 2003 11:19:21 +1000 (EST)
- Subject: [Bug c++/9738. c++/5287, c++/7910, c++/11021 ] [3.3 regression] [mingw]: Patch
Hello.
The attached backport fixes mingw/cygwin dllimport regressions
on 3.3 branch. Chris Faylor has approved changes to config/i386/winnt.c
for branch. However, for these to have any affect, backport of
patches to c-decl.c (duplicate_decls) and to cp/decl.c (dupicate_decls)
to re-invoke make_decl_rtl are also required, so I need approval for
those as well.
The patches cause no regressions on 3.3 branch with i386-pc-mingw32
but I am unable to test other targets.
(This does not include my recent dllexport vs MI-thunk patch to trunk,
which has been approved for trunk and branch by Chris, pending no
further objection).
Danny
ChangeLog
2003-07-11 Danny Smith <dannysmith@users.sourceforge.net>
Backport from trunk
2003-05-13 Richard Henderson <rth@redhat.com>
* c-decl.c (duplicate_decls): Re-invoke make_decl_rtl if
the old decl had instantiated DECL_RTL.
2003-05-21 Danny Smith <dannysmith@users.sourceforge.net>
PR c++/9738
* config/i386/winnt.c (i386_pe_encode_section_info): Enable
even if not first.
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.
cp/ChangeLog
2003-07-11 Danny Smith <dannysmith@users.sourceforge.net>
Backport from trunk
2003-05-21 Danny Smith <dannysmith@users.sourceforge.net>
PR c++/9738
* decl.c (duplicate_decls): Re-invoke make_decl_rtl
if the old decl had instantiated DECL_RTL.
(Base on Richard Henderson 2003-05-13 patch to c-decl.c).
testsuite/ChangeLog
2003-07-11 Danny Smith <dannysmith@users.sourceforge.net>
2003-05-21 Danny Smith <dannysmith@users.sourceforge.net>
PR c++/9738
* g++.dg/ext/dllimport2.C: New file.
* g++.dg/ext/dllimport3.C: New file.
2003-07-04 Danny Smith <dannysmith@users.sourceforge.net>
PR c++/5287, PR c++/7910, PR c++/11021
* testsuite/g++.dg/ext/dllimport1.C: Add mingw32 as target. Add
tests for warnings.
* testsuite/g++.dg/ext/dllimport2.C: Add tests for warnings.
* testsuite/g++.dg/ext/dllimport3.C: Likewise.
* testsuite/g++.dg/ext/dllimport4.C: New file.
* testsuite/g++.dg/ext/dllimport5.C: New file.
* testsuite/g++.dg/ext/dllimport6.C: New file.
* testsuite/g++.dg/ext/dllimport7.C: New file.
* testsuite/g++.dg/ext/dllimport8.C: New file.
* testsuite/g++.dg/ext/dllimport9.C: New file.
* testsuite/g++.dg/ext/dllimport10.C: New file.
* testsuite/g++.dg/ext/dllexport1.C: New file.
http://mobile.yahoo.com.au - Yahoo! Mobile
- Check & compose your email via SMS on your Telstra or Vodafone mobile.
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.356.2.10
diff -c -3 -p -r1.356.2.10 c-decl.c
*** c-decl.c 12 Jun 2003 14:38:09 -0000 1.356.2.10
--- c-decl.c 10 Jul 2003 23:36:25 -0000
*************** duplicate_decls (newdecl, olddecl, diffe
*** 1578,1583 ****
--- 1578,1592 ----
Update OLDDECL to be the same. */
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
+ /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
+ so that encode_section_info has a chance to look at the new decl
+ flags and attributes. */
+ if (DECL_RTL_SET_P (olddecl)
+ && (TREE_CODE (olddecl) == FUNCTION_DECL
+ || (TREE_CODE (olddecl) == VAR_DECL
+ && TREE_STATIC (olddecl))))
+ make_decl_rtl (olddecl, NULL);
+
return 1;
}
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.965.2.53
diff -c -3 -p -r1.965.2.53 decl.c
*** cp/decl.c 27 Jun 2003 21:28:13 -0000 1.965.2.53
--- cp/decl.c 10 Jul 2003 23:36:58 -0000
*************** duplicate_decls (newdecl, olddecl)
*** 4039,4044 ****
--- 4039,4053 ----
Update OLDDECL to be the same. */
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
+ /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
+ so that encode_section_info has a chance to look at the new decl
+ flags and attributes. */
+ if (DECL_RTL_SET_P (olddecl)
+ && (TREE_CODE (olddecl) == FUNCTION_DECL
+ || (TREE_CODE (olddecl) == VAR_DECL
+ && TREE_STATIC (olddecl))))
+ make_decl_rtl (olddecl, NULL);
+
return 1;
}
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.109.2.17
diff -c -3 -p -r1.109.2.17 extend.texi
*** doc/extend.texi 23 Jun 2003 16:02:42 -0000 1.109.2.17
--- doc/extend.texi 11 Jul 2003 00:40:32 -0000
*************** contents of that register. The @code{s
*** 2432,2451 ****
the offset to the function from the call site into the @samp{BL}
instruction directly.
- @item dllimport
- @cindex functions which are imported from a dll on PowerPC Windows NT
- On the PowerPC running Windows NT, the @code{dllimport} attribute causes
- the compiler to call the function via a global pointer to the function
- pointer that is set up by the Windows NT dll library. The pointer name
- is formed by combining @code{__imp_} and the function name.
-
- @item dllexport
- @cindex functions which are exported from a dll on PowerPC Windows NT
- On the PowerPC running Windows NT, the @code{dllexport} attribute causes
- the compiler to provide a global pointer to the function pointer, so
- that it can be called with the @code{dllimport} attribute. The pointer
- name is formed by combining @code{__imp_} and the function name.
-
@item exception (@var{except-func} [, @var{except-arg}])
@cindex functions which specify exception handling on PowerPC Windows NT
On the PowerPC running Windows NT, the @code{exception} attribute causes
--- 2432,2437 ----
*************** use the normal calling convention based
*** 2589,2594 ****
--- 2575,2639 ----
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 emitted.
+ If a symbol previousy 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.
+
+ 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 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
*************** addresses can be loaded with the @code{l
*** 3271,3276 ****
--- 3316,3327 ----
Medium and large model objects may live anywhere in the 32-bit address space
(the compiler will generate @code{seth/add3} instructions to load their
addresses).
+
+ @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
Index: config/i386/winnt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/winnt.c,v
retrieving revision 1.37.2.3
diff -c -3 -p -r1.37.2.3 winnt.c
*** config/i386/winnt.c 21 Apr 2003 23:25:55 -0000 1.37.2.3
--- config/i386/winnt.c 10 Jul 2003 23:36:58 -0000
***************
*** 1,24 ****
/* Subroutines for insn-output.c for Windows NT.
Contributed by Douglas Rupp (drupp@cs.washington.edu)
! Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
! This file is part of GNU CC.
! 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.
!
! 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.
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. */
#include "config.h"
#include "system.h"
--- 1,24 ----
/* Subroutines for insn-output.c for Windows NT.
Contributed by Douglas Rupp (drupp@cs.washington.edu)
! Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003
Free Software Foundation, Inc.
! This file is part of GCC.
! 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.
!
! 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 GCC; see the file COPYING. If not, write to the Free
! Software Foundation, 59 Temple Place - Suite 330, Boston, MA
! 02111-1307, USA. */
#include "config.h"
#include "system.h"
*************** void i386_pe_mark_dllimport PARAMS ((tre
*** 54,69 ****
/* 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;
tree name;
tree args;
int flags;
bool *no_add_attrs;
{
/* These attributes may apply to structure and union types being created,
but otherwise should pass to the declaration involved. */
! if (!DECL_P (*node))
{
if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
| (int) ATTR_FLAG_ARRAY_NEXT))
--- 54,71 ----
/* Handle a "dllimport" or "dllexport" attribute;
arguments as in struct attribute_spec.handler. */
tree
! 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 (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
| (int) ATTR_FLAG_ARRAY_NEXT))
*************** ix86_handle_dll_attribute (node, name, a
*** 71,90 ****
*no_add_attrs = true;
return tree_cons (name, args, NULL_TREE);
}
! if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
{
warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
}
! /* `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))
{
! DECL_EXTERNAL (*node) = 1;
! TREE_PUBLIC (*node) = 1;
}
return NULL_TREE;
--- 73,128 ----
*no_add_attrs = true;
return tree_cons (name, args, NULL_TREE);
}
! 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_with_decl (node, "function `%s' definition is marked dllimport.");
+ *no_add_attrs = true;
+ }
+
+ else if (TREE_CODE (node) == VAR_DECL)
+ {
+ if (DECL_INITIAL (node))
+ {
+ error_with_decl (node,"variable `%s' definition is marked dllimport.");
+ *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;
+ }
}
! /* Report error if symbol is not accessible at global scope. */
! if (!TREE_PUBLIC (node)
! && (TREE_CODE (node) == VAR_DECL
! || TREE_CODE (node) == FUNCTION_DECL))
{
! error_with_decl (node, "external linkage required for symbol '%s' because of '%s' attribute.",
! IDENTIFIER_POINTER (name));
! *no_add_attrs = true;
}
return NULL_TREE;
*************** i386_pe_dllimport_p (decl)
*** 169,174 ****
--- 207,213 ----
tree decl;
{
tree imp;
+ int context_imp = 0;
if (TREE_CODE (decl) == FUNCTION_DECL
&& TARGET_NOP_FUN_DLLIMPORT)
*************** i386_pe_dllimport_p (decl)
*** 177,193 ****
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))
{
imp = lookup_attribute ("dllimport",
TYPE_ATTRIBUTES (associated_type (decl)));
if (imp)
! return 1;
}
return 0;
--- 216,277 ----
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
+
imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
/* Class members get the dllimport status of their class. */
! if (!imp && associated_type (decl))
{
imp = lookup_attribute ("dllimport",
TYPE_ATTRIBUTES (associated_type (decl)));
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_with_decl (decl,"function '%s' is defined after prior declaration as dllimport: attribute ignored.");
! 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_with_decl (decl, "inline function '%s' is declared as dllimport: attribute ignored.");
! 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_with_decl (decl, "definition of static data member '%s' of dllimport'd class.");
! 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;
*************** i386_pe_mark_dllexport (decl)
*** 234,240 ****
else
abort ();
if (i386_pe_dllimport_name_p (oldname))
! oldname += 9;
else if (i386_pe_dllexport_name_p (oldname))
return; /* already done */
--- 318,329 ----
else
abort ();
if (i386_pe_dllimport_name_p (oldname))
! {
! warning_with_decl (decl,"inconsistent dll linkage for '%s': dllexport assumed.");
! /* Remove DLL_IMPORT_PREFIX. */
! oldname += 9;
! DECL_NON_ADDR_CONST_P (decl) = 0;
! }
else if (i386_pe_dllexport_name_p (oldname))
return; /* already done */
*************** i386_pe_mark_dllimport (decl)
*** 278,316 ****
}
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))
{
! DECL_EXTERNAL (decl) = 1;
! TREE_PUBLIC (decl) = 1;
}
! 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 (oldname) + 11);
--- 367,379 ----
}
else if (i386_pe_dllimport_name_p (oldname))
{
! /* Already done, but do a sanity check to prevent assembler errors. */
! if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
{
! error_with_decl (decl, "failure in redeclaration of '%s': dllimport'd symbol lacks external linkage.");
! abort();
}
! return;
}
newname = alloca (strlen (oldname) + 11);
*************** gen_stdcall_suffix (decl)
*** 372,382 ****
void
i386_pe_encode_section_info (decl, first)
tree decl;
! int first;
{
- if (!first)
- return;
-
/* This bit is copied from i386.h. */
if (optimize > 0 && TREE_CONSTANT (decl)
&& (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
--- 435,442 ----
void
i386_pe_encode_section_info (decl, first)
tree decl;
! int first ATTRIBUTE_UNUSED;
{
/* This bit is copied from i386.h. */
if (optimize > 0 && TREE_CONSTANT (decl)
&& (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
*************** i386_pe_encode_section_info (decl, first
*** 393,399 ****
gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
/* Mark the decl so we can tell from the rtl whether the object is
! dllexport'd or dllimport'd. */
if (i386_pe_dllexport_p (decl))
i386_pe_mark_dllexport (decl);
--- 453,460 ----
gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
/* 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. */
if (i386_pe_dllexport_p (decl))
i386_pe_mark_dllexport (decl);
*************** i386_pe_encode_section_info (decl, first
*** 415,420 ****
--- 476,485 ----
tree idp = get_identifier (oldname + 9);
rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
+ warning_with_decl (decl, "'%s' %s after being referenced with dllimport linkage.",
+ (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;
*************** i386_pe_asm_file_end (file)
*** 698,701 ****
}
}
}
-
--- 763,765 ----
Index: testsuite/g++.dg/ext/dllimport1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/ext/dllimport1.C,v
retrieving revision 1.1.2.1
diff -c -3 -p -r1.1.2.1 dllimport1.C
*** testsuite/g++.dg/ext/dllimport1.C 12 Apr 2003 20:03:12 -0000 1.1.2.1
--- testsuite/g++.dg/ext/dllimport1.C 10 Jul 2003 23:36:58 -0000
***************
*** 1,12 ****
! // { dg-do compile { target i?86-*-cygwin* } }
class __attribute__((dllimport)) Foo
{
public:
virtual void dummy_foo_func(void)
! {}
};
class Bar : public Foo
{
public:
--- 1,20 ----
! // PR c++/7910
! // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
! // { dg-options { -Wall -W } }
class __attribute__((dllimport)) Foo
{
public:
virtual void dummy_foo_func(void)
! {} // { dg-warning "inline function" }
! void Foo::dummy_foo_fun2();
! virtual ~Foo(); // avoid warning
};
+ void Foo::dummy_foo_fun2()
+ { // { dg-warning "defined" }
+ }
+
class Bar : public Foo
{
public:
*************** Bar::~Bar()
*** 19,21 ****
--- 27,31 ----
void Bar::dummy_bar_func()
{}
+
+ // { dg-final { scan-assembler-not "__imp___ZN3Foo14dummy_foo_fun" } }
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllexport1.C Wed Jun 4 09:36:10 2003
***************
*** 0 ****
--- 1,23 ----
+ // Test that inline functions are exported with -fkeep-inline-functions.
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+ // { dg-options -fkeep-inline-functions }
+
+ __attribute__((dllexport)) inline int foo (int a) { return a;}
+
+
+ class __attribute__((dllexport)) Bar
+ {
+ public:
+ Bar(){};
+ int inline_bar(int a) {return a;}
+ int outline_bar(int a);
+ };
+
+ int Bar::outline_bar(int a) {return foo (a);}
+
+
+ Bar abar;
+
+ // { dg-final { scan-assembler "\.section\[ \t\]*.drectve\n.*_ZN3Bar11outline_barEi" } }
+ // { dg-final { scan-assembler " -export:_ZN3Bar10inline_barEi" } }
+ // { dg-final { scan-assembler " -export:_Z3fooi" } }
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport10.C Wed Jun 11 11:45:02 2003
***************
*** 0 ****
--- 1,16 ----
+ // PR c++/5287, c++/11021
+ // Inherit a virtual method from a dllimport'd base class.
+
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+
+ struct __attribute__((dllimport)) A
+ {
+ virtual void vfunc(void);
+ };
+
+ struct B : public A
+ {
+ };
+
+
+ B aB;
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport2.C Sun Jun 15 22:05:27 2003
***************
*** 0 ****
--- 1,29 ----
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+
+ // PR c++/9738 Dllimport attribute is overriden by later definition/redeclaration
+
+ void __attribute__((dllimport)) Bar(void);
+ void __attribute__((dllimport)) Baz(void);
+ __attribute__((dllimport)) int Biz;
+ __attribute__((dllimport)) int Boz;
+
+ void Foo(void)
+ {
+ Bar();
+ Baz();
+ Biz++;
+ Boz++;
+ }
+
+ void Bar(void)
+ { // { dg-warning "defined" }
+ }
+
+ void Baz(void); // { dg-warning "redeclared" }
+ extern int Biz; // { dg-warning "redeclared" }
+ int Boz; // { dg-warning "defined" }
+
+ void foo()
+ {
+ Biz++;
+ }
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport3.C Sun Jun 15 09:54:46 2003
***************
*** 0 ****
--- 1,25 ----
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+
+ // PR 10148 Dllimport attribute of object is overriden by later
+ // redefinition without attribute.
+
+ struct Foo
+ {
+ int a;
+ };
+
+ __attribute__((dllimport)) struct Foo f;
+
+ void Bar(void)
+ {
+ void* dummy = &f;
+ }
+
+ struct Foo f; // { dg-warning "defined" }
+
+ // Dllimport sets DECL_NON_ADDR_CONST_P to 1, so following
+ // assignment would require static_initialization_and_destruction
+ // if attribute is retained.
+
+ void* dummy = &f;
+
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport4.C Sat Jun 14 12:27:05 2003
***************
*** 0 ****
--- 1,6 ----
+ // Report error if dllimport attribute in definition itself.
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+
+ __attribute__((dllimport)) void bar () { } // { dg-error "definition" }
+
+ __attribute__((dllimport)) int foo = 1; // { dg-error "definition" }
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport5.C Thu Jul 3 23:12:19 2003
***************
*** 0 ****
--- 1,28 ----
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+ // Report error if static symbol definition has dllimport attribute.
+
+ __attribute__((dllimport))
+ int impvar; // OK, implicit "extern"
+
+ static __attribute__((dllimport))
+ int static_impvar; // { dg-error "external linkage" }
+
+ static __attribute__((dllexport))
+ int static_expvar; // { dg-error "external linkage" }
+
+ static __attribute__((dllimport))
+ void static_impfun(void); // { dg-error "external linkage" }
+
+ void foo()
+ {
+ __attribute__((dllimport))
+ int foovar; // OK, implicit "extern"
+ foovar++;
+ }
+
+ void bar()
+ {
+ __attribute__((dllexport))
+ int barvar; // { dg-error "external linkage" }
+ barvar++;
+ }
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport6.C Sun Jun 15 10:39:04 2003
***************
*** 0 ****
--- 1,30 ----
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+ // Mark class static members as dllimport.
+
+ struct Baz
+ {
+ Baz(int a_ =0) : a(a_) {};
+ int a;
+ };
+
+ class __attribute__ ((dllimport)) Bar
+ {
+ public:
+ static const int two = 2;
+ static const int three;
+ static const Baz null_baz;
+ };
+
+ int foo()
+ {
+ Bar foobar;
+ const int* baz = &Bar::two;
+ int a = foobar.two;
+ int b = foobar.three;
+ int c = foobar.null_baz.a;
+ return (a + b + c + *baz);
+ }
+
+ // { dg-final { scan-assembler __imp___ZN3Bar3twoE } }
+ // { dg-final { scan-assembler __imp___ZN3Bar5threeE } }
+ // { dg-final { scan-assembler __imp___ZN3Bar8null_bazE } }
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport7.C Sun Jun 15 10:00:27 2003
***************
*** 0 ****
--- 1,33 ----
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+
+ // Report errors on definition of dllimport'd static data member .
+
+
+ struct Baz
+ {
+ Baz(int a_ =0) : a(a_) {};
+ int a;
+ };
+
+ class __declspec(dllimport) Bar
+ {
+ public:
+ enum {one = 1};
+ static const int two = 2;
+ static const int three;
+ static const Baz null_baz;
+ };
+
+ const int Bar::three = 3; // { dg-error "definition of static data" }
+ const Baz Bar::null_baz; // { dg-error "definition of static data" }
+
+
+ int foo()
+ {
+ Bar foobar;
+ const int* baz = &Bar::two;
+ int a = foobar.two;
+ int b = foobar.three;
+ int c = foobar.null_baz.a;
+ return (a + b + c + *baz);
+ }
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport8.C Wed Jun 11 12:08:08 2003
***************
*** 0 ****
--- 1,29 ----
+ // PR c++/8378
+ // Ignore dllimport of static members if marked inlined.
+ // or if definition follows declaration in dllimported class.
+
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+ // { dg-options { -Wall -W } }
+
+ struct __attribute__((dllimport)) Foo
+ {
+ static int static_int;
+ static void static_func1();
+ static void static_func2();
+ };
+
+ void Foo::static_func1()
+ { // { dg-warning "defined" }
+ }
+
+ inline void Foo::static_func2()
+ { // { dg-warning "inline function" }
+ }
+
+ void testfoo()
+ {
+ Foo::static_func1();
+ Foo::static_func2();
+ }
+
+ // { dg-final { scan-assembler-not "__imp__" } }
*** /dev/null Fri Jul 11 01:23:15 2003
--- testsuite/g++.dg/ext/dllimport9.C Sun Jun 15 11:19:22 2003
***************
*** 0 ****
--- 1,23 ----
+ // Handle dllimport attribute for functions declared inline.
+ // { dg-do compile { target i?86-*-cygwin* i?86-*-mingw*} }
+ // { dg-options { -W } }
+
+ inline __attribute__((dllimport)) void bar() { } // { dg-warning "inline" }
+
+ struct __attribute__ ((dllimport)) Blah
+ {
+ void in_blah () { } // { dg-warning "inline" }
+ void out_blah ();
+ };
+
+ inline void Blah::out_blah(){ } // { dg-warning "inline" }
+
+ void use_inlines()
+ {
+ Blah aBlah;
+ bar();
+ aBlah.in_blah ();
+ aBlah.out_blah ();
+ }
+
+ // { dg-final { scan-assembler-not "__imp__" } }