1169689Skan/* Target support for C++ classes on Windows. 2169689Skan Contributed by Danny Smith (dannysmith@users.sourceforge.net) 3169689Skan Copyright (C) 2005 4169689Skan Free Software Foundation, Inc. 5169689Skan 6169689SkanThis file is part of GCC. 7169689Skan 8169689SkanGCC is free software; you can redistribute it and/or modify it under 9169689Skanthe terms of the GNU General Public License as published by the Free 10169689SkanSoftware Foundation; either version 2, or (at your option) any later 11169689Skanversion. 12169689Skan 13169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 14169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 15169689SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16169689Skanfor more details. 17169689Skan 18169689SkanYou should have received a copy of the GNU General Public License 19169689Skanalong with GCC; see the file COPYING. If not, write to 20169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 21169689SkanBoston, MA 02110-1301, USA. */ 22169689Skan 23169689Skan#include "config.h" 24169689Skan#include "system.h" 25169689Skan#include "coretypes.h" 26169689Skan#include "tm.h" 27169689Skan#include "rtl.h" 28169689Skan#include "regs.h" 29169689Skan#include "hard-reg-set.h" 30169689Skan#include "output.h" 31169689Skan#include "tree.h" 32169689Skan#include "cp/cp-tree.h" /* this is why we're a separate module */ 33169689Skan#include "flags.h" 34169689Skan#include "tm_p.h" 35169689Skan#include "toplev.h" 36169689Skan#include "hashtab.h" 37169689Skan 38169689Skanbool 39169689Skani386_pe_type_dllimport_p (tree decl) 40169689Skan{ 41169689Skan gcc_assert (TREE_CODE (decl) == VAR_DECL 42169689Skan || TREE_CODE (decl) == FUNCTION_DECL); 43169689Skan 44169689Skan if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL) 45169689Skan return false; 46169689Skan 47169689Skan /* We ignore the dllimport attribute for inline member functions. 48169689Skan This differs from MSVC behavior which treats it like GNUC 49169689Skan 'extern inline' extension. Also ignore for template 50169689Skan instantiations with linkonce semantics and artificial methods. */ 51169689Skan if (TREE_CODE (decl) == FUNCTION_DECL 52169689Skan && (DECL_DECLARED_INLINE_P (decl) 53169689Skan || DECL_TEMPLATE_INSTANTIATION (decl) 54169689Skan || DECL_ARTIFICIAL (decl))) 55169689Skan return false; 56169689Skan 57169689Skan /* Since we can't treat a pointer to a dllimport'd symbol as a 58169689Skan constant address, we turn off the attribute on C++ virtual 59169689Skan methods to allow creation of vtables using thunks. */ 60169689Skan else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE 61169689Skan && DECL_VIRTUAL_P (decl)) 62169689Skan { 63169689Skan /* Even though we ignore the attribute from the start, warn if we later see 64169689Skan an out-of class definition, as we do for other member functions in 65169689Skan tree.c:merge_dllimport_decl_attributes. If this is the key method, the 66169689Skan definition may affect the import-export status of vtables, depending 67169689Skan on how we handle MULTIPLE_SYMBOL_SPACES in cp/decl2.c. */ 68169689Skan if (DECL_INITIAL (decl)) 69169689Skan { 70169689Skan warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: " 71169689Skan "previous dllimport ignored", decl); 72169689Skan#ifdef PE_DLL_DEBUG 73169689Skan if (decl == CLASSTYPE_KEY_METHOD (DECL_CONTEXT (decl))) 74169689Skan warning (OPT_Wattributes, "key method %q+D of dllimport'd class defined" 75169689Skan decl); 76169689Skan#endif 77169689Skan } 78169689Skan return false; 79169689Skan } 80169689Skan 81169689Skan /* Don't mark defined functions as dllimport. This code will only be 82169689Skan reached if we see a non-inline function defined out-of-class. */ 83169689Skan else if (TREE_CODE (decl) == FUNCTION_DECL 84169689Skan && (DECL_INITIAL (decl))) 85169689Skan return false; 86169689Skan 87169689Skan /* Don't allow definitions of static data members in dllimport class, 88169689Skan If vtable data is marked as DECL_EXTERNAL, import it; otherwise just 89169689Skan ignore the class attribute. */ 90169689Skan else if (TREE_CODE (decl) == VAR_DECL 91169689Skan && TREE_STATIC (decl) && TREE_PUBLIC (decl) 92169689Skan && !DECL_EXTERNAL (decl)) 93169689Skan { 94169689Skan if (!DECL_VIRTUAL_P (decl)) 95169689Skan error ("definition of static data member %q+D of " 96169689Skan "dllimport'd class", decl); 97169689Skan return false; 98169689Skan } 99169689Skan 100169689Skan return true; 101169689Skan} 102169689Skan 103169689Skan 104169689Skanbool 105169689Skani386_pe_type_dllexport_p (tree decl) 106169689Skan{ 107169689Skan gcc_assert (TREE_CODE (decl) == VAR_DECL 108169689Skan || TREE_CODE (decl) == FUNCTION_DECL); 109169689Skan /* Avoid exporting compiler-generated default dtors and copy ctors. 110169689Skan The only artificial methods that need to be exported are virtual 111169689Skan and non-virtual thunks. */ 112169689Skan if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE 113169689Skan && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl)) 114169689Skan return false; 115169689Skan return true; 116169689Skan} 117169689Skan 118169689Skanstatic inline void maybe_add_dllimport (tree decl) 119169689Skan{ 120169689Skan if (i386_pe_type_dllimport_p (decl)) 121169689Skan DECL_DLLIMPORT_P (decl) = 1; 122169689Skan} 123169689Skan 124169689Skanvoid 125169689Skani386_pe_adjust_class_at_definition (tree t) 126169689Skan{ 127169689Skan tree member; 128169689Skan 129169689Skan gcc_assert (CLASS_TYPE_P (t)); 130169689Skan 131169689Skan /* We only look at dllimport. The only thing that dllexport does is 132169689Skan add stuff to a '.drectiv' section at end-of-file, so no need to do 133169689Skan anything for dllexport'd classes until we generate RTL. */ 134169689Skan if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE) 135169689Skan return; 136169689Skan 137169689Skan /* We don't actually add the attribute to the decl, just set the flag 138169689Skan that signals that the address of this symbol is not a compile-time 139169689Skan constant. Any subsequent out-of-class declaration of members wil 140169689Skan cause the DECL_DLLIMPORT_P flag to be unset. 141169689Skan (See tree.c: merge_dllimport_decl_attributes). 142169689Skan That is just right since out-of class declarations can only be a 143169689Skan definition. We recheck the class members at RTL generation to 144169689Skan emit warnings if this has happened. Definition of static data member 145169689Skan of dllimport'd class always causes an error (as per MS compiler). 146169689Skan */ 147169689Skan 148169689Skan /* Check static VAR_DECL's. */ 149169689Skan for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member)) 150169689Skan if (TREE_CODE (member) == VAR_DECL) 151169689Skan maybe_add_dllimport (member); 152169689Skan 153169689Skan /* Check FUNCTION_DECL's. */ 154169689Skan for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member)) 155169689Skan if (TREE_CODE (member) == FUNCTION_DECL) 156169689Skan maybe_add_dllimport (member); 157169689Skan 158169689Skan /* Check vtables */ 159169689Skan for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member)) 160169689Skan if (TREE_CODE (member) == VAR_DECL) 161169689Skan maybe_add_dllimport (member); 162169689Skan 163169689Skan/* We leave typeinfo tables alone. We can't mark TI objects as 164169689Skan dllimport, since the address of a secondary VTT may be needed 165169689Skan for static initialization of a primary VTT. VTT's of 166169689Skan dllimport'd classes should always be link-once COMDAT. */ 167169689Skan} 168