118334Speter/* Handle the hair of processing (but not expanding) inline functions.
218334Speter   Also manage function and variable name overloading.
3169689Skan   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4169689Skan   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
518334Speter   Contributed by Michael Tiemann (tiemann@cygnus.com)
618334Speter
7132718SkanThis file is part of GCC.
8169689Skan
9132718SkanGCC is free software; you can redistribute it and/or modify
1018334Speterit under the terms of the GNU General Public License as published by
1118334Speterthe Free Software Foundation; either version 2, or (at your option)
1218334Speterany later version.
1318334Speter
14132718SkanGCC is distributed in the hope that it will be useful,
1518334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1618334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1718334SpeterGNU General Public License for more details.
1818334Speter
1918334SpeterYou should have received a copy of the GNU General Public License
20132718Skanalong with GCC; see the file COPYING.  If not, write to
21169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor,
22169689SkanBoston, MA 02110-1301, USA.  */
2318334Speter
2418334Speter
2518334Speter/* Handle method declarations.  */
2618334Speter#include "config.h"
2750397Sobrien#include "system.h"
28132718Skan#include "coretypes.h"
29132718Skan#include "tm.h"
3018334Speter#include "tree.h"
3118334Speter#include "cp-tree.h"
3218334Speter#include "rtl.h"
3318334Speter#include "expr.h"
3418334Speter#include "output.h"
3518334Speter#include "flags.h"
3650397Sobrien#include "toplev.h"
3790075Sobrien#include "tm_p.h"
38117395Skan#include "target.h"
39169689Skan#include "tree-pass.h"
40169689Skan#include "diagnostic.h"
4118334Speter
4290075Sobrien/* Various flags to control the mangling process.  */
4318334Speter
4490075Sobrienenum mangling_flags
4590075Sobrien{
4690075Sobrien  /* No flags.  */
4790075Sobrien  mf_none = 0,
4890075Sobrien  /* The thing we are presently mangling is part of a template type,
4990075Sobrien     rather than a fully instantiated type.  Therefore, we may see
5090075Sobrien     complex expressions where we would normally expect to see a
5190075Sobrien     simple integer constant.  */
5290075Sobrien  mf_maybe_uninstantiated = 1,
5390075Sobrien  /* When mangling a numeric value, use the form `_XX_' (instead of
5490075Sobrien     just `XX') if the value has more than one digit.  */
55132718Skan  mf_use_underscores_around_value = 2
5690075Sobrien};
5750397Sobrien
5890075Sobrientypedef enum mangling_flags mangling_flags;
5990075Sobrien
60132718Skanstatic tree thunk_adjust (tree, bool, HOST_WIDE_INT, tree);
61132718Skanstatic void do_build_assign_ref (tree);
62132718Skanstatic void do_build_copy_constructor (tree);
63132718Skanstatic tree synthesize_exception_spec (tree, tree (*) (tree, void *), void *);
64132718Skanstatic tree locate_dtor (tree, void *);
65132718Skanstatic tree locate_ctor (tree, void *);
66132718Skanstatic tree locate_copy (tree, void *);
67132718Skanstatic tree make_alias_for_thunk (tree);
6818334Speter
6990075Sobrien/* Called once to initialize method.c.  */
7050397Sobrien
7118334Spetervoid
72132718Skaninit_method (void)
7318334Speter{
7490075Sobrien  init_mangle ();
7518334Speter}
7618334Speter
77132718Skan/* Return a this or result adjusting thunk to FUNCTION.  THIS_ADJUSTING
78132718Skan   indicates whether it is a this or result adjusting thunk.
79132718Skan   FIXED_OFFSET and VIRTUAL_OFFSET indicate how to do the adjustment
80132718Skan   (see thunk_adjust).  VIRTUAL_OFFSET can be NULL, but FIXED_OFFSET
81132718Skan   never is.  VIRTUAL_OFFSET is the /index/ into the vtable for this
82132718Skan   adjusting thunks, we scale it to a byte offset. For covariant
83132718Skan   thunks VIRTUAL_OFFSET is the virtual binfo.  You must post process
84132718Skan   the returned thunk with finish_thunk.  */
8518334Speter
8618334Spetertree
87132718Skanmake_thunk (tree function, bool this_adjusting,
88132718Skan	    tree fixed_offset, tree virtual_offset)
8918334Speter{
90132718Skan  HOST_WIDE_INT d;
9118334Speter  tree thunk;
92169689Skan
93169689Skan  gcc_assert (TREE_CODE (function) == FUNCTION_DECL);
94132718Skan  /* We can have this thunks to covariant thunks, but not vice versa.  */
95169689Skan  gcc_assert (!DECL_THIS_THUNK_P (function));
96169689Skan  gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting);
97169689Skan
98132718Skan  /* Scale the VIRTUAL_OFFSET to be in terms of bytes.  */
99132718Skan  if (this_adjusting && virtual_offset)
100169689Skan    virtual_offset
10190075Sobrien      = size_binop (MULT_EXPR,
102169689Skan		    virtual_offset,
103169689Skan		    convert (ssizetype,
104169689Skan			     TYPE_SIZE_UNIT (vtable_entry_type)));
105169689Skan
106132718Skan  d = tree_low_cst (fixed_offset, 0);
107169689Skan
108132718Skan  /* See if we already have the thunk in question.  For this_adjusting
109132718Skan     thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it
110132718Skan     will be a BINFO.  */
111117395Skan  for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
112132718Skan    if (DECL_THIS_THUNK_P (thunk) == this_adjusting
113132718Skan	&& THUNK_FIXED_OFFSET (thunk) == d
114132718Skan	&& !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk)
115132718Skan	&& (!virtual_offset
116132718Skan	    || (this_adjusting
117132718Skan		? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk),
118132718Skan				      virtual_offset)
119132718Skan		: THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset)))
120117395Skan      return thunk;
121169689Skan
122117395Skan  /* All thunks must be created before FUNCTION is actually emitted;
123117395Skan     the ABI requires that all thunks be emitted together with the
124117395Skan     function to which they transfer control.  */
125169689Skan  gcc_assert (!TREE_ASM_WRITTEN (function));
126132718Skan  /* Likewise, we can only be adding thunks to a function declared in
127132718Skan     the class currently being laid out.  */
128169689Skan  gcc_assert (TYPE_SIZE (DECL_CONTEXT (function))
129169689Skan	      && TYPE_BEING_DEFINED (DECL_CONTEXT (function)));
130117395Skan
131132718Skan  thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
132117395Skan  DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
133132718Skan  cxx_dup_lang_specific_decl (thunk);
134132718Skan  DECL_THUNKS (thunk) = NULL_TREE;
135169689Skan
136117395Skan  DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
137117395Skan  TREE_READONLY (thunk) = TREE_READONLY (function);
138117395Skan  TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
139117395Skan  TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
140132718Skan  SET_DECL_THUNK_P (thunk, this_adjusting);
141132718Skan  THUNK_TARGET (thunk) = function;
142132718Skan  THUNK_FIXED_OFFSET (thunk) = d;
143132718Skan  THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
144132718Skan  THUNK_ALIAS (thunk) = NULL_TREE;
145169689Skan
146117395Skan  /* The thunk itself is not a constructor or destructor, even if
147117395Skan     the thing it is thunking to is.  */
148117395Skan  DECL_INTERFACE_KNOWN (thunk) = 1;
149117395Skan  DECL_NOT_REALLY_EXTERN (thunk) = 1;
150117395Skan  DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
151117395Skan  DECL_DESTRUCTOR_P (thunk) = 0;
152117395Skan  DECL_CONSTRUCTOR_P (thunk) = 0;
153117395Skan  DECL_EXTERNAL (thunk) = 1;
154117395Skan  DECL_ARTIFICIAL (thunk) = 1;
155117395Skan  /* Even if this thunk is a member of a local class, we don't
156117395Skan     need a static chain.  */
157117395Skan  DECL_NO_STATIC_CHAIN (thunk) = 1;
158117395Skan  /* The THUNK is not a pending inline, even if the FUNCTION is.  */
159117395Skan  DECL_PENDING_INLINE_P (thunk) = 0;
160117395Skan  DECL_INLINE (thunk) = 0;
161117395Skan  DECL_DECLARED_INLINE_P (thunk) = 0;
162117395Skan  /* Nor has it been deferred.  */
163117395Skan  DECL_DEFERRED_FN (thunk) = 0;
164169689Skan  /* Nor is it a template instantiation.  */
165169689Skan  DECL_USE_TEMPLATE (thunk) = 0;
166169689Skan  DECL_TEMPLATE_INFO (thunk) = NULL;
167169689Skan
168117395Skan  /* Add it to the list of thunks associated with FUNCTION.  */
169117395Skan  TREE_CHAIN (thunk) = DECL_THUNKS (function);
170117395Skan  DECL_THUNKS (function) = thunk;
171117395Skan
17218334Speter  return thunk;
17318334Speter}
17418334Speter
175132718Skan/* Finish THUNK, a thunk decl.  */
17650397Sobrien
17718334Spetervoid
178132718Skanfinish_thunk (tree thunk)
17918334Speter{
180132718Skan  tree function, name;
181132718Skan  tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk));
182132718Skan  tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk);
18318334Speter
184169689Skan  gcc_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk));
185132718Skan  if (virtual_offset && DECL_RESULT_THUNK_P (thunk))
186132718Skan    virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
187132718Skan  function = THUNK_TARGET (thunk);
188132718Skan  name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
189132718Skan		       fixed_offset, virtual_offset);
190132718Skan
191132718Skan  /* We can end up with declarations of (logically) different
192132718Skan     covariant thunks, that do identical adjustments.  The two thunks
193132718Skan     will be adjusting between within different hierarchies, which
194132718Skan     happen to have the same layout.  We must nullify one of them to
195132718Skan     refer to the other.  */
196132718Skan  if (DECL_RESULT_THUNK_P (thunk))
197132718Skan    {
198132718Skan      tree cov_probe;
199132718Skan
200132718Skan      for (cov_probe = DECL_THUNKS (function);
201132718Skan	   cov_probe; cov_probe = TREE_CHAIN (cov_probe))
202132718Skan	if (DECL_NAME (cov_probe) == name)
203132718Skan	  {
204169689Skan	    gcc_assert (!DECL_THUNKS (thunk));
205132718Skan	    THUNK_ALIAS (thunk) = (THUNK_ALIAS (cov_probe)
206132718Skan				   ? THUNK_ALIAS (cov_probe) : cov_probe);
207132718Skan	    break;
208132718Skan	  }
209132718Skan    }
210169689Skan
211132718Skan  DECL_NAME (thunk) = name;
212132718Skan  SET_DECL_ASSEMBLER_NAME (thunk, name);
213132718Skan}
214132718Skan
215132718Skan/* Adjust PTR by the constant FIXED_OFFSET, and by the vtable
216132718Skan   offset indicated by VIRTUAL_OFFSET, if that is
217132718Skan   non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and
218132718Skan   zero for a result adjusting thunk.  */
219132718Skan
220132718Skanstatic tree
221132718Skanthunk_adjust (tree ptr, bool this_adjusting,
222132718Skan	      HOST_WIDE_INT fixed_offset, tree virtual_offset)
223132718Skan{
224132718Skan  if (this_adjusting)
225132718Skan    /* Adjust the pointer by the constant.  */
226169689Skan    ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr,
227169689Skan		       ssize_int (fixed_offset));
228132718Skan
229132718Skan  /* If there's a virtual offset, look up that value in the vtable and
230132718Skan     adjust the pointer again.  */
231132718Skan  if (virtual_offset)
232132718Skan    {
233132718Skan      tree vtable;
234132718Skan
235132718Skan      ptr = save_expr (ptr);
236132718Skan      /* The vptr is always at offset zero in the object.  */
237132718Skan      vtable = build1 (NOP_EXPR,
238169689Skan		       build_pointer_type (build_pointer_type
239132718Skan					   (vtable_entry_type)),
240132718Skan		       ptr);
241132718Skan      /* Form the vtable address.  */
242132718Skan      vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
243132718Skan      /* Find the entry with the vcall offset.  */
244169689Skan      vtable = build2 (PLUS_EXPR, TREE_TYPE (vtable), vtable, virtual_offset);
245132718Skan      /* Get the offset itself.  */
246132718Skan      vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
247132718Skan      /* Adjust the `this' pointer.  */
248169689Skan      ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, vtable);
249132718Skan    }
250169689Skan
251132718Skan  if (!this_adjusting)
252132718Skan    /* Adjust the pointer by the constant.  */
253169689Skan    ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr,
254169689Skan		       ssize_int (fixed_offset));
255132718Skan
256132718Skan  return ptr;
257132718Skan}
258132718Skan
259132718Skanstatic GTY (()) int thunk_labelno;
260132718Skan
261132718Skan/* Create a static alias to function.  */
262132718Skan
263169689Skantree
264169689Skanmake_alias_for (tree function, tree newid)
265132718Skan{
266169689Skan  tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function));
267132718Skan  DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
268132718Skan  cxx_dup_lang_specific_decl (alias);
269132718Skan  DECL_CONTEXT (alias) = NULL;
270132718Skan  TREE_READONLY (alias) = TREE_READONLY (function);
271132718Skan  TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
272132718Skan  TREE_PUBLIC (alias) = 0;
273132718Skan  DECL_INTERFACE_KNOWN (alias) = 1;
274132718Skan  DECL_NOT_REALLY_EXTERN (alias) = 1;
275132718Skan  DECL_THIS_STATIC (alias) = 1;
276132718Skan  DECL_SAVED_FUNCTION_DATA (alias) = NULL;
277132718Skan  DECL_DESTRUCTOR_P (alias) = 0;
278132718Skan  DECL_CONSTRUCTOR_P (alias) = 0;
279132718Skan  DECL_CLONED_FUNCTION (alias) = NULL_TREE;
280132718Skan  DECL_EXTERNAL (alias) = 0;
281132718Skan  DECL_ARTIFICIAL (alias) = 1;
282132718Skan  DECL_NO_STATIC_CHAIN (alias) = 1;
283132718Skan  DECL_PENDING_INLINE_P (alias) = 0;
284132718Skan  DECL_INLINE (alias) = 0;
285132718Skan  DECL_DECLARED_INLINE_P (alias) = 0;
286132718Skan  DECL_DEFERRED_FN (alias) = 0;
287132718Skan  DECL_USE_TEMPLATE (alias) = 0;
288132718Skan  DECL_TEMPLATE_INSTANTIATED (alias) = 0;
289132718Skan  DECL_TEMPLATE_INFO (alias) = NULL;
290132718Skan  DECL_INITIAL (alias) = error_mark_node;
291132718Skan  TREE_ADDRESSABLE (alias) = 1;
292132718Skan  TREE_USED (alias) = 1;
293132718Skan  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
294132718Skan  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
295169689Skan  return alias;
296169689Skan}
297169689Skan
298169689Skanstatic tree
299169689Skanmake_alias_for_thunk (tree function)
300169689Skan{
301169689Skan  tree alias;
302169689Skan  char buf[256];
303169689Skan
304169689Skan  ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
305169689Skan  thunk_labelno++;
306169689Skan
307169689Skan  alias = make_alias_for (function, get_identifier (buf));
308169689Skan
309132718Skan  if (!flag_syntax_only)
310132718Skan    assemble_alias (alias, DECL_ASSEMBLER_NAME (function));
311169689Skan
312132718Skan  return alias;
313132718Skan}
314132718Skan
315132718Skan/* Emit the definition of a C++ multiple inheritance or covariant
316132718Skan   return vtable thunk.  If EMIT_P is nonzero, the thunk is emitted
317132718Skan   immediately.  */
318132718Skan
319132718Skanvoid
320132718Skanuse_thunk (tree thunk_fndecl, bool emit_p)
321132718Skan{
322169689Skan  tree a, t, function, alias;
323132718Skan  tree virtual_offset;
324132718Skan  HOST_WIDE_INT fixed_offset, virtual_value;
325132718Skan  bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl);
326132718Skan
327132718Skan  /* We should have called finish_thunk to give it a name.  */
328169689Skan  gcc_assert (DECL_NAME (thunk_fndecl));
329132718Skan
330132718Skan  /* We should never be using an alias, always refer to the
331132718Skan     aliased thunk.  */
332169689Skan  gcc_assert (!THUNK_ALIAS (thunk_fndecl));
333132718Skan
33418334Speter  if (TREE_ASM_WRITTEN (thunk_fndecl))
33518334Speter    return;
336169689Skan
337132718Skan  function = THUNK_TARGET (thunk_fndecl);
338132718Skan  if (DECL_RESULT (thunk_fndecl))
33990075Sobrien    /* We already turned this thunk into an ordinary function.
34090075Sobrien       There's no need to process this thunk again.  */
34190075Sobrien    return;
34218334Speter
343146895Skan  if (DECL_THUNK_P (function))
344146895Skan    /* The target is itself a thunk, process it now.  */
345146895Skan    use_thunk (function, emit_p);
346169689Skan
34790075Sobrien  /* Thunks are always addressable; they only appear in vtables.  */
34890075Sobrien  TREE_ADDRESSABLE (thunk_fndecl) = 1;
34918334Speter
35090075Sobrien  /* Figure out what function is being thunked to.  It's referenced in
35190075Sobrien     this translation unit.  */
35250397Sobrien  TREE_ADDRESSABLE (function) = 1;
35350397Sobrien  mark_used (function);
35490075Sobrien  if (!emit_p)
35590075Sobrien    return;
35618334Speter
357169689Skan  if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function))
358169689Skan   alias = make_alias_for_thunk (function);
359169689Skan  else
360169689Skan   alias = function;
36118334Speter
362132718Skan  fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl);
363132718Skan  virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl);
364132718Skan
365132718Skan  if (virtual_offset)
366117395Skan    {
367132718Skan      if (!this_adjusting)
368132718Skan	virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
369132718Skan      virtual_value = tree_low_cst (virtual_offset, /*pos=*/0);
370169689Skan      gcc_assert (virtual_value);
371117395Skan    }
372117395Skan  else
373132718Skan    virtual_value = 0;
374169689Skan
37590075Sobrien  /* And, if we need to emit the thunk, it's used.  */
37690075Sobrien  mark_used (thunk_fndecl);
37790075Sobrien  /* This thunk is actually defined.  */
37890075Sobrien  DECL_EXTERNAL (thunk_fndecl) = 0;
37990075Sobrien  /* The linkage of the function may have changed.  FIXME in linkage
38090075Sobrien     rewrite.  */
38190075Sobrien  TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
382132718Skan  DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
383169689Skan  DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
384169689Skan    = DECL_VISIBILITY_SPECIFIED (function);
385169689Skan  if (DECL_ONE_ONLY (function))
386169689Skan    make_decl_one_only (thunk_fndecl);
38718334Speter
38890075Sobrien  if (flag_syntax_only)
38990075Sobrien    {
39090075Sobrien      TREE_ASM_WRITTEN (thunk_fndecl) = 1;
39190075Sobrien      return;
39290075Sobrien    }
39390075Sobrien
39490075Sobrien  push_to_top_level ();
39590075Sobrien
396169689Skan  if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)
397169689Skan      && targetm.have_named_sections)
398132718Skan    {
399132718Skan      resolve_unique_section (function, 0, flag_function_sections);
400132718Skan
401132718Skan      if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function))
402132718Skan	{
403132718Skan	  resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
404132718Skan
405132718Skan	  /* Output the thunk into the same section as function.  */
406132718Skan	  DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function);
407132718Skan	}
408132718Skan    }
409132718Skan
41096263Sobrien  /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
41196263Sobrien     create one.  */
41296263Sobrien  DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
413169689Skan
414169689Skan  /* Set up cloned argument trees for the thunk.  */
415169689Skan  t = NULL_TREE;
416169689Skan  for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
417169689Skan    {
418169689Skan      tree x = copy_node (a);
419169689Skan      TREE_CHAIN (x) = t;
420169689Skan      DECL_CONTEXT (x) = thunk_fndecl;
421169689Skan      SET_DECL_RTL (x, NULL_RTX);
422169689Skan      DECL_HAS_VALUE_EXPR_P (x) = 0;
423169689Skan      t = x;
424169689Skan    }
425169689Skan  a = nreverse (t);
426169689Skan  DECL_ARGUMENTS (thunk_fndecl) = a;
427169689Skan  BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a;
428169689Skan
429132718Skan  if (this_adjusting
430132718Skan      && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
431132718Skan					      virtual_value, alias))
43290075Sobrien    {
43390075Sobrien      const char *fnname;
43490075Sobrien      current_function_decl = thunk_fndecl;
43590075Sobrien      DECL_RESULT (thunk_fndecl)
43690075Sobrien	= build_decl (RESULT_DECL, 0, integer_type_node);
43790075Sobrien      fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
438132718Skan      init_function_start (thunk_fndecl);
43990075Sobrien      current_function_is_thunk = 1;
44090075Sobrien      assemble_start_function (thunk_fndecl, fnname);
441117395Skan
442132718Skan      targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
443132718Skan				       fixed_offset, virtual_value, alias);
444117395Skan
44590075Sobrien      assemble_end_function (thunk_fndecl, fnname);
446169689Skan      init_insn_lengths ();
44790075Sobrien      current_function_decl = 0;
44890075Sobrien      cfun = 0;
44990075Sobrien      TREE_ASM_WRITTEN (thunk_fndecl) = 1;
45090075Sobrien    }
45190075Sobrien  else
45296263Sobrien    {
453132718Skan      /* If this is a covariant thunk, or we don't have the necessary
454132718Skan	 code for efficient thunks, generate a thunk function that
455132718Skan	 just makes a call to the real function.  Unfortunately, this
456132718Skan	 doesn't work for varargs.  */
45718334Speter
45896263Sobrien      if (varargs_function_p (function))
459169689Skan	error ("generic thunk code fails for method %q#D which uses %<...%>",
46096263Sobrien	       function);
46118334Speter
46296263Sobrien      DECL_RESULT (thunk_fndecl) = NULL_TREE;
46318334Speter
464169689Skan      start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
46596263Sobrien      /* We don't bother with a body block for thunks.  */
46618334Speter
467132718Skan      /* There's no need to check accessibility inside the thunk body.  */
468132718Skan      push_deferring_access_checks (dk_no_check);
46918334Speter
470132718Skan      t = a;
471132718Skan      if (this_adjusting)
472132718Skan	t = thunk_adjust (t, /*this_adjusting=*/1,
473132718Skan			  fixed_offset, virtual_offset);
474169689Skan
47596263Sobrien      /* Build up the call to the real function.  */
47696263Sobrien      t = tree_cons (NULL_TREE, t, NULL_TREE);
47796263Sobrien      for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
47896263Sobrien	t = tree_cons (NULL_TREE, a, t);
47996263Sobrien      t = nreverse (t);
480132718Skan      t = build_call (alias, t);
481132718Skan      CALL_FROM_THUNK_P (t) = 1;
482169689Skan
48396263Sobrien      if (VOID_TYPE_P (TREE_TYPE (t)))
48496263Sobrien	finish_expr_stmt (t);
48596263Sobrien      else
486169689Skan	{
487169689Skan	  if (!this_adjusting)
488169689Skan	    {
489169689Skan	      tree cond = NULL_TREE;
49070635Sobrien
491169689Skan	      if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
492169689Skan		{
493169689Skan		  /* If the return type is a pointer, we need to
494169689Skan		     protect against NULL.  We know there will be an
495169689Skan		     adjustment, because that's why we're emitting a
496169689Skan		     thunk.  */
497169689Skan		  t = save_expr (t);
498169689Skan		  cond = cp_convert (boolean_type_node, t);
499169689Skan		}
500169689Skan
501169689Skan	      t = thunk_adjust (t, /*this_adjusting=*/0,
502169689Skan				fixed_offset, virtual_offset);
503169689Skan	      if (cond)
504169689Skan		t = build3 (COND_EXPR, TREE_TYPE (t), cond, t,
505169689Skan			    cp_convert (TREE_TYPE (t), integer_zero_node));
506169689Skan	    }
507169689Skan	  if (IS_AGGR_TYPE (TREE_TYPE (t)))
508169689Skan	    t = build_cplus_new (TREE_TYPE (t), t);
509169689Skan	  finish_return_stmt (t);
510169689Skan	}
511169689Skan
51296263Sobrien      /* Since we want to emit the thunk, we explicitly mark its name as
51396263Sobrien	 referenced.  */
514169689Skan      mark_decl_referenced (thunk_fndecl);
51560967Sobrien
51696263Sobrien      /* But we don't want debugging information about it.  */
51796263Sobrien      DECL_IGNORED_P (thunk_fndecl) = 1;
51860967Sobrien
519132718Skan      /* Re-enable access control.  */
520132718Skan      pop_deferring_access_checks ();
521132718Skan
522169689Skan      thunk_fndecl = finish_function (0);
523169689Skan      tree_lowering_passes (thunk_fndecl);
524169689Skan      expand_body (thunk_fndecl);
52596263Sobrien    }
52660967Sobrien
52790075Sobrien  pop_from_top_level ();
52860967Sobrien}
52960967Sobrien
53018334Speter/* Code for synthesizing methods which have default semantics defined.  */
53118334Speter
53218334Speter/* Generate code for default X(X&) constructor.  */
53350397Sobrien
53450397Sobrienstatic void
535132718Skando_build_copy_constructor (tree fndecl)
53618334Speter{
53790075Sobrien  tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
53818334Speter
53918334Speter  parm = convert_from_reference (parm);
54018334Speter
54150397Sobrien  if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
54250397Sobrien      && is_empty_class (current_class_type))
54350397Sobrien    /* Don't copy the padding byte; it might not have been allocated
54450397Sobrien       if *this is a base subobject.  */;
54550397Sobrien  else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
54618334Speter    {
547169689Skan      tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
54890075Sobrien      finish_expr_stmt (t);
54918334Speter    }
55018334Speter  else
55118334Speter    {
55218334Speter      tree fields = TYPE_FIELDS (current_class_type);
55390075Sobrien      tree member_init_list = NULL_TREE;
55490075Sobrien      int cvquals = cp_type_quals (TREE_TYPE (parm));
55518334Speter      int i;
556169689Skan      tree binfo, base_binfo;
557169689Skan      VEC(tree,gc) *vbases;
55818334Speter
55990075Sobrien      /* Initialize all the base-classes with the parameter converted
56090075Sobrien	 to their type so that we get their copy constructor and not
56190075Sobrien	 another constructor that takes current_class_type.  We must
56290075Sobrien	 deal with the binfo's directly as a direct base might be
56390075Sobrien	 inaccessible due to ambiguity.  */
564169689Skan      for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
565169689Skan	   VEC_iterate (tree, vbases, i, binfo); i++)
56690075Sobrien	{
567169689Skan	  member_init_list
568117395Skan	    = tree_cons (binfo,
569117395Skan			 build_tree_list (NULL_TREE,
570117395Skan					  build_base_path (PLUS_EXPR, parm,
571117395Skan							   binfo, 1)),
572117395Skan			 member_init_list);
57390075Sobrien	}
57490075Sobrien
575169689Skan      for (binfo = TYPE_BINFO (current_class_type), i = 0;
576169689Skan	   BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
57718334Speter	{
578169689Skan	  if (BINFO_VIRTUAL_P (base_binfo))
579169689Skan	    continue;
58018334Speter
581169689Skan	  member_init_list
582169689Skan	    = tree_cons (base_binfo,
583117395Skan			 build_tree_list (NULL_TREE,
584117395Skan					  build_base_path (PLUS_EXPR, parm,
585169689Skan							   base_binfo, 1)),
586117395Skan			 member_init_list);
58752284Sobrien	}
58850397Sobrien
58918334Speter      for (; fields; fields = TREE_CHAIN (fields))
59018334Speter	{
591146895Skan	  tree init = parm;
59218334Speter	  tree field = fields;
59396263Sobrien	  tree expr_type;
59418334Speter
59518334Speter	  if (TREE_CODE (field) != FIELD_DECL)
59618334Speter	    continue;
59750397Sobrien
598146895Skan	  expr_type = TREE_TYPE (field);
59918334Speter	  if (DECL_NAME (field))
60018334Speter	    {
60118334Speter	      if (VFIELD_NAME_P (DECL_NAME (field)))
60218334Speter		continue;
60318334Speter	    }
604146895Skan	  else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
60590075Sobrien	    /* Just use the field; anonymous types can't have
60690075Sobrien	       nontrivial copy ctors or assignment ops.  */;
60718334Speter	  else
60818334Speter	    continue;
60918334Speter
61096263Sobrien	  /* Compute the type of "init->field".  If the copy-constructor
61196263Sobrien	     parameter is, for example, "const S&", and the type of
61296263Sobrien	     the field is "T", then the type will usually be "const
61396263Sobrien	     T".  (There are no cv-qualified variants of reference
61496263Sobrien	     types.)  */
61596263Sobrien	  if (TREE_CODE (expr_type) != REFERENCE_TYPE)
616146895Skan	    {
617146895Skan	      int quals = cvquals;
618169689Skan
619146895Skan	      if (DECL_MUTABLE_P (field))
620146895Skan		quals &= ~TYPE_QUAL_CONST;
621146895Skan	      expr_type = cp_build_qualified_type (expr_type, quals);
622146895Skan	    }
623169689Skan
624169689Skan	  init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
62518334Speter	  init = build_tree_list (NULL_TREE, init);
62618334Speter
627146895Skan	  member_init_list = tree_cons (field, init, member_init_list);
62818334Speter	}
629117395Skan      finish_mem_initializers (member_init_list);
63018334Speter    }
63118334Speter}
63218334Speter
63350397Sobrienstatic void
634132718Skando_build_assign_ref (tree fndecl)
63518334Speter{
63618334Speter  tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
63790075Sobrien  tree compound_stmt;
63818334Speter
639169689Skan  compound_stmt = begin_compound_stmt (0);
64018334Speter  parm = convert_from_reference (parm);
64118334Speter
64250397Sobrien  if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
64350397Sobrien      && is_empty_class (current_class_type))
64450397Sobrien    /* Don't copy the padding byte; it might not have been allocated
64550397Sobrien       if *this is a base subobject.  */;
64650397Sobrien  else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
64718334Speter    {
648169689Skan      tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm);
64990075Sobrien      finish_expr_stmt (t);
65018334Speter    }
65118334Speter  else
65218334Speter    {
653117395Skan      tree fields;
65490075Sobrien      int cvquals = cp_type_quals (TREE_TYPE (parm));
65518334Speter      int i;
656169689Skan      tree binfo, base_binfo;
65718334Speter
658119256Skan      /* Assign to each of the direct base classes.  */
659169689Skan      for (binfo = TYPE_BINFO (current_class_type), i = 0;
660169689Skan	   BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
66118334Speter	{
662117395Skan	  tree converted_parm;
66390075Sobrien
664117395Skan	  /* We must convert PARM directly to the base class
665117395Skan	     explicitly since the base class may be ambiguous.  */
666169689Skan	  converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
667117395Skan	  /* Call the base class assignment operator.  */
668169689Skan	  finish_expr_stmt
669169689Skan	    (build_special_member_call (current_class_ref,
670117395Skan					ansi_assopname (NOP_EXPR),
671169689Skan					build_tree_list (NULL_TREE,
672117395Skan							 converted_parm),
673169689Skan					base_binfo,
674117395Skan					LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
67518334Speter	}
676117395Skan
677117395Skan      /* Assign to each of the non-static data members.  */
678169689Skan      for (fields = TYPE_FIELDS (current_class_type);
679169689Skan	   fields;
680117395Skan	   fields = TREE_CHAIN (fields))
68118334Speter	{
682146895Skan	  tree comp = current_class_ref;
683146895Skan	  tree init = parm;
68418334Speter	  tree field = fields;
685146895Skan	  tree expr_type;
686146895Skan	  int quals;
68718334Speter
688117395Skan	  if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
68918334Speter	    continue;
69050397Sobrien
691146895Skan	  expr_type = TREE_TYPE (field);
692169689Skan
693146895Skan	  if (CP_TYPE_CONST_P (expr_type))
69450397Sobrien	    {
695169689Skan	      error ("non-static const member %q#D, can't use default "
696169689Skan		     "assignment operator", field);
69750397Sobrien	      continue;
69850397Sobrien	    }
699146895Skan	  else if (TREE_CODE (expr_type) == REFERENCE_TYPE)
70050397Sobrien	    {
701169689Skan	      error ("non-static reference member %q#D, can't use "
702169689Skan		     "default assignment operator", field);
70350397Sobrien	      continue;
70450397Sobrien	    }
70550397Sobrien
70618334Speter	  if (DECL_NAME (field))
70718334Speter	    {
70818334Speter	      if (VFIELD_NAME_P (DECL_NAME (field)))
70918334Speter		continue;
71018334Speter	    }
711169689Skan	  else if (ANON_AGGR_TYPE_P (expr_type)
712169689Skan		   && TYPE_FIELDS (expr_type) != NULL_TREE)
71390075Sobrien	    /* Just use the field; anonymous types can't have
71490075Sobrien	       nontrivial copy ctors or assignment ops.  */;
71518334Speter	  else
71618334Speter	    continue;
71718334Speter
718169689Skan	  comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE);
71918334Speter
720146895Skan	  /* Compute the type of init->field  */
721146895Skan	  quals = cvquals;
722146895Skan	  if (DECL_MUTABLE_P (field))
723146895Skan	    quals &= ~TYPE_QUAL_CONST;
724146895Skan	  expr_type = cp_build_qualified_type (expr_type, quals);
725146895Skan
726169689Skan	  init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
727169689Skan
72890075Sobrien	  if (DECL_NAME (field))
729146895Skan	    init = build_modify_expr (comp, NOP_EXPR, init);
73090075Sobrien	  else
731169689Skan	    init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
732146895Skan	  finish_expr_stmt (init);
73318334Speter	}
73418334Speter    }
73590075Sobrien  finish_return_stmt (current_class_ref);
736132718Skan  finish_compound_stmt (compound_stmt);
73718334Speter}
73818334Speter
739169689Skan/* Synthesize FNDECL, a non-static member function.   */
740169689Skan
74118334Spetervoid
742132718Skansynthesize_method (tree fndecl)
74318334Speter{
744132718Skan  bool nested = (current_function_decl != NULL_TREE);
74590075Sobrien  tree context = decl_function_context (fndecl);
746132718Skan  bool need_body = true;
74790075Sobrien  tree stmt;
748169689Skan  location_t save_input_location = input_location;
749169689Skan  int error_count = errorcount;
750169689Skan  int warning_count = warningcount;
75118334Speter
752169689Skan  /* Reset the source location, we might have been previously
753169689Skan     deferred, and thus have saved where we were first needed.  */
754169689Skan  DECL_SOURCE_LOCATION (fndecl)
755169689Skan    = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl)));
75690075Sobrien
75790075Sobrien  /* If we've been asked to synthesize a clone, just synthesize the
75890075Sobrien     cloned function instead.  Doing so will automatically fill in the
75990075Sobrien     body for the clone.  */
76090075Sobrien  if (DECL_CLONED_FUNCTION_P (fndecl))
761169689Skan    fndecl = DECL_CLONED_FUNCTION (fndecl);
76260967Sobrien
763132718Skan  /* We may be in the middle of deferred access check.  Disable
764132718Skan     it now.  */
765132718Skan  push_deferring_access_checks (dk_no_deferred);
766132718Skan
76750397Sobrien  if (! context)
76850397Sobrien    push_to_top_level ();
76950397Sobrien  else if (nested)
77090075Sobrien    push_function_context_to (context);
77118334Speter
772169689Skan  input_location = DECL_SOURCE_LOCATION (fndecl);
77390075Sobrien
774169689Skan  start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
77590075Sobrien  stmt = begin_function_body ();
77618334Speter
77790075Sobrien  if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
77818334Speter    {
77990075Sobrien      do_build_assign_ref (fndecl);
780132718Skan      need_body = false;
78190075Sobrien    }
78290075Sobrien  else if (DECL_CONSTRUCTOR_P (fndecl))
78390075Sobrien    {
78490075Sobrien      tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl);
78590075Sobrien      if (arg_chain != void_list_node)
78618334Speter	do_build_copy_constructor (fndecl);
787169689Skan      else
78890075Sobrien	finish_mem_initializers (NULL_TREE);
78918334Speter    }
79018334Speter
79190075Sobrien  /* If we haven't yet generated the body of the function, just
79290075Sobrien     generate an empty compound statement.  */
79390075Sobrien  if (need_body)
79490075Sobrien    {
79590075Sobrien      tree compound_stmt;
796169689Skan      compound_stmt = begin_compound_stmt (BCS_FN_BODY);
797132718Skan      finish_compound_stmt (compound_stmt);
79890075Sobrien    }
79918334Speter
80090075Sobrien  finish_function_body (stmt);
801132718Skan  expand_or_defer_fn (finish_function (0));
80290075Sobrien
803169689Skan  input_location = save_input_location;
804169689Skan
80550397Sobrien  if (! context)
80650397Sobrien    pop_from_top_level ();
80750397Sobrien  else if (nested)
80890075Sobrien    pop_function_context_from (context);
809132718Skan
810132718Skan  pop_deferring_access_checks ();
811169689Skan
812169689Skan  if (error_count != errorcount || warning_count != warningcount)
813169689Skan    inform ("%Hsynthesized method %qD first required here ",
814169689Skan	    &input_location, fndecl);
81518334Speter}
81690075Sobrien
81790075Sobrien/* Use EXTRACTOR to locate the relevant function called for each base &
81890075Sobrien   class field of TYPE. CLIENT allows additional information to be passed
81996263Sobrien   to EXTRACTOR.  Generates the union of all exceptions generated by those
82096263Sobrien   functions.  Note that we haven't updated TYPE_FIELDS and such of any
82196263Sobrien   variants yet, so we need to look at the main one.  */
82290075Sobrien
82390075Sobrienstatic tree
824132718Skansynthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
825169689Skan			   void *client)
82690075Sobrien{
82790075Sobrien  tree raises = empty_except_spec;
82890075Sobrien  tree fields = TYPE_FIELDS (type);
829169689Skan  tree binfo, base_binfo;
830169689Skan  int i;
83196263Sobrien
832169689Skan  for (binfo = TYPE_BINFO (type), i = 0;
833169689Skan       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
83490075Sobrien    {
835169689Skan      tree fn = (*extractor) (BINFO_TYPE (base_binfo), client);
83690075Sobrien      if (fn)
837169689Skan	{
838169689Skan	  tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
839169689Skan
840169689Skan	  raises = merge_exception_specifiers (raises, fn_raises);
841169689Skan	}
84290075Sobrien    }
84390075Sobrien  for (; fields; fields = TREE_CHAIN (fields))
84490075Sobrien    {
84590075Sobrien      tree type = TREE_TYPE (fields);
84690075Sobrien      tree fn;
847169689Skan
848117395Skan      if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
849169689Skan	continue;
85090075Sobrien      while (TREE_CODE (type) == ARRAY_TYPE)
851169689Skan	type = TREE_TYPE (type);
852161651Skan      if (!CLASS_TYPE_P (type))
853169689Skan	continue;
854169689Skan
85590075Sobrien      fn = (*extractor) (type, client);
85690075Sobrien      if (fn)
857169689Skan	{
858169689Skan	  tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
859169689Skan
860169689Skan	  raises = merge_exception_specifiers (raises, fn_raises);
861169689Skan	}
86290075Sobrien    }
86390075Sobrien  return raises;
86490075Sobrien}
86590075Sobrien
86690075Sobrien/* Locate the dtor of TYPE.  */
86790075Sobrien
86890075Sobrienstatic tree
869132718Skanlocate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
87090075Sobrien{
871169689Skan  return CLASSTYPE_DESTRUCTORS (type);
87290075Sobrien}
87390075Sobrien
87490075Sobrien/* Locate the default ctor of TYPE.  */
87590075Sobrien
87690075Sobrienstatic tree
877132718Skanlocate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
87890075Sobrien{
87990075Sobrien  tree fns;
880169689Skan
88190075Sobrien  if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
88290075Sobrien    return NULL_TREE;
883169689Skan
884169689Skan  /* Call lookup_fnfields_1 to create the constructor declarations, if
885169689Skan     necessary.  */
886169689Skan  if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
887169689Skan    return lazily_declare_fn (sfk_constructor, type);
888169689Skan
889169689Skan  for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
89090075Sobrien    {
89190075Sobrien      tree fn = OVL_CURRENT (fns);
89290075Sobrien      tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
893169689Skan
894161651Skan      parms = skip_artificial_parms_for (fn, parms);
895161651Skan
896161651Skan      if (sufficient_parms_p (parms))
897169689Skan	return fn;
89890075Sobrien    }
899169689Skan  gcc_unreachable ();
90090075Sobrien}
90190075Sobrien
90290075Sobrienstruct copy_data
90390075Sobrien{
90490075Sobrien  tree name;
90590075Sobrien  int quals;
90690075Sobrien};
90790075Sobrien
90890075Sobrien/* Locate the copy ctor or copy assignment of TYPE. CLIENT_
90990075Sobrien   points to a COPY_DATA holding the name (NULL for the ctor)
91090075Sobrien   and desired qualifiers of the source operand.  */
91190075Sobrien
91290075Sobrienstatic tree
913132718Skanlocate_copy (tree type, void *client_)
91490075Sobrien{
91590075Sobrien  struct copy_data *client = (struct copy_data *)client_;
91690075Sobrien  tree fns;
91790075Sobrien  tree best = NULL_TREE;
918132718Skan  bool excess_p = false;
919169689Skan
92090075Sobrien  if (client->name)
92190075Sobrien    {
922169689Skan      int ix;
923169689Skan      ix = lookup_fnfields_1 (type, client->name);
924169689Skan      if (ix < 0)
925169689Skan	return NULL_TREE;
926169689Skan      fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
92790075Sobrien    }
92890075Sobrien  else if (TYPE_HAS_INIT_REF (type))
929169689Skan    {
930169689Skan      /* If construction of the copy constructor was postponed, create
931169689Skan	 it now.  */
932169689Skan      if (CLASSTYPE_LAZY_COPY_CTOR (type))
933169689Skan	lazily_declare_fn (sfk_copy_constructor, type);
934169689Skan      fns = CLASSTYPE_CONSTRUCTORS (type);
935169689Skan    }
936169689Skan  else
93790075Sobrien    return NULL_TREE;
93890075Sobrien  for (; fns; fns = OVL_NEXT (fns))
93990075Sobrien    {
94090075Sobrien      tree fn = OVL_CURRENT (fns);
94190075Sobrien      tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
94290075Sobrien      tree src_type;
94390075Sobrien      int excess;
94490075Sobrien      int quals;
945169689Skan
946161651Skan      parms = skip_artificial_parms_for (fn, parms);
94790075Sobrien      if (!parms)
948169689Skan	continue;
949132718Skan      src_type = non_reference (TREE_VALUE (parms));
950169689Skan
951169689Skan      if (src_type == error_mark_node)
952169689Skan        return NULL_TREE;
953169689Skan
95490075Sobrien      if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
955169689Skan	continue;
95690075Sobrien      if (!sufficient_parms_p (TREE_CHAIN (parms)))
957169689Skan	continue;
95890075Sobrien      quals = cp_type_quals (src_type);
95990075Sobrien      if (client->quals & ~quals)
960169689Skan	continue;
96190075Sobrien      excess = quals & ~client->quals;
96290075Sobrien      if (!best || (excess_p && !excess))
963169689Skan	{
964169689Skan	  best = fn;
965169689Skan	  excess_p = excess;
966169689Skan	}
96790075Sobrien      else
968169689Skan	/* Ambiguous */
969169689Skan	return NULL_TREE;
97090075Sobrien    }
97190075Sobrien  return best;
97290075Sobrien}
97390075Sobrien
97490075Sobrien/* Implicitly declare the special function indicated by KIND, as a
97590075Sobrien   member of TYPE.  For copy constructors and assignment operators,
97690075Sobrien   CONST_P indicates whether these functions should take a const
977169689Skan   reference argument or a non-const reference.  Returns the
978169689Skan   FUNCTION_DECL for the implicitly declared function.  */
97990075Sobrien
980169689Skanstatic tree
981132718Skanimplicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
98290075Sobrien{
983169689Skan  tree fn;
984169689Skan  tree parameter_types = void_list_node;
985169689Skan  tree return_type;
986169689Skan  tree fn_type;
98790075Sobrien  tree raises = empty_except_spec;
988169689Skan  tree rhs_parm_type = NULL_TREE;
989169689Skan  tree this_parm;
990169689Skan  tree name;
991169689Skan  HOST_WIDE_INT saved_processing_template_decl;
99290075Sobrien
993169689Skan  /* Because we create declarations for implicitly declared functions
994169689Skan     lazily, we may be creating the declaration for a member of TYPE
995169689Skan     while in some completely different context.  However, TYPE will
996169689Skan     never be a dependent class (because we never want to do lookups
997169689Skan     for implicitly defined functions in a dependent class).
998169689Skan     Furthermore, we must set PROCESSING_TEMPLATE_DECL to zero here
999169689Skan     because we only create clones for constructors and destructors
1000169689Skan     when not in a template.  */
1001169689Skan  gcc_assert (!dependent_type_p (type));
1002169689Skan  saved_processing_template_decl = processing_template_decl;
1003169689Skan  processing_template_decl = 0;
1004169689Skan
1005169689Skan  type = TYPE_MAIN_VARIANT (type);
1006169689Skan
1007169689Skan  if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (type))
1008169689Skan    {
1009169689Skan      if (kind == sfk_destructor)
1010169689Skan	/* See comment in check_special_function_return_type.  */
1011169689Skan	return_type = build_pointer_type (void_type_node);
1012169689Skan      else
1013169689Skan	return_type = build_pointer_type (type);
1014169689Skan    }
1015169689Skan  else
1016169689Skan    return_type = void_type_node;
1017169689Skan
101890075Sobrien  switch (kind)
101990075Sobrien    {
102090075Sobrien    case sfk_destructor:
102190075Sobrien      /* Destructor.  */
1022169689Skan      name = constructor_name (type);
102390075Sobrien      raises = synthesize_exception_spec (type, &locate_dtor, 0);
102490075Sobrien      break;
102590075Sobrien
102690075Sobrien    case sfk_constructor:
102790075Sobrien      /* Default constructor.  */
1028169689Skan      name = constructor_name (type);
102990075Sobrien      raises = synthesize_exception_spec (type, &locate_ctor, 0);
103090075Sobrien      break;
103190075Sobrien
103290075Sobrien    case sfk_copy_constructor:
103390075Sobrien    case sfk_assignment_operator:
103490075Sobrien    {
103590075Sobrien      struct copy_data data;
1036169689Skan
103790075Sobrien      data.name = NULL;
103890075Sobrien      data.quals = 0;
103990075Sobrien      if (kind == sfk_assignment_operator)
1040169689Skan	{
1041169689Skan	  return_type = build_reference_type (type);
1042169689Skan	  name = ansi_assopname (NOP_EXPR);
1043169689Skan	  data.name = name;
1044169689Skan	}
1045169689Skan      else
1046169689Skan	name = constructor_name (type);
104790075Sobrien
104890075Sobrien      if (const_p)
1049169689Skan	{
1050169689Skan	  data.quals = TYPE_QUAL_CONST;
1051169689Skan	  rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST);
1052169689Skan	}
1053169689Skan      else
1054169689Skan	rhs_parm_type = type;
1055169689Skan      rhs_parm_type = build_reference_type (rhs_parm_type);
1056169689Skan      parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types);
105790075Sobrien      raises = synthesize_exception_spec (type, &locate_copy, &data);
105890075Sobrien      break;
105990075Sobrien    }
106090075Sobrien    default:
1061169689Skan      gcc_unreachable ();
106290075Sobrien    }
106390075Sobrien
1064169689Skan  /* Create the function.  */
1065169689Skan  fn_type = build_method_type_directly (type, return_type, parameter_types);
1066169689Skan  if (raises)
1067169689Skan    fn_type = build_exception_variant (fn_type, raises);
1068169689Skan  fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
1069169689Skan  DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type));
1070169689Skan  if (kind == sfk_constructor || kind == sfk_copy_constructor)
1071169689Skan    DECL_CONSTRUCTOR_P (fn) = 1;
1072169689Skan  else if (kind == sfk_destructor)
1073169689Skan    DECL_DESTRUCTOR_P (fn) = 1;
1074169689Skan  else
1075169689Skan    {
1076169689Skan      DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
1077169689Skan      SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
1078169689Skan    }
1079169689Skan  /* Create the explicit arguments.  */
1080169689Skan  if (rhs_parm_type)
1081169689Skan    {
1082169689Skan      /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we
1083169689Skan	 want its type to be included in the mangled function
1084169689Skan	 name.  */
1085169689Skan      DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
1086169689Skan      TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
1087169689Skan    }
1088169689Skan  /* Add the "this" parameter.  */
1089169689Skan  this_parm = build_this_parm (fn_type, TYPE_UNQUALIFIED);
1090169689Skan  TREE_CHAIN (this_parm) = DECL_ARGUMENTS (fn);
1091169689Skan  DECL_ARGUMENTS (fn) = this_parm;
109290075Sobrien
1093169689Skan  grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL);
1094169689Skan  set_linkage_according_to_type (type, fn);
1095169689Skan  rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
1096169689Skan  DECL_IN_AGGR_P (fn) = 1;
109790075Sobrien  DECL_ARTIFICIAL (fn) = 1;
109890075Sobrien  DECL_NOT_REALLY_EXTERN (fn) = 1;
109990075Sobrien  DECL_DECLARED_INLINE_P (fn) = 1;
110090075Sobrien  DECL_INLINE (fn) = 1;
1101169689Skan  gcc_assert (!TREE_USED (fn));
1102169689Skan
1103169689Skan  /* Restore PROCESSING_TEMPLATE_DECL.  */
1104169689Skan  processing_template_decl = saved_processing_template_decl;
1105169689Skan
110690075Sobrien  return fn;
110790075Sobrien}
110890075Sobrien
1109169689Skan/* Add an implicit declaration to TYPE for the kind of function
1110169689Skan   indicated by SFK.  Return the FUNCTION_DECL for the new implicit
1111169689Skan   declaration.  */
1112169689Skan
1113169689Skantree
1114169689Skanlazily_declare_fn (special_function_kind sfk, tree type)
1115169689Skan{
1116169689Skan  tree fn;
1117169689Skan  bool const_p;
1118169689Skan
1119169689Skan  /* Figure out whether or not the argument has a const reference
1120169689Skan     type.  */
1121169689Skan  if (sfk == sfk_copy_constructor)
1122169689Skan    const_p = TYPE_HAS_CONST_INIT_REF (type);
1123169689Skan  else if (sfk == sfk_assignment_operator)
1124169689Skan    const_p = TYPE_HAS_CONST_ASSIGN_REF (type);
1125169689Skan  else
1126169689Skan    /* In this case, CONST_P will be ignored.  */
1127169689Skan    const_p = false;
1128169689Skan  /* Declare the function.  */
1129169689Skan  fn = implicitly_declare_fn (sfk, type, const_p);
1130169689Skan  /* A destructor may be virtual.  */
1131169689Skan  if (sfk == sfk_destructor)
1132169689Skan    check_for_override (fn, type);
1133169689Skan  /* Add it to CLASSTYPE_METHOD_VEC.  */
1134169689Skan  add_method (type, fn, NULL_TREE);
1135169689Skan  /* Add it to TYPE_METHODS.  */
1136169689Skan  if (sfk == sfk_destructor
1137169689Skan      && DECL_VIRTUAL_P (fn)
1138169689Skan      && abi_version_at_least (2))
1139169689Skan    /* The ABI requires that a virtual destructor go at the end of the
1140169689Skan       vtable.  */
1141169689Skan    TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn);
1142169689Skan  else
1143169689Skan    {
1144169689Skan      /* G++ 3.2 put the implicit destructor at the *beginning* of the
1145169689Skan	 TYPE_METHODS list, which cause the destructor to be emitted
1146169689Skan	 in an incorrect location in the vtable.  */
1147169689Skan      if (warn_abi && DECL_VIRTUAL_P (fn))
1148169689Skan	warning (OPT_Wabi, "vtable layout for class %qT may not be ABI-compliant"
1149169689Skan		 "and may change in a future version of GCC due to "
1150169689Skan		 "implicit virtual destructor",
1151169689Skan		 type);
1152169689Skan      TREE_CHAIN (fn) = TYPE_METHODS (type);
1153169689Skan      TYPE_METHODS (type) = fn;
1154169689Skan    }
1155169689Skan  maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0);
1156169689Skan  if (sfk == sfk_assignment_operator)
1157169689Skan    CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0;
1158169689Skan  else
1159169689Skan    {
1160169689Skan      /* Remember that the function has been created.  */
1161169689Skan      if (sfk == sfk_constructor)
1162169689Skan	CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0;
1163169689Skan      else if (sfk == sfk_copy_constructor)
1164169689Skan	CLASSTYPE_LAZY_COPY_CTOR (type) = 0;
1165169689Skan      else if (sfk == sfk_destructor)
1166169689Skan	CLASSTYPE_LAZY_DESTRUCTOR (type) = 0;
1167169689Skan      /* Create appropriate clones.  */
1168169689Skan      clone_function_decl (fn, /*update_method_vec=*/true);
1169169689Skan    }
1170169689Skan
1171169689Skan  return fn;
1172169689Skan}
1173169689Skan
117490075Sobrien/* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST
117590075Sobrien   as there are artificial parms in FN.  */
117690075Sobrien
117790075Sobrientree
1178132718Skanskip_artificial_parms_for (tree fn, tree list)
117990075Sobrien{
118090075Sobrien  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
118190075Sobrien    list = TREE_CHAIN (list);
118290075Sobrien  else
118390075Sobrien    return list;
118490075Sobrien
118590075Sobrien  if (DECL_HAS_IN_CHARGE_PARM_P (fn))
118690075Sobrien    list = TREE_CHAIN (list);
118790075Sobrien  if (DECL_HAS_VTT_PARM_P (fn))
118890075Sobrien    list = TREE_CHAIN (list);
118990075Sobrien  return list;
119090075Sobrien}
1191132718Skan
1192132718Skan#include "gt-cp-method.h"
1193