PR middle-end/21275
authordannysmith <dannysmith@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 12 Oct 2005 20:54:50 +0000 (20:54 +0000)
committerdannysmith <dannysmith@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 12 Oct 2005 20:54:50 +0000 (20:54 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@105332 138bc75d-0d04-0410-961f-82ee72b054a4

27 files changed:
gcc/ChangeLog
gcc/config.gcc
gcc/config/i386/cygming.h
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/t-cygming
gcc/config/i386/winnt-cxx.c [new file with mode: 0755]
gcc/config/i386/winnt-stubs.c [new file with mode: 0755]
gcc/config/i386/winnt.c
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/doc/tm.texi
gcc/target-def.h
gcc/target.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/dllimport1.C
gcc/testsuite/g++.dg/ext/dllimport2.C
gcc/testsuite/g++.dg/ext/dllimport3.C
gcc/testsuite/g++.dg/ext/dllimport7.C
gcc/testsuite/g++.dg/ext/dllimport8.C
gcc/testsuite/g++.dg/ext/dllimport9.C
gcc/testsuite/gcc.dg/dll-2.c
gcc/testsuite/gcc.dg/dll-3.c
gcc/testsuite/gcc.dg/dll-4.c
gcc/tree.c
gcc/tree.h
gcc/varasm.c

index f2b9db3..18c64b8 100644 (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.
index 9acca82..21c6dab 100644 (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
index 4259c13..4005f1d 100644 (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
index 8b34e03..6c81d4d 100644 (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];
index fa29570..7b3cf6a 100644 (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
index aa6ff61..c001a8b 100644 (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
diff --git a/gcc/config/i386/winnt-cxx.c b/gcc/config/i386/winnt-cxx.c
new file mode 100755 (executable)
index 0000000..5117bd7
--- /dev/null
@@ -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 (executable)
index 0000000..b373345
--- /dev/null
@@ -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)
+{ }
index c1c605c..f8a36ff 100644 (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;
-
-  /* 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
index 404c7de..cb4ce85 100644 (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
index 3f56652..dceeffe 100644 (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);
index 16b48ff..46d24b6 100644 (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
index e874bb7..6dd121d 100644 (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,                     \
index 564c333..cd850d1 100644 (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.  */
index 99d2dbd..18ed822 100644 (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
index 2536312..1fb69ed 100644 (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" }
 {
 }
 
index 7b3f685..87a96d8 100644 (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()
 {
index 5a13a50..cd16dfa 100644 (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;
index fa76d3e..9754ada 100644 (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()
index 7bc2b46..55326c5 100644 (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()
 { 
index edf79ef..8d60bb8 100644 (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()
 {
index 5c81f4e..3b8b60e 100644 (file)
 /* { 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" } */
index 2d5517e..0a3f7df 100644 (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 (); }
index 45ed7a1..9fcc8e9 100644 (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; }
 
index 333c745..946bf90 100644 (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.  */
index 08f33fe..144dbd8 100644 (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;
index 286abb3..1aee983 100644 (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;