re PR target/21275 (gcc 4.0.0 crash with mingw when using stdout in global var)

PR middle-end/21275
	PR middle-end/21766
	* target.h (struct gcc_target): Add valid_dllimport_attribute_p
	target hook.
	(struct cxx): Add adjust_class_at_definition target hook.
	* target-def.h: (TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): New define,
	defaulting to hook_bool_tree_true. Add to TARGET_INITIALIZER
	(TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): New define, defaulting to
	hook_void_tree. Add to TARGET_CXX.
	* tree.h (struct decl_with_vis): Rename non_addr_const_p field to
	dllimport_flag.
	(DECL_NON_ADDR_CONSTANT_P): Replace with DECL_DLLIMPORT_P macro.
	* tree.c (merge_dllimport_decl_attributes): Check DECL_DLLIMPORT_P
	instead of attribute. Check for dllexport override.  Warn if
	inconsistent dll linkage. Don't lose old dllimport if decl has
	had address referenced.   Tweak lookup of dllimport atribute.
	(handle_dll_attribute): Check targetm.valid_dllimport_attribute_p
	for target specific rules.  Don't add dllimport attribute if
	DECL_DECLARED_INLINE_P.  Set DECL_DLLIMPORT_P when adding
	dllimport attribute.
	(staticp): Replace DECL_NON_ADDR_CONSTANT_P with DECL_DLLIMPORT_P.
	* varasm.c (initializer_constant_valid_p): Replace
	DECL_NON_ADDR_CONSTANT_P with DECL_DLLIMPORT_P

	PR target/21801
	PR target/23589
	* config.gcc (i[34567]86-*-cygwin*): Add winnt-cxx.o to
	'cxx_target_objs', winnt-stubs,o to 'extra_objs'.
	(i[34567]86-*-mingw32*): Likewise.

	* doc/tm.texi (TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): Document.
	(TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): Document.

	* config/i386/winnt.c (i386_pe_dllimport_p): Factor out
	C++-specific code. Change return value to bool.
	(i386_pe_dllimport_p): Likewise.
	(associated_type): Simplify and make language-independent
	(i386_pe_encode_section_info): Replace override of ambiguous
	dllimport symbol refs with a gcc_assert.
	(i386_pe_valid_dllimport_attribute_p): Define.
	* config/i386/winnt-cxx.c: New file. Define C++ versions of
	i386_pe_type_dllimport_p, i386_pe_type_dllexport_p,
	i386_pe_adjust_class_at_definition.
	* config/i386/winnt-stubs.c: New file. Define stub versions of
	lang-specific functions.
	* config/i386/i386-protos.h: Declare winnt-[cxx|stubs].c functions
	i386_pe_type_dllimport_p, i386_pe_type_dllexport_p,
	i386_pe_adjust_class_at_definition.
	(i386_pe_valid_dllimport_attribute_p): Declare.
	* config/i386/cygming.h (TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): Define.
	(TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): Define.
	* config/i386/t-cygming: Add rules for winnt-cxx.o, winnt-stubs.o.

	PR target/19704
	* config/i386/i386.c (ix86_function_ok_for_sibcall): Replace test for
	dllimport attribute with test of DECL_DLLIMPORT_P.


cp
	PR target/21801
	PR target/23589
	* class.c (finish_struct_1): Call
	targetm.cxx.adjust_class_at_definition.


testsuite
	* gcc.dg/dll-2.c: Add tests for warnings.
	* gcc.dg/dll-3.c: Likewise.
	* gcc.dg/dll-4.c: Likewise.

	* g++.dg/ext/dllimport1.C: Adjust tests for warnings.
	* g++.dg/ext/dllimport2.C: Likewise.
	* g++.dg/ext/dllimport3.C: Likewise.
	* g++.dg/ext/dllimport7.C: Likewise.
	* g++.dg/ext/dllimport8.C: Likewise.
	* g++.dg/ext/dllimport9.C: Likewise.

From-SVN: r105332
This commit is contained in:
Danny Smith 2005-10-12 20:54:50 +00:00 committed by Danny Smith
parent bce7137612
commit 43d9ad1dbd
27 changed files with 538 additions and 220 deletions

View File

@ -1,3 +1,62 @@
2005-10-12 Danny Smith <dannysmith@users.sourceforge.net>
PR middle-end/21275
PR middle-end/21766
* target.h (struct gcc_target): Add valid_dllimport_attribute_p
target hook.
(struct cxx): Add adjust_class_at_definition target hook.
* target-def.h: (TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): New define,
defaulting to hook_bool_tree_true. Add to TARGET_INITIALIZER
(TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): New define, defaulting to
hook_void_tree. Add to TARGET_CXX.
* tree.h (struct decl_with_vis): Rename non_addr_const_p field to
dllimport_flag.
(DECL_NON_ADDR_CONSTANT_P): Replace with DECL_DLLIMPORT_P macro.
* tree.c (merge_dllimport_decl_attributes): Check DECL_DLLIMPORT_P
instead of attribute. Check for dllexport override. Warn if
inconsistent dll linkage. Don't lose old dllimport if decl has
had address referenced. Tweak lookup of dllimport atribute.
(handle_dll_attribute): Check targetm.valid_dllimport_attribute_p
for target specific rules. Don't add dllimport attribute if
DECL_DECLARED_INLINE_P. Set DECL_DLLIMPORT_P when adding
dllimport attribute.
(staticp): Replace DECL_NON_ADDR_CONSTANT_P with DECL_DLLIMPORT_P.
* varasm.c (initializer_constant_valid_p): Replace
DECL_NON_ADDR_CONSTANT_P with DECL_DLLIMPORT_P
PR target/21801
PR target/23589
* config.gcc (i[34567]86-*-cygwin*): Add winnt-cxx.o to
'cxx_target_objs', winnt-stubs,o to 'extra_objs'.
(i[34567]86-*-mingw32*): Likewise.
* doc/tm.texi (TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): Document.
(TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): Document.
* config/i386/winnt.c (i386_pe_dllimport_p): Factor out
C++-specific code. Change return value to bool.
(i386_pe_dllimport_p): Likewise.
(associated_type): Simplify and make language-independent
(i386_pe_encode_section_info): Replace override of ambiguous
dllimport symbol refs with a gcc_assert.
(i386_pe_valid_dllimport_attribute_p): Define.
* config/i386/winnt-cxx.c: New file. Define C++ versions of
i386_pe_type_dllimport_p, i386_pe_type_dllexport_p,
i386_pe_adjust_class_at_definition.
* config/i386/winnt-stubs.c: New file. Define stub versions of
lang-specific functions.
* config/i386/i386-protos.h: Declare winnt-[cxx|stubs].c functions
i386_pe_type_dllimport_p, i386_pe_type_dllexport_p,
i386_pe_adjust_class_at_definition.
(i386_pe_valid_dllimport_attribute_p): Declare.
* config/i386/cygming.h (TARGET_VALID_DLLIMPORT_ATTRIBUTE_P): Define.
(TARGET_CXX_ADJUST_CLASS_AT_DEFINITION): Define.
* config/i386/t-cygming: Add rules for winnt-cxx.o, winnt-stubs.o.
PR target/19704
* config/i386/i386.c (ix86_function_ok_for_sibcall): Replace test for
dllimport attribute with test of DECL_DLLIMPORT_P.
2005-10-12 Adrian Straetling <straetling@de.ibm.com>
* combine.c (make_extraction): Correct offset computation.

View File

@ -1202,9 +1202,9 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
tmake_file="i386/t-cygwin i386/t-cygming"
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
extra_options="${extra_options} i386/cygming.opt"
extra_objs=winnt.o
extra_objs="winnt.o winnt-stubs.o"
c_target_objs=cygwin2.o
cxx_target_objs=cygwin2.o
cxx_target_objs="cygwin2.o winnt-cxx.o"
extra_gcc_objs=cygwin1.o
if test x$enable_threads = xyes; then
thread_file='posix'
@ -1216,7 +1216,8 @@ i[34567]86-*-mingw32*)
tmake_file="i386/t-cygming i386/t-mingw32"
target_gtfiles="\$(srcdir)/config/i386/winnt.c"
extra_options="${extra_options} i386/cygming.opt"
extra_objs=winnt.o
extra_objs="winnt.o winnt-stubs.o"
cxx_target_objs=winnt-cxx.o
case ${enable_threads} in
"" | yes | win32) thread_file='win32' ;;
esac

View File

@ -410,6 +410,9 @@ extern int i386_pe_dllimport_name_p (const char *);
#undef NO_PROFILE_COUNTERS
#define NO_PROFILE_COUNTERS 1
#define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P i386_pe_valid_dllimport_attribute_p
#define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION i386_pe_adjust_class_at_definition
#undef TREE
#ifndef BUFSIZ

View File

@ -244,6 +244,13 @@ extern void i386_pe_encode_section_info (tree, rtx, int);
extern const char *i386_pe_strip_name_encoding (const char *);
extern const char *i386_pe_strip_name_encoding_full (const char *);
extern void i386_pe_output_labelref (FILE *, const char *);
extern bool i386_pe_valid_dllimport_attribute_p (tree);
/* In winnt-cxx.c and winnt-stubs.c */
extern void i386_pe_adjust_class_at_definition (tree);
extern bool i386_pe_type_dllimport_p (tree);
extern bool i386_pe_type_dllexport_p (tree);
extern rtx maybe_get_pool_constant (rtx);
extern char internal_label_prefix[16];

View File

@ -1982,7 +1982,7 @@ ix86_function_ok_for_sibcall (tree decl, tree exp)
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
/* Dllimport'd functions are also called indirectly. */
if (decl && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))
if (decl && DECL_DLLIMPORT_P (decl)
&& ix86_function_regparm (TREE_TYPE (decl), NULL) >= 3)
return false;
#endif

View File

@ -16,4 +16,17 @@ winnt.o: $(srcdir)/config/i386/winnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/winnt.c
winnt-cxx.o: $(srcdir)/config/i386/winnt-cxx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/winnt-cxx.c
winnt-stubs.o: $(srcdir)/config/i386/winnt-stubs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/winnt-stubs.c
STMP_FIXINC=stmp-fixinc

166
gcc/config/i386/winnt-cxx.c Executable file
View File

@ -0,0 +1,166 @@
/* Target support for C++ classes on Windows.
Contributed by Danny Smith (dannysmith@users.sourceforge.net)
Copyright (C) 2005
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, 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "output.h"
#include "tree.h"
#include "cp/cp-tree.h" /* this is why we're a separate module */
#include "flags.h"
#include "tm_p.h"
#include "toplev.h"
#include "hashtab.h"
bool
i386_pe_type_dllimport_p (tree decl)
{
gcc_assert (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL);
if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
return false;
/* We ignore the dllimport attribute for inline member functions.
This differs from MSVC behavior which treats it like GNUC
'extern inline' extension. Also ignore for template
instantiations with linkonce semantics and artificial methods. */
if (TREE_CODE (decl) == FUNCTION_DECL
&& (DECL_DECLARED_INLINE_P (decl)
|| DECL_TEMPLATE_INSTANTIATION (decl)
|| DECL_ARTIFICIAL (decl)))
return false;
/* 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))
{
/* Even though we ignore the attribute from the start, warn if we later see
an out-of class definition, as we do for other member functions in
tree.c:merge_dllimport_decl_attributes. If this is the key method, the
definition may affect the import-export status of vtables, depending
on how we handle MULTIPLE_SYMBOL_SPACES in cp/decl2.c. */
if (DECL_INITIAL (decl))
{
warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
"previous dllimport ignored", decl);
#ifdef PE_DLL_DEBUG
if (decl == CLASSTYPE_KEY_METHOD (DECL_CONTEXT (decl)))
warning (OPT_Wattributes, "key method %q+D of dllimport'd class defined"
decl);
#endif
}
return false;
}
/* Don't mark defined functions as dllimport. This code will only be
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;
}
bool
i386_pe_type_dllexport_p (tree decl)
{
gcc_assert (TREE_CODE (decl) == VAR_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
and non-virtual thunks. */
if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
&& DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl))
return false;
return true;
}
static inline void maybe_add_dllimport (tree decl)
{
if (i386_pe_type_dllimport_p (decl))
DECL_DLLIMPORT_P (decl) = 1;
}
void
i386_pe_adjust_class_at_definition (tree t)
{
tree member;
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))
maybe_add_dllimport (member);
/* 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. */
}

53
gcc/config/i386/winnt-stubs.c Executable file
View File

@ -0,0 +1,53 @@
/* Dummy subroutines for language-specific support on Windows.
Contributed by Danny Smith (dannysmith@users.sourceforge.net)
Copyright (C) 2005
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"
#include "coretypes.h"
#include "tm.h"
#include "rtl.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "output.h"
#include "tree.h"
#include "flags.h"
#include "tm_p.h"
#include "toplev.h"
#include "hashtab.h"
bool
i386_pe_type_dllimport_p (tree decl ATTRIBUTE_UNUSED)
{
return false;
}
bool
i386_pe_type_dllexport_p (tree decl ATTRIBUTE_UNUSED)
{
return false;
}
void
i386_pe_adjust_class_at_definition (tree t ATTRIBUTE_UNUSED)
{ }

View File

@ -48,8 +48,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
static tree associated_type (tree);
static tree gen_stdcall_or_fastcall_suffix (tree, bool);
static int i386_pe_dllexport_p (tree);
static int i386_pe_dllimport_p (tree);
static bool i386_pe_dllexport_p (tree);
static bool i386_pe_dllimport_p (tree);
static void i386_pe_mark_dllexport (tree);
static void i386_pe_mark_dllimport (tree);
@ -115,131 +115,63 @@ ix86_handle_selectany_attribute (tree *node, tree name,
static tree
associated_type (tree decl)
{
tree t = NULL_TREE;
/* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer
to the containing class. So we look at the 'this' arg. */
if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
{
/* Artificial methods are not affected by the import/export status
of their class unless they are COMDAT. Implicit copy ctor's and
dtor's are not affected by class status but virtual and
non-virtual thunks are. */
if (!DECL_ARTIFICIAL (decl) || DECL_COMDAT (decl))
t = TYPE_MAIN_VARIANT
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
}
else if (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
t = DECL_CONTEXT (decl);
return t;
return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
? DECL_CONTEXT (decl) : NULL_TREE;
}
/* Return nonzero if DECL is a dllexport'd object. */
static int
/* Return true if DECL is a dllexport'd object. */
static bool
i386_pe_dllexport_p (tree decl)
{
tree exp;
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
if (exp)
return 1;
&& TREE_CODE (decl) != FUNCTION_DECL)
return false;
/* Class members get the dllexport status of their class. */
if (associated_type (decl))
{
exp = lookup_attribute ("dllexport",
TYPE_ATTRIBUTES (associated_type (decl)));
if (exp)
return 1;
}
if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
return true;
return 0;
/* Also mark class members of exported classes with dllexport. */
if (associated_type (decl)
&& lookup_attribute ("dllexport",
TYPE_ATTRIBUTES (associated_type (decl))))
return i386_pe_type_dllexport_p (decl);
return false;
}
/* Return nonzero if DECL is a dllimport'd object. */
static int
static bool
i386_pe_dllimport_p (tree decl)
{
tree imp;
int context_imp = 0;
if (TREE_CODE (decl) == FUNCTION_DECL
&& TARGET_NOP_FUN_DLLIMPORT)
return 0;
if (TREE_CODE (decl) != VAR_DECL
&& TREE_CODE (decl) != FUNCTION_DECL)
return 0;
&& TREE_CODE (decl) != FUNCTION_DECL)
return false;
imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
/* Lookup the attribute rather than rely on the DECL_DLLIMPORT_P flag.
We may need to override an earlier decision. */
if (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
return true;
/* 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;
}
/* The DECL_DLLIMPORT_P flag was set for decls in the class definition
by targetm.cxx.adjust_class_at_definition. Check again to emit
warnings if the class attribute has been overriden by an
out-of-class definition. */
if (associated_type (decl)
&& lookup_attribute ("dllimport",
TYPE_ATTRIBUTES (associated_type (decl))))
return i386_pe_type_dllimport_p (decl);
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 (0, "function %q+D is defined after prior declaration "
"as dllimport: attribute ignored", decl);
return 0;
}
return false;
}
/* We ignore the dllimport attribute for inline member functions.
This differs from MSVC behavior which treats it like GNUC
'extern inline' extension. */
else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
{
if (extra_warnings)
warning (0, "inline function %q+D is declared as dllimport: "
"attribute ignored", 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 ("definition of static data member %q+D of "
"dllimport'd class", 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. Don't mark
artificial methods either (in associated_type, only COMDAT
artificial method get import status from class context). */
else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
&& (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
return 0;
return 1;
}
return 0;
/* Handle the -mno-fun-dllimport target switch. */
bool
i386_pe_valid_dllimport_attribute_p (tree decl)
{
if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
return false;
return true;
}
/* Return nonzero if SYMBOL is marked as being dllexport'd. */
@ -283,7 +215,6 @@ i386_pe_mark_dllexport (tree 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 */
@ -328,7 +259,9 @@ i386_pe_mark_dllimport (tree decl)
{
/* Already done, but do a sanity check to prevent assembler
errors. */
gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl));
gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
&& DECL_DLLIMPORT_P (decl));
return;
}
newname = alloca (strlen (DLL_IMPORT_PREFIX) + strlen (oldname) + 1);
@ -345,8 +278,7 @@ i386_pe_mark_dllimport (tree decl)
newrtl = gen_rtx_MEM (Pmode,symref);
XEXP (DECL_RTL (decl), 0) = newrtl;
/* Can't treat a pointer to this as a constant address */
DECL_NON_ADDR_CONST_P (decl) = 1;
DECL_DLLIMPORT_P (decl) = 1;
}
/* Return string which is the former assembler name modified with a
@ -431,45 +363,25 @@ i386_pe_encode_section_info (tree decl, rtx rtl, int 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. */
dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes
handles dllexport/dllimport override semantics. */
if (i386_pe_dllexport_p (decl))
i386_pe_mark_dllexport (decl);
else if (i386_pe_dllimport_p (decl))
i386_pe_mark_dllimport (decl);
/* It might be that DECL has already been marked as dllimport, but a
subsequent definition nullified that. The attribute is gone but
DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
that. Ditto for the DECL_NON_ADDR_CONST_P flag. */
else if ((TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& DECL_RTL (decl) != NULL_RTX
&& GET_CODE (DECL_RTL (decl)) == MEM
&& GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
&& GET_CODE (XEXP (XEXP (DECL_RTL (decl), 0), 0)) == SYMBOL_REF
&& i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0)))
{
const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
/* Remove DLL_IMPORT_PREFIX. */
tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
rtx symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
SYMBOL_REF_DECL (symref) = decl;
XEXP (DECL_RTL (decl), 0) = symref;
DECL_NON_ADDR_CONST_P (decl) = 0;
/* We previously set TREE_PUBLIC and DECL_EXTERNAL.
We leave these alone for now. */
if (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
warning (0, "%q+D defined locally after being "
"referenced with dllimport linkage", decl);
else
warning (OPT_Wattributes, "%q+D redeclared without dllimport "
"attribute after being referenced with dllimport linkage",
decl);
}
/* It might be that DECL has been declared as dllimport, but a
subsequent definition nullified that. Assert that
tree.c: merge_dllimport_decl_attributes has removed the attribute
before the RTL name was marked with the DLL_IMPORT_PREFIX. */
else
gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == VAR_DECL)
&& rtl != NULL_RTX
&& GET_CODE (rtl) == MEM
&& GET_CODE (XEXP (rtl, 0)) == MEM
&& GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF
&& i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0))));
}
/* Strip only the leading encoding, leaving the stdcall suffix and fastcall

View File

@ -1,3 +1,11 @@
2005-10-12 Danny Smith <dannysmith@users.sourceforge.net>
PR target/21801
PR target/23589
* class.c (finish_struct_1): Call
targetm.cxx.adjust_class_at_definition.
2005-10-12 Nathan Sidwell <nathan@codesourcery.com>
PR c++/21592

View File

@ -5028,6 +5028,11 @@ finish_struct_1 (tree t)
if (warn_overloaded_virtual)
warn_hidden (t);
/* Class layout, assignment of virtual table slots, etc., is now
complete. Give the back end a chance to tweak the visibility of
the class or perform any other required target modifications. */
targetm.cxx.adjust_class_at_definition (t);
maybe_suppress_debug_info (t);
dump_class_hierarchy (t);

View File

@ -8478,6 +8478,12 @@ to perform initial processing of the @samp{dllimport} and
@file{i386/i386.c}, for example.
@end deftypefn
@deftypefn {Target Hook} bool TARGET_VALID_DLLIMPORT_ATTRIBUTE_P (tree @var{decl})
@var{decl} is a variable or function with @code{__attribute__((dllimport))}
specified. Use this hook if the target needs to add extra validation
checks to @code{handle_dll_attribute}.
@end deftypefn
@defmac TARGET_DECLSPEC
Define this macro to a nonzero value if you want to treat
@code{__declspec(X)} as equivalent to @code{__attribute((X))}. By
@ -8657,6 +8663,12 @@ should be used to register static destructors when @option{-fuse-cxa-atexit}
is in effect. The default is to return false to use @code{__cxa_atexit}.
@end deftypefn
@deftypefn {Target Hook} void TARGET_CXX_ADJUST_CLASS_AT_DEFINITION (tree @var{type})
@var{type} is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that has just been
defined. Use this hook to make adjustments to the class (eg, tweak
visibility or perform any other required target modifications).
@end deftypefn
@node Misc
@section Miscellaneous Parameters
@cindex parameters, miscellaneous

View File

@ -147,6 +147,10 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define TARGET_INVALID_WITHIN_DOLOOP default_invalid_within_doloop
#endif
#ifndef TARGET_VALID_DLLIMPORT_ATTRIBUTE_P
#define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P hook_bool_tree_true
#endif
#ifndef TARGET_HAVE_TLS
#define TARGET_HAVE_TLS false
#endif
@ -516,6 +520,10 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#define TARGET_CXX_USE_AEABI_ATEXIT hook_bool_void_false
#endif
#ifndef TARGET_CXX_ADJUST_CLASS_AT_DEFINITION
#define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION hook_void_tree
#endif
#define TARGET_CXX \
{ \
TARGET_CXX_GUARD_TYPE, \
@ -528,6 +536,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY, \
TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT, \
TARGET_CXX_USE_AEABI_ATEXIT, \
TARGET_CXX_ADJUST_CLASS_AT_DEFINITION \
}
/* The whole shebang. */
@ -593,6 +602,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
TARGET_STACK_PROTECT_GUARD, \
TARGET_STACK_PROTECT_FAIL, \
TARGET_INVALID_WITHIN_DOLOOP, \
TARGET_VALID_DLLIMPORT_ATTRIBUTE_P, \
TARGET_CALLS, \
TARGET_INVALID_CONVERSION, \
TARGET_INVALID_UNARY_OP, \

View File

@ -550,6 +550,11 @@ struct gcc_target
/* Returns NULL if target supports the insn within a doloop block,
otherwise it returns an error message. */
const char * (*invalid_within_doloop) (rtx);
/* DECL is a variable or function with __attribute__((dllimport))
specified. Use this hook if the target needs to add extra validation
checks to handle_dll_attribute (). */
bool (* valid_dllimport_attribute_p) (tree decl);
/* Functions relating to calls - argument passing, returns, etc. */
struct calls {
@ -660,6 +665,11 @@ struct gcc_target
/* Returns true if __aeabi_atexit should be used to register static
destructors. */
bool (*use_aeabi_atexit) (void);
/* TYPE is a C++ class (i.e., RECORD_TYPE or UNION_TYPE) that
has just been defined. Use this hook to make adjustments to the
class (eg, tweak visibility or perform any other required
target modifications). */
void (*adjust_class_at_definition) (tree type);
} cxx;
/* True if unwinding tables should be generated by default. */

View File

@ -1,3 +1,16 @@
2005-10-12 Danny Smith <dannysmith@users.sourceforge.net>
* gcc.dg/dll-2.c: Add tests for warnings.
* gcc.dg/dll-3.c: Likewise.
* gcc.dg/dll-4.c: Likewise.
* g++.dg/ext/dllimport1.C: Adjust tests for warnings.
* g++.dg/ext/dllimport2.C: Likewise.
* g++.dg/ext/dllimport3.C: Likewise.
* g++.dg/ext/dllimport7.C: Likewise.
* g++.dg/ext/dllimport8.C: Likewise.
* g++.dg/ext/dllimport9.C: Likewise.
2005-10-10 Paul Thomas <pault@gcc.gnu.org>
PR fortran/24092

View File

@ -5,13 +5,13 @@
class __attribute__((dllimport)) Foo
{
public:
virtual void dummy_foo_func(void) // { dg-warning "inline function" }
virtual void dummy_foo_func(void)
{}
void Foo::dummy_foo_fun2();
void dummy_foo_fun2();
virtual ~Foo(); // avoid warning
};
void Foo::dummy_foo_fun2() // { dg-warning "defined" }
void Foo::dummy_foo_fun2() // { dg-warning "redeclared without dllimport" }
{
}

View File

@ -1,5 +1,4 @@
// { 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);
@ -7,6 +6,7 @@ void __attribute__((dllimport)) Baz(void);
__attribute__((dllimport)) int Biz;
__attribute__((dllimport)) int Boz;
void Foo(void)
{
Bar();
@ -14,14 +14,13 @@ void Foo(void)
Biz++;
Boz++;
}
void Bar(void) // { dg-warning "defined" }
void Baz(void); // { dg-warning "referenced with dll linkage" }
void Bar(void) // { dg-warning "referenced with dll linkage" }
{
}
void Baz(void); // { dg-warning "redeclared" }
extern int Biz; // { dg-warning "redeclared" }
int Boz; // { dg-warning "defined" }
extern int Biz; // { dg-warning "referenced with dll linkage" }
int Boz; // { dg-warning "referenced with dll linkage" }
void foo()
{

View File

@ -4,22 +4,21 @@
// redefinition without attribute.
struct Foo
{
int a;
};
{
int a;
};
__attribute__((dllimport)) struct Foo f;
void Bar(void)
{
void* dummy = &f;
}
void Bar(void)
{
void* dummy = (void*) &f;
}
struct Foo f; // { dg-warning "defined" }
struct Foo f; // { dg-warning "referenced with dll linkage" }
// Dllimport sets DECL_NON_ADDR_CONST_P to 1, so following
// Dllimport'd symbols do not have a constant address, so following
// assignment would require static_initialization_and_destruction
// if attribute is retained.
void* dummy = &f;
void* dummy = &f;

View File

@ -18,8 +18,12 @@ class __declspec(dllimport) Bar
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" }
const int Bar::three = 3; // { dg-warning "redeclared without dllimport" }
// { dg-error "definition of static data" "C++ specific error" { target i?86-*-cygwin* i?86-*-mingw* } 21 }
const Baz Bar::null_baz; // { dg-warning "redeclared without dllimport" }
// { dg-error "definition of static data" "C++ specific error" { target i?86-*-cygwin* i?86-*-mingw* } 24 }
int foo()

View File

@ -6,19 +6,19 @@
// { dg-options { -Wall -W } }
struct __attribute__((dllimport)) Foo
{
static int static_int;
static void static_func1();
static void static_func2();
{
static int static_int;
static void static_func1();
static void static_func2();
};
void Foo::static_func1() // { dg-warning "defined" }
{
}
void Foo::static_func1() // { dg-warning "redeclared without dllimport" }
{
}
inline void Foo::static_func2() // { dg-warning "inline function" }
{
}
inline void Foo::static_func2()
{
}
void testfoo()
{

View File

@ -6,11 +6,11 @@ inline __attribute__((dllimport)) void bar() { } // { dg-warning "inline" }
struct __attribute__ ((dllimport)) Blah
{
void in_blah () { } // { dg-warning "inline" }
void in_blah () { } // Don't warn if member declared inline in class definition.
void out_blah ();
};
inline void Blah::out_blah(){ } // { dg-warning "inline" }
inline void Blah::out_blah(){ } // Don't warn for inline override of external declaration
void use_inlines()
{

View File

@ -11,13 +11,12 @@
/* { dg-require-dll "" } */
__declspec (dllimport) int foo1 ();
__declspec (dllexport) int foo1 ();
__declspec (dllexport) int foo1 (); /* { dg-warning "previous dllimport ignored" } */
__declspec (dllexport) int foo2 ();
__declspec (dllimport) int foo2 ();
__declspec (dllimport) int foo2 (); /* { dg-warning "dllimport ignored" } */
__declspec (dllimport) int bar1;
__declspec (dllexport) int bar1;
__declspec (dllexport) int bar1; /* { dg-warning "previous dllimport ignored" } */
__declspec (dllexport) int bar2;
__declspec (dllimport) int bar2;
__declspec (dllimport) int bar2; /* { dg-warning "dllimport ignored" } */

View File

@ -5,10 +5,10 @@
/* { dg-do compile { target i?86-pc-mingw* } } */
__declspec (dllimport) int foo1 ();
__declspec (dllexport) int foo1 ();
__declspec (dllexport) int foo1 (); /* { dg-warning "previous dllimport ignored" } */
__declspec (dllexport) int foo2 ();
__declspec (dllimport) int foo2 ();
__declspec (dllimport) int foo2 (); /* { dg-warning "dllimport ignored" } */
__declspec (dllexport) int foo1 () { return foo2 (); }
__declspec (dllexport) int foo2 () { return foo1 (); }

View File

@ -3,10 +3,10 @@
/* { dg-do compile { target i?86-pc-mingw* } } */
__declspec (dllimport) int foo1;
int foo1;
int foo1; /* { dg-warning "redeclared without dllimport" } */
__declspec (dllimport) int foo2;
int foo2 = 5;
int foo2 = 5; /* { dg-warning "redeclared without dllimport" } */
int f () { return foo1 + foo2; }

View File

@ -1797,7 +1797,7 @@ staticp (tree arg)
case VAR_DECL:
return ((TREE_STATIC (arg) || DECL_EXTERNAL (arg))
&& ! DECL_THREAD_LOCAL_P (arg)
&& ! DECL_NON_ADDR_CONST_P (arg)
&& ! DECL_DLLIMPORT_P (arg)
? arg : NULL);
case CONST_DECL:
@ -3478,31 +3478,66 @@ tree
merge_dllimport_decl_attributes (tree old, tree new)
{
tree a;
int delete_dllimport_p;
old = DECL_ATTRIBUTES (old);
new = DECL_ATTRIBUTES (new);
int delete_dllimport_p = 1;
/* What we need to do here is remove from `old' dllimport if it doesn't
appear in `new'. dllimport behaves like extern: if a declaration is
marked dllimport and a definition appears later, then the object
is not dllimport'd. */
if (lookup_attribute ("dllimport", old) != NULL_TREE
&& lookup_attribute ("dllimport", new) == NULL_TREE)
delete_dllimport_p = 1;
is not dllimport'd. We also remove a `new' dllimport if the old list
contains dllexport: dllexport always overrides dllimport, regardless
of the order of declaration. */
if (!VAR_OR_FUNCTION_DECL_P (new))
delete_dllimport_p = 0;
else if (DECL_DLLIMPORT_P (new)
&& lookup_attribute ("dllexport", DECL_ATTRIBUTES (old)))
{
DECL_DLLIMPORT_P (new) = 0;
warning (OPT_Wattributes, "%q+D already declared with dllexport attribute: "
"dllimport ignored", new);
}
else if (DECL_DLLIMPORT_P (old) && !DECL_DLLIMPORT_P (new))
{
/* Warn about overriding a symbol that has already been used. eg:
extern int __attribute__ ((dllimport)) foo;
int* bar () {return &foo;}
int foo;
*/
if (TREE_USED (old))
{
warning (0, "%q+D redeclared without dllimport attribute "
"after being referenced with dll linkage", new);
/* If we have used a variable's address with dllimport linkage,
keep the old DECL_DLLIMPORT_P flag: the ADDR_EXPR using the
decl may already have had TREE_INVARIANT and TREE_CONSTANT
computed.
We still remove the attribute so that assembler code refers
to '&foo rather than '_imp__foo'. */
if (TREE_CODE (old) == VAR_DECL && TREE_ADDRESSABLE (old))
DECL_DLLIMPORT_P (new) = 1;
}
/* Let an inline definition silently override the external reference,
but otherwise warn about attribute inconsistency. */
else if (TREE_CODE (new) == VAR_DECL
|| !DECL_DECLARED_INLINE_P (new))
warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
"previous dllimport ignored", new);
}
else
delete_dllimport_p = 0;
a = merge_attributes (old, new);
a = merge_attributes (DECL_ATTRIBUTES (old), DECL_ATTRIBUTES (new));
if (delete_dllimport_p)
if (delete_dllimport_p)
{
tree prev, t;
const size_t attr_len = strlen ("dllimport");
/* Scan the list for dllimport and delete it. */
for (prev = NULL_TREE, t = a; t; prev = t, t = TREE_CHAIN (t))
{
if (is_attribute_p ("dllimport", TREE_PURPOSE (t)))
if (is_attribute_with_length_p ("dllimport", attr_len,
TREE_PURPOSE (t)))
{
if (prev == NULL_TREE)
a = TREE_CHAIN (a);
@ -3549,18 +3584,26 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
any damage. */
if (is_attribute_p ("dllimport", name))
{
/* Honor any target-specific overides. */
if (!targetm.valid_dllimport_attribute_p (node))
*no_add_attrs = true;
else if (TREE_CODE (node) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (node))
{
warning (OPT_Wattributes, "inline function %q+D declared as "
" dllimport: attribute ignored", node);
*no_add_attrs = true;
}
/* 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. */
if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node)
&& !DECL_DECLARED_INLINE_P (node))
non-inlined functions on declaration as syntax errors. */
else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node))
{
error ("function %q+D definition is marked dllimport", node);
*no_add_attrs = true;
}
else if (TREE_CODE (node) == VAR_DECL)
else if (TREE_CODE (node) == VAR_DECL)
{
if (DECL_INITIAL (node))
{
@ -3577,6 +3620,9 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
TREE_PUBLIC (node) = 1;
}
if (*no_add_attrs == false)
DECL_DLLIMPORT_P (node) = 1;
}
/* Report error if symbol is not accessible at global scope. */

View File

@ -2421,9 +2421,8 @@ struct tree_parm_decl GTY(())
#define DECL_GIMPLE_FORMAL_TEMP_P(DECL) \
DECL_WITH_VIS_CHECK (DECL)->decl_with_vis.gimple_formal_temp
/* Used to indicate that the pointer to this DECL cannot be treated as
an address constant. */
#define DECL_NON_ADDR_CONST_P(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.non_addr_const_p)
/* Used to indicate that the DECL is a dllimport. */
#define DECL_DLLIMPORT_P(NODE) (DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.dllimport_flag)
/* DECL_BASED_ON_RESTRICT_P records whether a VAR_DECL is a temporary
based on a variable with a restrict qualified type. If it is,
@ -2514,7 +2513,7 @@ struct tree_decl_with_vis GTY(())
unsigned common_flag:1;
unsigned in_text_section : 1;
unsigned gimple_formal_temp : 1;
unsigned non_addr_const_p : 1;
unsigned dllimport_flag : 1;
unsigned based_on_restrict_p : 1;
/* Used by C++. Might become a generic decl flag. */
unsigned shadowed_for_var_p : 1;

View File

@ -3643,7 +3643,7 @@ initializer_constant_valid_p (tree value, tree endtype)
if (value
&& TREE_CODE (value) == FUNCTION_DECL
&& ((decl_function_context (value) && !DECL_NO_STATIC_CHAIN (value))
|| DECL_NON_ADDR_CONST_P (value)))
|| DECL_DLLIMPORT_P (value)))
return NULL_TREE;
return value;