re PR target/41512 (dllexport broken on cygwin)
PR target/41512 * config/i386/winnt.c (i386_pe_determine_dllexport_p): Don't propagate dllexport to class members here. (i386_pe_determine_dllimport_p): Only check static class data for definition. (i386_pe_encode_section_info): Don't recheck DECL_DLLIMPORT_P. * config/i386/winnt-cxx.c (i386_pe_type_dllimport_p): Only check functions for vague linkage. (i386_pe_type_dllexport_p): Fix formatting. (maybe_add_dllexport) New function. (i386_pe_adjust_class_at_definition): Use it to propagate dllexport to class members. From-SVN: r152511
This commit is contained in:
parent
e4f512b710
commit
09a6b8a46a
|
@ -1,4 +1,20 @@
|
||||||
2009-10-07 Ben Elliston <bje@au.ibm.com>
|
|
||||||
|
2009-10-07 Danny Smith <dannysmith@users.sourceforge.net>
|
||||||
|
|
||||||
|
PR target/41512
|
||||||
|
* config/i386/winnt.c (i386_pe_determine_dllexport_p): Don't propagate
|
||||||
|
dllexport to class members here.
|
||||||
|
(i386_pe_determine_dllimport_p): Only check static class data for
|
||||||
|
definition.
|
||||||
|
(i386_pe_encode_section_info): Don't recheck DECL_DLLIMPORT_P.
|
||||||
|
* config/i386/winnt-cxx.c (i386_pe_type_dllimport_p): Only check
|
||||||
|
functions for vague linkage.
|
||||||
|
(i386_pe_type_dllexport_p): Fix formatting.
|
||||||
|
(maybe_add_dllexport) New function.
|
||||||
|
(i386_pe_adjust_class_at_definition): Use it to propagate dllexport
|
||||||
|
to class members.
|
||||||
|
|
||||||
|
2009-10-07 Ben Elliston <bje@au.ibm.com>
|
||||||
|
|
||||||
* config/rs6000/a2.md: Remove duplicated lines.
|
* config/rs6000/a2.md: Remove duplicated lines.
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
/* Target support for C++ classes on Windows.
|
/* Target support for C++ classes on Windows.
|
||||||
Contributed by Danny Smith (dannysmith@users.sourceforge.net)
|
Contributed by Danny Smith (dannysmith@users.sourceforge.net)
|
||||||
Copyright (C) 2005, 2007
|
Copyright (C) 2005, 2007, 2009 Free Software Foundation, Inc.
|
||||||
Free Software Foundation, Inc.
|
|
||||||
|
|
||||||
This file is part of GCC.
|
This file is part of GCC.
|
||||||
|
|
||||||
|
@ -28,7 +27,7 @@ along with GCC; see the file COPYING3. If not see
|
||||||
#include "hard-reg-set.h"
|
#include "hard-reg-set.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
#include "tree.h"
|
#include "tree.h"
|
||||||
#include "cp/cp-tree.h" /* this is why we're a separate module */
|
#include "cp/cp-tree.h" /* This is why we're a separate module. */
|
||||||
#include "flags.h"
|
#include "flags.h"
|
||||||
#include "tm_p.h"
|
#include "tm_p.h"
|
||||||
#include "toplev.h"
|
#include "toplev.h"
|
||||||
|
@ -52,49 +51,44 @@ i386_pe_type_dllimport_p (tree decl)
|
||||||
|| DECL_TEMPLATE_INSTANTIATION (decl)
|
|| DECL_TEMPLATE_INSTANTIATION (decl)
|
||||||
|| DECL_ARTIFICIAL (decl)))
|
|| DECL_ARTIFICIAL (decl)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
/* Overrides of the class dllimport decls by out-of-class definitions are
|
||||||
/* Don't mark defined functions as dllimport. This code will only be
|
handled by tree.c:merge_dllimport_decl_attributes. */
|
||||||
reached if we see a non-inline function defined out-of-class. */
|
|
||||||
else if (TREE_CODE (decl) == FUNCTION_DECL
|
|
||||||
&& (DECL_INITIAL (decl)))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Don't allow definitions of static data members in dllimport class,
|
|
||||||
If vtable data is marked as DECL_EXTERNAL, import it; otherwise just
|
|
||||||
ignore the class attribute. */
|
|
||||||
else if (TREE_CODE (decl) == VAR_DECL
|
|
||||||
&& TREE_STATIC (decl) && TREE_PUBLIC (decl)
|
|
||||||
&& !DECL_EXTERNAL (decl))
|
|
||||||
{
|
|
||||||
if (!DECL_VIRTUAL_P (decl))
|
|
||||||
error ("definition of static data member %q+D of "
|
|
||||||
"dllimport'd class", decl);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
i386_pe_type_dllexport_p (tree decl)
|
i386_pe_type_dllexport_p (tree decl)
|
||||||
{
|
{
|
||||||
gcc_assert (TREE_CODE (decl) == VAR_DECL
|
gcc_assert (TREE_CODE (decl) == VAR_DECL
|
||||||
|| TREE_CODE (decl) == FUNCTION_DECL);
|
|| TREE_CODE (decl) == FUNCTION_DECL);
|
||||||
/* Avoid exporting compiler-generated default dtors and copy ctors.
|
|
||||||
The only artificial methods that need to be exported are virtual
|
/* Avoid exporting compiler-generated default dtors and copy ctors.
|
||||||
and non-virtual thunks. */
|
The only artificial methods that need to be exported are virtual
|
||||||
if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
|
and non-virtual thunks. */
|
||||||
&& DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl))
|
if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
|
||||||
return false;
|
&& DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl))
|
||||||
return true;
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void maybe_add_dllimport (tree decl)
|
static inline void maybe_add_dllimport (tree decl)
|
||||||
{
|
{
|
||||||
if (i386_pe_type_dllimport_p (decl))
|
if (i386_pe_type_dllimport_p (decl))
|
||||||
DECL_DLLIMPORT_P (decl) = 1;
|
DECL_DLLIMPORT_P (decl) = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void maybe_add_dllexport (tree decl)
|
||||||
|
{
|
||||||
|
if (i386_pe_type_dllexport_p (decl))
|
||||||
|
{
|
||||||
|
tree decl_attrs = DECL_ATTRIBUTES (decl);
|
||||||
|
if (lookup_attribute ("dllexport", decl_attrs) != NULL_TREE)
|
||||||
|
/* Already done. */
|
||||||
|
return;
|
||||||
|
DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("dllexport"),
|
||||||
|
NULL_TREE, decl_attrs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -103,41 +97,69 @@ i386_pe_adjust_class_at_definition (tree t)
|
||||||
tree member;
|
tree member;
|
||||||
|
|
||||||
gcc_assert (CLASS_TYPE_P (t));
|
gcc_assert (CLASS_TYPE_P (t));
|
||||||
|
|
||||||
/* We only look at dllimport. The only thing that dllexport does is
|
|
||||||
add stuff to a '.drectiv' section at end-of-file, so no need to do
|
|
||||||
anything for dllexport'd classes until we generate RTL. */
|
|
||||||
if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* We don't actually add the attribute to the decl, just set the flag
|
|
||||||
that signals that the address of this symbol is not a compile-time
|
|
||||||
constant. Any subsequent out-of-class declaration of members wil
|
|
||||||
cause the DECL_DLLIMPORT_P flag to be unset.
|
|
||||||
(See tree.c: merge_dllimport_decl_attributes).
|
|
||||||
That is just right since out-of class declarations can only be a
|
|
||||||
definition. We recheck the class members at RTL generation to
|
|
||||||
emit warnings if this has happened. Definition of static data member
|
|
||||||
of dllimport'd class always causes an error (as per MS compiler).
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Check static VAR_DECL's. */
|
|
||||||
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
|
|
||||||
if (TREE_CODE (member) == VAR_DECL)
|
|
||||||
maybe_add_dllimport (member);
|
|
||||||
|
|
||||||
/* Check FUNCTION_DECL's. */
|
|
||||||
for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member))
|
|
||||||
if (TREE_CODE (member) == FUNCTION_DECL)
|
|
||||||
maybe_add_dllimport (member);
|
|
||||||
|
|
||||||
/* Check vtables */
|
|
||||||
for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member))
|
if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (t)) != NULL_TREE)
|
||||||
if (TREE_CODE (member) == VAR_DECL)
|
{
|
||||||
maybe_add_dllimport (member);
|
/* Check static VAR_DECL's. */
|
||||||
|
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
|
||||||
|
if (TREE_CODE (member) == VAR_DECL)
|
||||||
|
maybe_add_dllexport (member);
|
||||||
|
|
||||||
|
/* Check FUNCTION_DECL's. */
|
||||||
|
for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member))
|
||||||
|
if (TREE_CODE (member) == FUNCTION_DECL)
|
||||||
|
{
|
||||||
|
tree thunk;
|
||||||
|
maybe_add_dllexport (member);
|
||||||
|
|
||||||
|
/* Also add the attribute to its thunks. */
|
||||||
|
for (thunk = DECL_THUNKS (member); thunk;
|
||||||
|
thunk = TREE_CHAIN (thunk))
|
||||||
|
maybe_add_dllexport (thunk);
|
||||||
|
}
|
||||||
|
/* Check vtables */
|
||||||
|
for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member))
|
||||||
|
if (TREE_CODE (member) == VAR_DECL)
|
||||||
|
maybe_add_dllexport (member);
|
||||||
|
}
|
||||||
|
|
||||||
/* We leave typeinfo tables alone. We can't mark TI objects as
|
else if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) != NULL_TREE)
|
||||||
dllimport, since the address of a secondary VTT may be needed
|
{
|
||||||
for static initialization of a primary VTT. VTT's of
|
/* We don't actually add the attribute to the decl, just set the flag
|
||||||
dllimport'd classes should always be link-once COMDAT. */
|
that signals that the address of this symbol is not a compile-time
|
||||||
|
constant. Any subsequent out-of-class declaration of members wil
|
||||||
|
cause the DECL_DLLIMPORT_P flag to be unset.
|
||||||
|
(See tree.c: merge_dllimport_decl_attributes).
|
||||||
|
That is just right since out-of class declarations can only be a
|
||||||
|
definition. */
|
||||||
|
|
||||||
|
/* Check static VAR_DECL's. */
|
||||||
|
for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
|
||||||
|
if (TREE_CODE (member) == VAR_DECL)
|
||||||
|
maybe_add_dllimport (member);
|
||||||
|
|
||||||
|
/* Check FUNCTION_DECL's. */
|
||||||
|
for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member))
|
||||||
|
if (TREE_CODE (member) == FUNCTION_DECL)
|
||||||
|
{
|
||||||
|
tree thunk;
|
||||||
|
maybe_add_dllimport (member);
|
||||||
|
|
||||||
|
/* Also add the attribute to its thunks. */
|
||||||
|
for (thunk = DECL_THUNKS (member); thunk;
|
||||||
|
thunk = TREE_CHAIN (thunk))
|
||||||
|
maybe_add_dllimport (thunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check vtables */
|
||||||
|
for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member))
|
||||||
|
if (TREE_CODE (member) == VAR_DECL)
|
||||||
|
maybe_add_dllimport (member);
|
||||||
|
|
||||||
|
/* We leave typeinfo tables alone. We can't mark TI objects as
|
||||||
|
dllimport, since the address of a secondary VTT may be needed
|
||||||
|
for static initialization of a primary VTT. VTT's of
|
||||||
|
dllimport'd classes should always be link-once COMDAT. */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,8 +102,6 @@ associated_type (tree decl)
|
||||||
static bool
|
static bool
|
||||||
i386_pe_determine_dllexport_p (tree decl)
|
i386_pe_determine_dllexport_p (tree decl)
|
||||||
{
|
{
|
||||||
tree assoc;
|
|
||||||
|
|
||||||
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -114,11 +112,6 @@ i386_pe_determine_dllexport_p (tree decl)
|
||||||
if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
|
if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* Also mark class members of exported classes with dllexport. */
|
|
||||||
assoc = associated_type (decl);
|
|
||||||
if (assoc && lookup_attribute ("dllexport", TYPE_ATTRIBUTES (assoc)))
|
|
||||||
return i386_pe_type_dllexport_p (decl);
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,18 +125,23 @@ i386_pe_determine_dllimport_p (tree decl)
|
||||||
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|
if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag.
|
|
||||||
We may need to override an earlier decision. */
|
|
||||||
if (DECL_DLLIMPORT_P (decl))
|
if (DECL_DLLIMPORT_P (decl))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
/* The DECL_DLLIMPORT_P flag was set for decls in the class definition
|
/* The DECL_DLLIMPORT_P flag was set for decls in the class definition
|
||||||
by targetm.cxx.adjust_class_at_definition. Check again to emit
|
by targetm.cxx.adjust_class_at_definition. Check again to emit
|
||||||
warnings if the class attribute has been overridden by an
|
error message if the class attribute has been overridden by an
|
||||||
out-of-class definition. */
|
out-of-class definition of static data. */
|
||||||
assoc = associated_type (decl);
|
assoc = associated_type (decl);
|
||||||
if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc)))
|
if (assoc && lookup_attribute ("dllimport", TYPE_ATTRIBUTES (assoc))
|
||||||
return i386_pe_type_dllimport_p (decl);
|
&& TREE_CODE (decl) == VAR_DECL
|
||||||
|
&& TREE_STATIC (decl) && TREE_PUBLIC (decl)
|
||||||
|
&& !DECL_EXTERNAL (decl)
|
||||||
|
/* vtable's are linkonce constants, so defining a vtable is not
|
||||||
|
an error as long as we don't try to import it too. */
|
||||||
|
&& !DECL_VIRTUAL_P (decl))
|
||||||
|
error ("definition of static data member %q+D of "
|
||||||
|
"dllimport'd class", decl);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -308,17 +306,8 @@ i386_pe_encode_section_info (tree decl, rtx rtl, int first)
|
||||||
if (i386_pe_determine_dllexport_p (decl))
|
if (i386_pe_determine_dllexport_p (decl))
|
||||||
flags |= SYMBOL_FLAG_DLLEXPORT;
|
flags |= SYMBOL_FLAG_DLLEXPORT;
|
||||||
else if (i386_pe_determine_dllimport_p (decl))
|
else if (i386_pe_determine_dllimport_p (decl))
|
||||||
{
|
flags |= SYMBOL_FLAG_DLLIMPORT;
|
||||||
flags |= SYMBOL_FLAG_DLLIMPORT;
|
|
||||||
/* If we went through the associated_type path, this won't already
|
|
||||||
be set. Though, frankly, this seems wrong, and should be fixed
|
|
||||||
elsewhere. */
|
|
||||||
if (!DECL_DLLIMPORT_P (decl))
|
|
||||||
{
|
|
||||||
DECL_DLLIMPORT_P (decl) = 1;
|
|
||||||
flags &= ~SYMBOL_FLAG_LOCAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SYMBOL_REF_FLAGS (symbol) = flags;
|
SYMBOL_REF_FLAGS (symbol) = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue