summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog59
-rw-r--r--gcc/config.gcc7
-rw-r--r--gcc/config/i386/cygming.h3
-rw-r--r--gcc/config/i386/i386-protos.h7
-rw-r--r--gcc/config/i386/i386.c2
-rw-r--r--gcc/config/i386/t-cygming13
-rwxr-xr-xgcc/config/i386/winnt-cxx.c166
-rwxr-xr-xgcc/config/i386/winnt-stubs.c53
-rw-r--r--gcc/config/i386/winnt.c216
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/class.c5
-rw-r--r--gcc/doc/tm.texi12
-rw-r--r--gcc/target-def.h10
-rw-r--r--gcc/target.h10
-rw-r--r--gcc/testsuite/ChangeLog13
-rw-r--r--gcc/testsuite/g++.dg/ext/dllimport1.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/dllimport2.C13
-rw-r--r--gcc/testsuite/g++.dg/ext/dllimport3.C21
-rw-r--r--gcc/testsuite/g++.dg/ext/dllimport7.C8
-rw-r--r--gcc/testsuite/g++.dg/ext/dllimport8.C20
-rw-r--r--gcc/testsuite/g++.dg/ext/dllimport9.C4
-rw-r--r--gcc/testsuite/gcc.dg/dll-2.c9
-rw-r--r--gcc/testsuite/gcc.dg/dll-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/dll-4.c4
-rw-r--r--gcc/tree.c84
-rw-r--r--gcc/tree.h7
-rw-r--r--gcc/varasm.c2
27 files changed, 542 insertions, 224 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f2b9db354b6..18c64b801c3 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 9acca827cc8..21c6dab8cd9 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -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
diff --git a/gcc/config/i386/cygming.h b/gcc/config/i386/cygming.h
index 4259c1381ff..4005f1d8e63 100644
--- a/gcc/config/i386/cygming.h
+++ b/gcc/config/i386/cygming.h
@@ -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
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 8b34e03ebc7..6c81d4d7e9f 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -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];
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index fa2957080ef..7b3cf6a9255 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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
diff --git a/gcc/config/i386/t-cygming b/gcc/config/i386/t-cygming
index aa6ff61ca03..c001a8b0f61 100644
--- a/gcc/config/i386/t-cygming
+++ b/gcc/config/i386/t-cygming
@@ -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
diff --git a/gcc/config/i386/winnt-cxx.c b/gcc/config/i386/winnt-cxx.c
new file mode 100755
index 00000000000..5117bd7c7c6
--- /dev/null
+++ b/gcc/config/i386/winnt-cxx.c
@@ -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. */
+}
diff --git a/gcc/config/i386/winnt-stubs.c b/gcc/config/i386/winnt-stubs.c
new file mode 100755
index 00000000000..b373345de9c
--- /dev/null
+++ b/gcc/config/i386/winnt-stubs.c
@@ -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)
+{ }
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index c1c605c6a1c..f8a36ff1ba1 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -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;
-
- /* 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;
- }
+ && TREE_CODE (decl) != FUNCTION_DECL)
+ return false;
- return 0;
-}
+ if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+ return true;
+
+ /* 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 nonzero if DECL is a dllimport'd object. */
+ return false;
+}
-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;
-
- imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
-
- /* Class members get the dllimport status of their class. */
- if (!imp && associated_type (decl))
- {
- imp = lookup_attribute ("dllimport",
- TYPE_ATTRIBUTES (associated_type (decl)));
- if (imp)
- context_imp = 1;
- }
-
- if (imp)
- {
- /* Don't mark defined functions as dllimport. If the definition
- itself was marked with dllimport, than ix86_handle_dll_attribute
- reports an error. This handles the case when the definition
- overrides an earlier declaration. */
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)
- && !DECL_INLINE (decl))
- {
- /* Don't warn about artificial methods. */
- if (!DECL_ARTIFICIAL (decl))
- warning (0, "function %q+D is defined after prior declaration "
- "as dllimport: attribute ignored", decl);
- return 0;
- }
-
- /* 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;
- }
+ && TREE_CODE (decl) != FUNCTION_DECL)
+ return false;
+
+ /* 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;
+
+ /* 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);
+
+ return false;
+}
- 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
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 404c7de9943..cb4ce856bfc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 3f56652f045..dceeffe29c1 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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);
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 16b48ff87a4..46d24b6b789 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/target-def.h b/gcc/target-def.h
index e874bb7147b..6dd121d952f 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -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, \
diff --git a/gcc/target.h b/gcc/target.h
index 564c333136c..cd850d1a4b5 100644
--- a/gcc/target.h
+++ b/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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 99d2dbd3309..18ed822c4f3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/ext/dllimport1.C b/gcc/testsuite/g++.dg/ext/dllimport1.C
index 253631276a7..1fb69ed9f5c 100644
--- a/gcc/testsuite/g++.dg/ext/dllimport1.C
+++ b/gcc/testsuite/g++.dg/ext/dllimport1.C
@@ -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" }
{
}
diff --git a/gcc/testsuite/g++.dg/ext/dllimport2.C b/gcc/testsuite/g++.dg/ext/dllimport2.C
index 7b3f68575de..87a96d8ddee 100644
--- a/gcc/testsuite/g++.dg/ext/dllimport2.C
+++ b/gcc/testsuite/g++.dg/ext/dllimport2.C
@@ -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()
{
diff --git a/gcc/testsuite/g++.dg/ext/dllimport3.C b/gcc/testsuite/g++.dg/ext/dllimport3.C
index 5a13a509d4f..cd16dfa2505 100644
--- a/gcc/testsuite/g++.dg/ext/dllimport3.C
+++ b/gcc/testsuite/g++.dg/ext/dllimport3.C
@@ -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;
diff --git a/gcc/testsuite/g++.dg/ext/dllimport7.C b/gcc/testsuite/g++.dg/ext/dllimport7.C
index fa76d3eec8c..9754ada962c 100644
--- a/gcc/testsuite/g++.dg/ext/dllimport7.C
+++ b/gcc/testsuite/g++.dg/ext/dllimport7.C
@@ -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()
diff --git a/gcc/testsuite/g++.dg/ext/dllimport8.C b/gcc/testsuite/g++.dg/ext/dllimport8.C
index 7bc2b46b702..55326c51866 100644
--- a/gcc/testsuite/g++.dg/ext/dllimport8.C
+++ b/gcc/testsuite/g++.dg/ext/dllimport8.C
@@ -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()
{
diff --git a/gcc/testsuite/g++.dg/ext/dllimport9.C b/gcc/testsuite/g++.dg/ext/dllimport9.C
index edf79efd8d1..8d60bb84d3a 100644
--- a/gcc/testsuite/g++.dg/ext/dllimport9.C
+++ b/gcc/testsuite/g++.dg/ext/dllimport9.C
@@ -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()
{
diff --git a/gcc/testsuite/gcc.dg/dll-2.c b/gcc/testsuite/gcc.dg/dll-2.c
index 5c81f4e64a1..3b8b60eee41 100644
--- a/gcc/testsuite/gcc.dg/dll-2.c
+++ b/gcc/testsuite/gcc.dg/dll-2.c
@@ -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" } */
diff --git a/gcc/testsuite/gcc.dg/dll-3.c b/gcc/testsuite/gcc.dg/dll-3.c
index 2d5517eace6..0a3f7df0988 100644
--- a/gcc/testsuite/gcc.dg/dll-3.c
+++ b/gcc/testsuite/gcc.dg/dll-3.c
@@ -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 (); }
diff --git a/gcc/testsuite/gcc.dg/dll-4.c b/gcc/testsuite/gcc.dg/dll-4.c
index 45ed7a11007..9fcc8e9ad2c 100644
--- a/gcc/testsuite/gcc.dg/dll-4.c
+++ b/gcc/testsuite/gcc.dg/dll-4.c
@@ -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; }
diff --git a/gcc/tree.c b/gcc/tree.c
index 333c745fc01..946bf90044e 100644
--- a/gcc/tree.c
+++ b/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. */
diff --git a/gcc/tree.h b/gcc/tree.h
index 08f33fe0d95..144dbd87061 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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;
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 286abb3eb93..1aee9839e2d 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -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;