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:
parent
bce7137612
commit
43d9ad1dbd
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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
|
||||
|
@ -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
166
gcc/config/i386/winnt-cxx.c
Executable 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
53
gcc/config/i386/winnt-stubs.c
Executable 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)
|
||||
{ }
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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, \
|
||||
|
10
gcc/target.h
10
gcc/target.h
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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" }
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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" } */
|
||||
|
@ -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 (); }
|
||||
|
@ -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; }
|
||||
|
||||
|
84
gcc/tree.c
84
gcc/tree.c
@ -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. */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user