1/* Target support for C++ classes on Windows. 2 Contributed by Danny Smith (dannysmith@users.sourceforge.net) 3 Copyright (C) 2005 4 Free Software Foundation, Inc. 5 6This file is part of GCC. 7 8GCC is free software; you can redistribute it and/or modify it under 9the terms of the GNU General Public License as published by the Free 10Software Foundation; either version 2, or (at your option) any later 11version. 12 13GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14WARRANTY; without even the implied warranty of MERCHANTABILITY or 15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16for more details. 17 18You should have received a copy of the GNU General Public License 19along with GCC; see the file COPYING. If not, write to 20the Free Software Foundation, 51 Franklin Street, Fifth Floor, 21Boston, MA 02110-1301, USA. */ 22 23#include "config.h" 24#include "system.h" 25#include "coretypes.h" 26#include "tm.h" 27#include "rtl.h" 28#include "regs.h" 29#include "hard-reg-set.h" 30#include "output.h" 31#include "tree.h" 32#include "cp/cp-tree.h" /* this is why we're a separate module */ 33#include "flags.h" 34#include "tm_p.h" 35#include "toplev.h" 36#include "hashtab.h" 37 38bool 39i386_pe_type_dllimport_p (tree decl) 40{ 41 gcc_assert (TREE_CODE (decl) == VAR_DECL 42 || TREE_CODE (decl) == FUNCTION_DECL); 43 44 if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL) 45 return false; 46 47 /* We ignore the dllimport attribute for inline member functions. 48 This differs from MSVC behavior which treats it like GNUC 49 'extern inline' extension. Also ignore for template 50 instantiations with linkonce semantics and artificial methods. */ 51 if (TREE_CODE (decl) == FUNCTION_DECL 52 && (DECL_DECLARED_INLINE_P (decl) 53 || DECL_TEMPLATE_INSTANTIATION (decl) 54 || DECL_ARTIFICIAL (decl))) 55 return false; 56 57 /* Since we can't treat a pointer to a dllimport'd symbol as a 58 constant address, we turn off the attribute on C++ virtual 59 methods to allow creation of vtables using thunks. */ 60 else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE 61 && DECL_VIRTUAL_P (decl)) 62 { 63 /* Even though we ignore the attribute from the start, warn if we later see 64 an out-of class definition, as we do for other member functions in 65 tree.c:merge_dllimport_decl_attributes. If this is the key method, the 66 definition may affect the import-export status of vtables, depending 67 on how we handle MULTIPLE_SYMBOL_SPACES in cp/decl2.c. */ 68 if (DECL_INITIAL (decl)) 69 { 70 warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: " 71 "previous dllimport ignored", decl); 72#ifdef PE_DLL_DEBUG 73 if (decl == CLASSTYPE_KEY_METHOD (DECL_CONTEXT (decl))) 74 warning (OPT_Wattributes, "key method %q+D of dllimport'd class defined" 75 decl); 76#endif 77 } 78 return false; 79 } 80 81 /* Don't mark defined functions as dllimport. This code will only be 82 reached if we see a non-inline function defined out-of-class. */ 83 else if (TREE_CODE (decl) == FUNCTION_DECL 84 && (DECL_INITIAL (decl))) 85 return false; 86 87 /* Don't allow definitions of static data members in dllimport class, 88 If vtable data is marked as DECL_EXTERNAL, import it; otherwise just 89 ignore the class attribute. */ 90 else if (TREE_CODE (decl) == VAR_DECL 91 && TREE_STATIC (decl) && TREE_PUBLIC (decl) 92 && !DECL_EXTERNAL (decl)) 93 { 94 if (!DECL_VIRTUAL_P (decl)) 95 error ("definition of static data member %q+D of " 96 "dllimport'd class", decl); 97 return false; 98 } 99 100 return true; 101} 102 103 104bool 105i386_pe_type_dllexport_p (tree decl) 106{ 107 gcc_assert (TREE_CODE (decl) == VAR_DECL 108 || TREE_CODE (decl) == FUNCTION_DECL); 109 /* Avoid exporting compiler-generated default dtors and copy ctors. 110 The only artificial methods that need to be exported are virtual 111 and non-virtual thunks. */ 112 if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE 113 && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl)) 114 return false; 115 return true; 116} 117 118static inline void maybe_add_dllimport (tree decl) 119{ 120 if (i386_pe_type_dllimport_p (decl)) 121 DECL_DLLIMPORT_P (decl) = 1; 122} 123 124void 125i386_pe_adjust_class_at_definition (tree t) 126{ 127 tree member; 128 129 gcc_assert (CLASS_TYPE_P (t)); 130 131 /* We only look at dllimport. The only thing that dllexport does is 132 add stuff to a '.drectiv' section at end-of-file, so no need to do 133 anything for dllexport'd classes until we generate RTL. */ 134 if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE) 135 return; 136 137 /* We don't actually add the attribute to the decl, just set the flag 138 that signals that the address of this symbol is not a compile-time 139 constant. Any subsequent out-of-class declaration of members wil 140 cause the DECL_DLLIMPORT_P flag to be unset. 141 (See tree.c: merge_dllimport_decl_attributes). 142 That is just right since out-of class declarations can only be a 143 definition. We recheck the class members at RTL generation to 144 emit warnings if this has happened. Definition of static data member 145 of dllimport'd class always causes an error (as per MS compiler). 146 */ 147 148 /* Check static VAR_DECL's. */ 149 for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) 150 if (TREE_CODE (member) == VAR_DECL) 151 maybe_add_dllimport (member); 152 153 /* Check FUNCTION_DECL's. */ 154 for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member)) 155 if (TREE_CODE (member) == FUNCTION_DECL) 156 maybe_add_dllimport (member); 157 158 /* Check vtables */ 159 for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member)) 160 if (TREE_CODE (member) == VAR_DECL) 161 maybe_add_dllimport (member); 162 163/* We leave typeinfo tables alone. We can't mark TI objects as 164 dllimport, since the address of a secondary VTT may be needed 165 for static initialization of a primary VTT. VTT's of 166 dllimport'd classes should always be link-once COMDAT. */ 167} 168