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