1130636Srwatson/* Target support for C++ classes on Windows.
2101242Srwatson   Contributed by Danny Smith (dannysmith@users.sourceforge.net)
3107603Sru   Copyright (C) 2005
4101242Srwatson   Free Software Foundation, Inc.
5101242Srwatson
6101242SrwatsonThis file is part of GCC.
7101242Srwatson
8101242SrwatsonGCC is free software; you can redistribute it and/or modify it under
9107603Sruthe terms of the GNU General Public License as published by the Free
10101242SrwatsonSoftware Foundation; either version 2, or (at your option) any later
11101242Srwatsonversion.
12101242Srwatson
13101242SrwatsonGCC is distributed in the hope that it will be useful, but WITHOUT ANY
14101242SrwatsonWARRANTY; without even the implied warranty of MERCHANTABILITY or
15101242SrwatsonFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16101242Srwatsonfor more details.
17101242Srwatson
18107603SruYou should have received a copy of the GNU General Public License
19101242Srwatsonalong with GCC; see the file COPYING.  If not, write to
20101242Srwatsonthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
21101242SrwatsonBoston, MA 02110-1301, USA.  */
22101242Srwatson
23101242Srwatson#include "config.h"
24101242Srwatson#include "system.h"
25101242Srwatson#include "coretypes.h"
26101242Srwatson#include "tm.h"
27101242Srwatson#include "rtl.h"
28101242Srwatson#include "regs.h"
29101242Srwatson#include "hard-reg-set.h"
30107603Sru#include "output.h"
31101242Srwatson#include "tree.h"
32107603Sru#include "cp/cp-tree.h" /* this is why we're a separate module */
33101242Srwatson#include "flags.h"
34101242Srwatson#include "tm_p.h"
35107744Sru#include "toplev.h"
36101242Srwatson#include "hashtab.h"
37101242Srwatson
38130636Srwatsonbool
39101242Srwatsoni386_pe_type_dllimport_p (tree decl)
40131365Sru{
41131365Sru   gcc_assert (TREE_CODE (decl) == VAR_DECL
42101242Srwatson               || TREE_CODE (decl) == FUNCTION_DECL);
43101242Srwatson
44107603Sru   if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
45107603Sru     return false;
46101242Srwatson
47101242Srwatson   /* We ignore the dllimport attribute for inline member functions.
48109263Schris      This differs from MSVC behavior which treats it like GNUC
49109263Schris      'extern inline' extension.  Also ignore for template
50109263Schris      instantiations with linkonce semantics and artificial methods.  */
51130636Srwatson    if (TREE_CODE (decl) ==  FUNCTION_DECL
52130636Srwatson        && (DECL_DECLARED_INLINE_P (decl)
53109263Schris	    || DECL_TEMPLATE_INSTANTIATION (decl)
54109263Schris	    || DECL_ARTIFICIAL (decl)))
55122810Srwatson      return false;
56122810Srwatson
57109263Schris   /* Since we can't treat a pointer to a dllimport'd symbol as a
58109263Schris       constant address, we turn off the attribute on C++ virtual
59109263Schris       methods to allow creation of vtables using thunks.  */
60101242Srwatson    else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
61101242Srwatson	     && DECL_VIRTUAL_P (decl))
62101242Srwatson      {
63122810Srwatson	/* Even though we ignore the attribute from the start, warn if we later see
64122810Srwatson	   an out-of class definition, as we do for other member functions in
65130636Srwatson	   tree.c:merge_dllimport_decl_attributes.  If this is the key method, the
66131365Sru	   definition may affect the import-export status of vtables, depending
67130636Srwatson           on how we handle MULTIPLE_SYMBOL_SPACES in cp/decl2.c.   */
68130636Srwatson	if (DECL_INITIAL (decl))
69130636Srwatson	  {
70122810Srwatson	    warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
71122810Srwatson		    "previous dllimport ignored", decl);
72101242Srwatson#ifdef PE_DLL_DEBUG
73122810Srwatson	    if (decl == CLASSTYPE_KEY_METHOD (DECL_CONTEXT (decl)))
74122810Srwatson	      warning (OPT_Wattributes, "key method %q+D of dllimport'd class defined"
75122810Srwatson		       decl);
76122810Srwatson#endif
77122810Srwatson	  }
78122810Srwatson	return false;
79122810Srwatson      }
80122810Srwatson
81122810Srwatson      /* Don't mark defined functions as dllimport.  This code will only be
82122810Srwatson         reached if we see a non-inline function defined out-of-class.  */
83122810Srwatson    else if (TREE_CODE (decl) ==  FUNCTION_DECL
84122810Srwatson	     && (DECL_INITIAL (decl)))
85109263Schris      return false;
86101242Srwatson
87122810Srwatson    /*  Don't allow definitions of static data members in dllimport class,
88122810Srwatson        If vtable data is marked as DECL_EXTERNAL, import it; otherwise just
89101242Srwatson        ignore the class attribute.  */
90122810Srwatson    else if (TREE_CODE (decl) == VAR_DECL
91131365Sru	     && TREE_STATIC (decl) && TREE_PUBLIC (decl)
92122810Srwatson	     && !DECL_EXTERNAL (decl))
93122810Srwatson      {
94122810Srwatson	if (!DECL_VIRTUAL_P (decl))
95122810Srwatson	     error ("definition of static data member %q+D of "
96122810Srwatson		    "dllimport'd class", decl);
97122810Srwatson	return false;
98122810Srwatson      }
99122810Srwatson
100101242Srwatson    return true;
101101242Srwatson}
102101242Srwatson
103101242Srwatson
104109263Schrisbool
105101242Srwatsoni386_pe_type_dllexport_p (tree decl)
106101242Srwatson{
107101242Srwatson   gcc_assert (TREE_CODE (decl) == VAR_DECL
108122810Srwatson               || TREE_CODE (decl) == FUNCTION_DECL);
109122810Srwatson   /* Avoid exporting compiler-generated default dtors and copy ctors.
110122810Srwatson      The only artificial methods that need to be exported are virtual
111101242Srwatson      and non-virtual thunks.  */
112101242Srwatson   if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
113109263Schris       && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl))
114101242Srwatson     return false;
115101242Srwatson   return true;
116101242Srwatson}
117101242Srwatson
118101242Srwatsonstatic inline void maybe_add_dllimport (tree decl)
119101242Srwatson{
120109263Schris  if (i386_pe_type_dllimport_p (decl))
121101242Srwatson    DECL_DLLIMPORT_P (decl) = 1;
122101242Srwatson}
123101242Srwatson
124101242Srwatsonvoid
125101242Srwatsoni386_pe_adjust_class_at_definition (tree t)
126101242Srwatson{
127109263Schris  tree member;
128101242Srwatson
129101242Srwatson  gcc_assert (CLASS_TYPE_P (t));
130101242Srwatson
131101242Srwatson /* We only look at dllimport.  The only thing that dllexport does is
132101242Srwatson    add stuff to a '.drectiv' section at end-of-file, so no need to do
133109263Schris    anything for dllexport'd classes until we generate RTL. */
134107603Sru  if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE)
135120010Sru    return;
136196123Srwatson
137109273Schris  /* We don't actually add the attribute to the decl, just set the flag
138109263Schris     that signals that the address of this symbol is not a compile-time
139101242Srwatson     constant.   Any subsequent out-of-class declaration of members wil
140101242Srwatson     cause the DECL_DLLIMPORT_P flag to be unset.
141101242Srwatson     (See  tree.c: merge_dllimport_decl_attributes).
142101242Srwatson     That is just right since out-of class declarations can only be a
143101242Srwatson     definition.  We recheck the class members  at RTL generation to
144101242Srwatson     emit warnings if this has happened.  Definition of static data member
145101242Srwatson     of dllimport'd class always causes an error (as per MS compiler).
146101242Srwatson     */
147119321Srwatson
148119321Srwatson  /* Check static VAR_DECL's.  */
149119321Srwatson  for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
150119321Srwatson    if (TREE_CODE (member) == VAR_DECL)
151119321Srwatson      maybe_add_dllimport (member);
152119321Srwatson
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