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
410169689Skan  /* Set up cloned argument trees for the thunk.  */
411169689Skan  t = NULL_TREE;
412169689Skan  for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
413169689Skan    {
414169689Skan      tree x = copy_node (a);
415169689Skan      TREE_CHAIN (x) = t;
416169689Skan      DECL_CONTEXT (x) = thunk_fndecl;
417169689Skan      SET_DECL_RTL (x, NULL_RTX);
418169689Skan      DECL_HAS_VALUE_EXPR_P (x) = 0;
419169689Skan      t = x;
420169689Skan    }
421169689Skan  a = nreverse (t);
422169689Skan  DECL_ARGUMENTS (thunk_fndecl) = a;
423169689Skan
424132718Skan  if (this_adjusting
425132718Skan      && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
426132718Skan					      virtual_value, alias))
42790075Sobrien    {
42890075Sobrien      const char *fnname;
429260139Spfg      tree fn_block;
430260139Spfg
43190075Sobrien      current_function_decl = thunk_fndecl;
43290075Sobrien      DECL_RESULT (thunk_fndecl)
43390075Sobrien	= build_decl (RESULT_DECL, 0, integer_type_node);
43490075Sobrien      fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
435260139Spfg      /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
436260139Spfg	 create one.  */
437260139Spfg      fn_block = make_node (BLOCK);
438260139Spfg      BLOCK_VARS (fn_block) = a;
439260139Spfg      DECL_INITIAL (thunk_fndecl) = fn_block;
440132718Skan      init_function_start (thunk_fndecl);
44190075Sobrien      current_function_is_thunk = 1;
44290075Sobrien      assemble_start_function (thunk_fndecl, fnname);
443117395Skan
444132718Skan      targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
445132718Skan				       fixed_offset, virtual_value, alias);
446117395Skan
44790075Sobrien      assemble_end_function (thunk_fndecl, fnname);
448169689Skan      init_insn_lengths ();
44990075Sobrien      current_function_decl = 0;
45090075Sobrien      cfun = 0;
45190075Sobrien      TREE_ASM_WRITTEN (thunk_fndecl) = 1;
45290075Sobrien    }
45390075Sobrien  else
45496263Sobrien    {
455132718Skan      /* If this is a covariant thunk, or we don't have the necessary
456132718Skan	 code for efficient thunks, generate a thunk function that
457132718Skan	 just makes a call to the real function.  Unfortunately, this
458132718Skan	 doesn't work for varargs.  */
45918334Speter
46096263Sobrien      if (varargs_function_p (function))
461169689Skan	error ("generic thunk code fails for method %q#D which uses %<...%>",
46296263Sobrien	       function);
46318334Speter
46496263Sobrien      DECL_RESULT (thunk_fndecl) = NULL_TREE;
46518334Speter
466169689Skan      start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
46796263Sobrien      /* We don't bother with a body block for thunks.  */
46818334Speter
469132718Skan      /* There's no need to check accessibility inside the thunk body.  */
470132718Skan      push_deferring_access_checks (dk_no_check);
47118334Speter
472132718Skan      t = a;
473132718Skan      if (this_adjusting)
474132718Skan	t = thunk_adjust (t, /*this_adjusting=*/1,
475132718Skan			  fixed_offset, virtual_offset);
476169689Skan
47796263Sobrien      /* Build up the call to the real function.  */
47896263Sobrien      t = tree_cons (NULL_TREE, t, NULL_TREE);
47996263Sobrien      for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
48096263Sobrien	t = tree_cons (NULL_TREE, a, t);
48196263Sobrien      t = nreverse (t);
482132718Skan      t = build_call (alias, t);
483132718Skan      CALL_FROM_THUNK_P (t) = 1;
484169689Skan
48596263Sobrien      if (VOID_TYPE_P (TREE_TYPE (t)))
48696263Sobrien	finish_expr_stmt (t);
48796263Sobrien      else
488169689Skan	{
489169689Skan	  if (!this_adjusting)
490169689Skan	    {
491169689Skan	      tree cond = NULL_TREE;
49270635Sobrien
493169689Skan	      if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
494169689Skan		{
495169689Skan		  /* If the return type is a pointer, we need to
496169689Skan		     protect against NULL.  We know there will be an
497169689Skan		     adjustment, because that's why we're emitting a
498169689Skan		     thunk.  */
499169689Skan		  t = save_expr (t);
500169689Skan		  cond = cp_convert (boolean_type_node, t);
501169689Skan		}
502169689Skan
503169689Skan	      t = thunk_adjust (t, /*this_adjusting=*/0,
504169689Skan				fixed_offset, virtual_offset);
505169689Skan	      if (cond)
506169689Skan		t = build3 (COND_EXPR, TREE_TYPE (t), cond, t,
507169689Skan			    cp_convert (TREE_TYPE (t), integer_zero_node));
508169689Skan	    }
509169689Skan	  if (IS_AGGR_TYPE (TREE_TYPE (t)))
510169689Skan	    t = build_cplus_new (TREE_TYPE (t), t);
511169689Skan	  finish_return_stmt (t);
512169689Skan	}
513169689Skan
51496263Sobrien      /* Since we want to emit the thunk, we explicitly mark its name as
51596263Sobrien	 referenced.  */
516169689Skan      mark_decl_referenced (thunk_fndecl);
51760967Sobrien
51896263Sobrien      /* But we don't want debugging information about it.  */
51996263Sobrien      DECL_IGNORED_P (thunk_fndecl) = 1;
52060967Sobrien
521132718Skan      /* Re-enable access control.  */
522132718Skan      pop_deferring_access_checks ();
523132718Skan
524169689Skan      thunk_fndecl = finish_function (0);
525169689Skan      tree_lowering_passes (thunk_fndecl);
526169689Skan      expand_body (thunk_fndecl);
52796263Sobrien    }
52860967Sobrien
52990075Sobrien  pop_from_top_level ();
53060967Sobrien}
53160967Sobrien
53218334Speter/* Code for synthesizing methods which have default semantics defined.  */
53318334Speter
53418334Speter/* Generate code for default X(X&) constructor.  */
53550397Sobrien
53650397Sobrienstatic void
537132718Skando_build_copy_constructor (tree fndecl)
53818334Speter{
53990075Sobrien  tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
54018334Speter
54118334Speter  parm = convert_from_reference (parm);
54218334Speter
54350397Sobrien  if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
54450397Sobrien      && is_empty_class (current_class_type))
54550397Sobrien    /* Don't copy the padding byte; it might not have been allocated
54650397Sobrien       if *this is a base subobject.  */;
54750397Sobrien  else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
54818334Speter    {
549169689Skan      tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
55090075Sobrien      finish_expr_stmt (t);
55118334Speter    }
55218334Speter  else
55318334Speter    {
55418334Speter      tree fields = TYPE_FIELDS (current_class_type);
55590075Sobrien      tree member_init_list = NULL_TREE;
55690075Sobrien      int cvquals = cp_type_quals (TREE_TYPE (parm));
55718334Speter      int i;
558169689Skan      tree binfo, base_binfo;
559169689Skan      VEC(tree,gc) *vbases;
56018334Speter
56190075Sobrien      /* Initialize all the base-classes with the parameter converted
56290075Sobrien	 to their type so that we get their copy constructor and not
56390075Sobrien	 another constructor that takes current_class_type.  We must
56490075Sobrien	 deal with the binfo's directly as a direct base might be
56590075Sobrien	 inaccessible due to ambiguity.  */
566169689Skan      for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
567169689Skan	   VEC_iterate (tree, vbases, i, binfo); i++)
56890075Sobrien	{
569169689Skan	  member_init_list
570117395Skan	    = tree_cons (binfo,
571117395Skan			 build_tree_list (NULL_TREE,
572117395Skan					  build_base_path (PLUS_EXPR, parm,
573117395Skan							   binfo, 1)),
574117395Skan			 member_init_list);
57590075Sobrien	}
57690075Sobrien
577169689Skan      for (binfo = TYPE_BINFO (current_class_type), i = 0;
578169689Skan	   BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
57918334Speter	{
580169689Skan	  if (BINFO_VIRTUAL_P (base_binfo))
581169689Skan	    continue;
58218334Speter
583169689Skan	  member_init_list
584169689Skan	    = tree_cons (base_binfo,
585117395Skan			 build_tree_list (NULL_TREE,
586117395Skan					  build_base_path (PLUS_EXPR, parm,
587169689Skan							   base_binfo, 1)),
588117395Skan			 member_init_list);
58952284Sobrien	}
59050397Sobrien
59118334Speter      for (; fields; fields = TREE_CHAIN (fields))
59218334Speter	{
593146895Skan	  tree init = parm;
59418334Speter	  tree field = fields;
59596263Sobrien	  tree expr_type;
59618334Speter
59718334Speter	  if (TREE_CODE (field) != FIELD_DECL)
59818334Speter	    continue;
59950397Sobrien
600146895Skan	  expr_type = TREE_TYPE (field);
60118334Speter	  if (DECL_NAME (field))
60218334Speter	    {
60318334Speter	      if (VFIELD_NAME_P (DECL_NAME (field)))
60418334Speter		continue;
60518334Speter	    }
606146895Skan	  else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
60790075Sobrien	    /* Just use the field; anonymous types can't have
60890075Sobrien	       nontrivial copy ctors or assignment ops.  */;
60918334Speter	  else
61018334Speter	    continue;
61118334Speter
61296263Sobrien	  /* Compute the type of "init->field".  If the copy-constructor
61396263Sobrien	     parameter is, for example, "const S&", and the type of
61496263Sobrien	     the field is "T", then the type will usually be "const
61596263Sobrien	     T".  (There are no cv-qualified variants of reference
61696263Sobrien	     types.)  */
61796263Sobrien	  if (TREE_CODE (expr_type) != REFERENCE_TYPE)
618146895Skan	    {
619146895Skan	      int quals = cvquals;
620169689Skan
621146895Skan	      if (DECL_MUTABLE_P (field))
622146895Skan		quals &= ~TYPE_QUAL_CONST;
623146895Skan	      expr_type = cp_build_qualified_type (expr_type, quals);
624146895Skan	    }
625169689Skan
626169689Skan	  init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
62718334Speter	  init = build_tree_list (NULL_TREE, init);
62818334Speter
629146895Skan	  member_init_list = tree_cons (field, init, member_init_list);
63018334Speter	}
631117395Skan      finish_mem_initializers (member_init_list);
63218334Speter    }
63318334Speter}
63418334Speter
63550397Sobrienstatic void
636132718Skando_build_assign_ref (tree fndecl)
63718334Speter{
63818334Speter  tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
63990075Sobrien  tree compound_stmt;
64018334Speter
641169689Skan  compound_stmt = begin_compound_stmt (0);
64218334Speter  parm = convert_from_reference (parm);
64318334Speter
64450397Sobrien  if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
64550397Sobrien      && is_empty_class (current_class_type))
64650397Sobrien    /* Don't copy the padding byte; it might not have been allocated
64750397Sobrien       if *this is a base subobject.  */;
64850397Sobrien  else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
64918334Speter    {
650169689Skan      tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm);
65190075Sobrien      finish_expr_stmt (t);
65218334Speter    }
65318334Speter  else
65418334Speter    {
655117395Skan      tree fields;
65690075Sobrien      int cvquals = cp_type_quals (TREE_TYPE (parm));
65718334Speter      int i;
658169689Skan      tree binfo, base_binfo;
65918334Speter
660119256Skan      /* Assign to each of the direct base classes.  */
661169689Skan      for (binfo = TYPE_BINFO (current_class_type), i = 0;
662169689Skan	   BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
66318334Speter	{
664117395Skan	  tree converted_parm;
66590075Sobrien
666117395Skan	  /* We must convert PARM directly to the base class
667117395Skan	     explicitly since the base class may be ambiguous.  */
668169689Skan	  converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
669117395Skan	  /* Call the base class assignment operator.  */
670169689Skan	  finish_expr_stmt
671169689Skan	    (build_special_member_call (current_class_ref,
672117395Skan					ansi_assopname (NOP_EXPR),
673169689Skan					build_tree_list (NULL_TREE,
674117395Skan							 converted_parm),
675169689Skan					base_binfo,
676117395Skan					LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
67718334Speter	}
678117395Skan
679117395Skan      /* Assign to each of the non-static data members.  */
680169689Skan      for (fields = TYPE_FIELDS (current_class_type);
681169689Skan	   fields;
682117395Skan	   fields = TREE_CHAIN (fields))
68318334Speter	{
684146895Skan	  tree comp = current_class_ref;
685146895Skan	  tree init = parm;
68618334Speter	  tree field = fields;
687146895Skan	  tree expr_type;
688146895Skan	  int quals;
68918334Speter
690117395Skan	  if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
69118334Speter	    continue;
69250397Sobrien
693146895Skan	  expr_type = TREE_TYPE (field);
694169689Skan
695146895Skan	  if (CP_TYPE_CONST_P (expr_type))
69650397Sobrien	    {
697169689Skan	      error ("non-static const member %q#D, can't use default "
698169689Skan		     "assignment operator", field);
69950397Sobrien	      continue;
70050397Sobrien	    }
701146895Skan	  else if (TREE_CODE (expr_type) == REFERENCE_TYPE)
70250397Sobrien	    {
703169689Skan	      error ("non-static reference member %q#D, can't use "
704169689Skan		     "default assignment operator", field);
70550397Sobrien	      continue;
70650397Sobrien	    }
70750397Sobrien
70818334Speter	  if (DECL_NAME (field))
70918334Speter	    {
71018334Speter	      if (VFIELD_NAME_P (DECL_NAME (field)))
71118334Speter		continue;
71218334Speter	    }
713169689Skan	  else if (ANON_AGGR_TYPE_P (expr_type)
714169689Skan		   && TYPE_FIELDS (expr_type) != NULL_TREE)
71590075Sobrien	    /* Just use the field; anonymous types can't have
71690075Sobrien	       nontrivial copy ctors or assignment ops.  */;
71718334Speter	  else
71818334Speter	    continue;
71918334Speter
720169689Skan	  comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE);
72118334Speter
722146895Skan	  /* Compute the type of init->field  */
723146895Skan	  quals = cvquals;
724146895Skan	  if (DECL_MUTABLE_P (field))
725146895Skan	    quals &= ~TYPE_QUAL_CONST;
726146895Skan	  expr_type = cp_build_qualified_type (expr_type, quals);
727146895Skan
728169689Skan	  init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
729169689Skan
73090075Sobrien	  if (DECL_NAME (field))
731146895Skan	    init = build_modify_expr (comp, NOP_EXPR, init);
73290075Sobrien	  else
733169689Skan	    init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
734146895Skan	  finish_expr_stmt (init);
73518334Speter	}
73618334Speter    }
73790075Sobrien  finish_return_stmt (current_class_ref);
738132718Skan  finish_compound_stmt (compound_stmt);
73918334Speter}
74018334Speter
741169689Skan/* Synthesize FNDECL, a non-static member function.   */
742169689Skan
74318334Spetervoid
744132718Skansynthesize_method (tree fndecl)
74518334Speter{
746132718Skan  bool nested = (current_function_decl != NULL_TREE);
74790075Sobrien  tree context = decl_function_context (fndecl);
748132718Skan  bool need_body = true;
74990075Sobrien  tree stmt;
750169689Skan  location_t save_input_location = input_location;
751169689Skan  int error_count = errorcount;
752169689Skan  int warning_count = warningcount;
75318334Speter
754169689Skan  /* Reset the source location, we might have been previously
755169689Skan     deferred, and thus have saved where we were first needed.  */
756169689Skan  DECL_SOURCE_LOCATION (fndecl)
757169689Skan    = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl)));
75890075Sobrien
75990075Sobrien  /* If we've been asked to synthesize a clone, just synthesize the
76090075Sobrien     cloned function instead.  Doing so will automatically fill in the
76190075Sobrien     body for the clone.  */
76290075Sobrien  if (DECL_CLONED_FUNCTION_P (fndecl))
763169689Skan    fndecl = DECL_CLONED_FUNCTION (fndecl);
76460967Sobrien
765132718Skan  /* We may be in the middle of deferred access check.  Disable
766132718Skan     it now.  */
767132718Skan  push_deferring_access_checks (dk_no_deferred);
768132718Skan
76950397Sobrien  if (! context)
77050397Sobrien    push_to_top_level ();
77150397Sobrien  else if (nested)
77290075Sobrien    push_function_context_to (context);
77318334Speter
774169689Skan  input_location = DECL_SOURCE_LOCATION (fndecl);
77590075Sobrien
776169689Skan  start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
77790075Sobrien  stmt = begin_function_body ();
77818334Speter
77990075Sobrien  if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
78018334Speter    {
78190075Sobrien      do_build_assign_ref (fndecl);
782132718Skan      need_body = false;
78390075Sobrien    }
78490075Sobrien  else if (DECL_CONSTRUCTOR_P (fndecl))
78590075Sobrien    {
78690075Sobrien      tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl);
78790075Sobrien      if (arg_chain != void_list_node)
78818334Speter	do_build_copy_constructor (fndecl);
789169689Skan      else
79090075Sobrien	finish_mem_initializers (NULL_TREE);
79118334Speter    }
79218334Speter
79390075Sobrien  /* If we haven't yet generated the body of the function, just
79490075Sobrien     generate an empty compound statement.  */
79590075Sobrien  if (need_body)
79690075Sobrien    {
79790075Sobrien      tree compound_stmt;
798169689Skan      compound_stmt = begin_compound_stmt (BCS_FN_BODY);
799132718Skan      finish_compound_stmt (compound_stmt);
80090075Sobrien    }
80118334Speter
80290075Sobrien  finish_function_body (stmt);
803132718Skan  expand_or_defer_fn (finish_function (0));
80490075Sobrien
805169689Skan  input_location = save_input_location;
806169689Skan
80750397Sobrien  if (! context)
80850397Sobrien    pop_from_top_level ();
80950397Sobrien  else if (nested)
81090075Sobrien    pop_function_context_from (context);
811132718Skan
812132718Skan  pop_deferring_access_checks ();
813169689Skan
814169689Skan  if (error_count != errorcount || warning_count != warningcount)
815169689Skan    inform ("%Hsynthesized method %qD first required here ",
816169689Skan	    &input_location, fndecl);
81718334Speter}
81890075Sobrien
81990075Sobrien/* Use EXTRACTOR to locate the relevant function called for each base &
82090075Sobrien   class field of TYPE. CLIENT allows additional information to be passed
82196263Sobrien   to EXTRACTOR.  Generates the union of all exceptions generated by those
82296263Sobrien   functions.  Note that we haven't updated TYPE_FIELDS and such of any
82396263Sobrien   variants yet, so we need to look at the main one.  */
82490075Sobrien
82590075Sobrienstatic tree
826132718Skansynthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
827169689Skan			   void *client)
82890075Sobrien{
82990075Sobrien  tree raises = empty_except_spec;
83090075Sobrien  tree fields = TYPE_FIELDS (type);
831169689Skan  tree binfo, base_binfo;
832169689Skan  int i;
83396263Sobrien
834169689Skan  for (binfo = TYPE_BINFO (type), i = 0;
835169689Skan       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
83690075Sobrien    {
837169689Skan      tree fn = (*extractor) (BINFO_TYPE (base_binfo), client);
83890075Sobrien      if (fn)
839169689Skan	{
840169689Skan	  tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
841169689Skan
842169689Skan	  raises = merge_exception_specifiers (raises, fn_raises);
843169689Skan	}
84490075Sobrien    }
84590075Sobrien  for (; fields; fields = TREE_CHAIN (fields))
84690075Sobrien    {
84790075Sobrien      tree type = TREE_TYPE (fields);
84890075Sobrien      tree fn;
849169689Skan
850117395Skan      if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
851169689Skan	continue;
85290075Sobrien      while (TREE_CODE (type) == ARRAY_TYPE)
853169689Skan	type = TREE_TYPE (type);
854161651Skan      if (!CLASS_TYPE_P (type))
855169689Skan	continue;
856169689Skan
85790075Sobrien      fn = (*extractor) (type, client);
85890075Sobrien      if (fn)
859169689Skan	{
860169689Skan	  tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
861169689Skan
862169689Skan	  raises = merge_exception_specifiers (raises, fn_raises);
863169689Skan	}
86490075Sobrien    }
86590075Sobrien  return raises;
86690075Sobrien}
86790075Sobrien
86890075Sobrien/* Locate the dtor of TYPE.  */
86990075Sobrien
87090075Sobrienstatic tree
871132718Skanlocate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
87290075Sobrien{
873169689Skan  return CLASSTYPE_DESTRUCTORS (type);
87490075Sobrien}
87590075Sobrien
87690075Sobrien/* Locate the default ctor of TYPE.  */
87790075Sobrien
87890075Sobrienstatic tree
879132718Skanlocate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
88090075Sobrien{
88190075Sobrien  tree fns;
882169689Skan
88390075Sobrien  if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
88490075Sobrien    return NULL_TREE;
885169689Skan
886169689Skan  /* Call lookup_fnfields_1 to create the constructor declarations, if
887169689Skan     necessary.  */
888169689Skan  if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
889169689Skan    return lazily_declare_fn (sfk_constructor, type);
890169689Skan
891169689Skan  for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
89290075Sobrien    {
89390075Sobrien      tree fn = OVL_CURRENT (fns);
89490075Sobrien      tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
895169689Skan
896161651Skan      parms = skip_artificial_parms_for (fn, parms);
897161651Skan
898161651Skan      if (sufficient_parms_p (parms))
899169689Skan	return fn;
90090075Sobrien    }
901169689Skan  gcc_unreachable ();
90290075Sobrien}
90390075Sobrien
90490075Sobrienstruct copy_data
90590075Sobrien{
90690075Sobrien  tree name;
90790075Sobrien  int quals;
90890075Sobrien};
90990075Sobrien
91090075Sobrien/* Locate the copy ctor or copy assignment of TYPE. CLIENT_
91190075Sobrien   points to a COPY_DATA holding the name (NULL for the ctor)
91290075Sobrien   and desired qualifiers of the source operand.  */
91390075Sobrien
91490075Sobrienstatic tree
915132718Skanlocate_copy (tree type, void *client_)
91690075Sobrien{
91790075Sobrien  struct copy_data *client = (struct copy_data *)client_;
91890075Sobrien  tree fns;
91990075Sobrien  tree best = NULL_TREE;
920132718Skan  bool excess_p = false;
921169689Skan
92290075Sobrien  if (client->name)
92390075Sobrien    {
924169689Skan      int ix;
925169689Skan      ix = lookup_fnfields_1 (type, client->name);
926169689Skan      if (ix < 0)
927169689Skan	return NULL_TREE;
928169689Skan      fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
92990075Sobrien    }
93090075Sobrien  else if (TYPE_HAS_INIT_REF (type))
931169689Skan    {
932169689Skan      /* If construction of the copy constructor was postponed, create
933169689Skan	 it now.  */
934169689Skan      if (CLASSTYPE_LAZY_COPY_CTOR (type))
935169689Skan	lazily_declare_fn (sfk_copy_constructor, type);
936169689Skan      fns = CLASSTYPE_CONSTRUCTORS (type);
937169689Skan    }
938169689Skan  else
93990075Sobrien    return NULL_TREE;
94090075Sobrien  for (; fns; fns = OVL_NEXT (fns))
94190075Sobrien    {
94290075Sobrien      tree fn = OVL_CURRENT (fns);
94390075Sobrien      tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
94490075Sobrien      tree src_type;
94590075Sobrien      int excess;
94690075Sobrien      int quals;
947169689Skan
948161651Skan      parms = skip_artificial_parms_for (fn, parms);
94990075Sobrien      if (!parms)
950169689Skan	continue;
951132718Skan      src_type = non_reference (TREE_VALUE (parms));
952169689Skan
953169689Skan      if (src_type == error_mark_node)
954169689Skan        return NULL_TREE;
955169689Skan
95690075Sobrien      if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
957169689Skan	continue;
95890075Sobrien      if (!sufficient_parms_p (TREE_CHAIN (parms)))
959169689Skan	continue;
96090075Sobrien      quals = cp_type_quals (src_type);
96190075Sobrien      if (client->quals & ~quals)
962169689Skan	continue;
96390075Sobrien      excess = quals & ~client->quals;
96490075Sobrien      if (!best || (excess_p && !excess))
965169689Skan	{
966169689Skan	  best = fn;
967169689Skan	  excess_p = excess;
968169689Skan	}
96990075Sobrien      else
970169689Skan	/* Ambiguous */
971169689Skan	return NULL_TREE;
97290075Sobrien    }
97390075Sobrien  return best;
97490075Sobrien}
97590075Sobrien
97690075Sobrien/* Implicitly declare the special function indicated by KIND, as a
97790075Sobrien   member of TYPE.  For copy constructors and assignment operators,
97890075Sobrien   CONST_P indicates whether these functions should take a const
979169689Skan   reference argument or a non-const reference.  Returns the
980169689Skan   FUNCTION_DECL for the implicitly declared function.  */
98190075Sobrien
982169689Skanstatic tree
983132718Skanimplicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
98490075Sobrien{
985169689Skan  tree fn;
986169689Skan  tree parameter_types = void_list_node;
987169689Skan  tree return_type;
988169689Skan  tree fn_type;
98990075Sobrien  tree raises = empty_except_spec;
990169689Skan  tree rhs_parm_type = NULL_TREE;
991169689Skan  tree this_parm;
992169689Skan  tree name;
993169689Skan  HOST_WIDE_INT saved_processing_template_decl;
99490075Sobrien
995169689Skan  /* Because we create declarations for implicitly declared functions
996169689Skan     lazily, we may be creating the declaration for a member of TYPE
997169689Skan     while in some completely different context.  However, TYPE will
998169689Skan     never be a dependent class (because we never want to do lookups
999169689Skan     for implicitly defined functions in a dependent class).
1000169689Skan     Furthermore, we must set PROCESSING_TEMPLATE_DECL to zero here
1001169689Skan     because we only create clones for constructors and destructors
1002169689Skan     when not in a template.  */
1003169689Skan  gcc_assert (!dependent_type_p (type));
1004169689Skan  saved_processing_template_decl = processing_template_decl;
1005169689Skan  processing_template_decl = 0;
1006169689Skan
1007169689Skan  type = TYPE_MAIN_VARIANT (type);
1008169689Skan
1009169689Skan  if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (type))
1010169689Skan    {
1011169689Skan      if (kind == sfk_destructor)
1012169689Skan	/* See comment in check_special_function_return_type.  */
1013169689Skan	return_type = build_pointer_type (void_type_node);
1014169689Skan      else
1015169689Skan	return_type = build_pointer_type (type);
1016169689Skan    }
1017169689Skan  else
1018169689Skan    return_type = void_type_node;
1019169689Skan
102090075Sobrien  switch (kind)
102190075Sobrien    {
102290075Sobrien    case sfk_destructor:
102390075Sobrien      /* Destructor.  */
1024169689Skan      name = constructor_name (type);
102590075Sobrien      raises = synthesize_exception_spec (type, &locate_dtor, 0);
102690075Sobrien      break;
102790075Sobrien
102890075Sobrien    case sfk_constructor:
102990075Sobrien      /* Default constructor.  */
1030169689Skan      name = constructor_name (type);
103190075Sobrien      raises = synthesize_exception_spec (type, &locate_ctor, 0);
103290075Sobrien      break;
103390075Sobrien
103490075Sobrien    case sfk_copy_constructor:
103590075Sobrien    case sfk_assignment_operator:
103690075Sobrien    {
103790075Sobrien      struct copy_data data;
1038169689Skan
103990075Sobrien      data.name = NULL;
104090075Sobrien      data.quals = 0;
104190075Sobrien      if (kind == sfk_assignment_operator)
1042169689Skan	{
1043169689Skan	  return_type = build_reference_type (type);
1044169689Skan	  name = ansi_assopname (NOP_EXPR);
1045169689Skan	  data.name = name;
1046169689Skan	}
1047169689Skan      else
1048169689Skan	name = constructor_name (type);
104990075Sobrien
105090075Sobrien      if (const_p)
1051169689Skan	{
1052169689Skan	  data.quals = TYPE_QUAL_CONST;
1053169689Skan	  rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST);
1054169689Skan	}
1055169689Skan      else
1056169689Skan	rhs_parm_type = type;
1057169689Skan      rhs_parm_type = build_reference_type (rhs_parm_type);
1058169689Skan      parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types);
105990075Sobrien      raises = synthesize_exception_spec (type, &locate_copy, &data);
106090075Sobrien      break;
106190075Sobrien    }
106290075Sobrien    default:
1063169689Skan      gcc_unreachable ();
106490075Sobrien    }
106590075Sobrien
1066169689Skan  /* Create the function.  */
1067169689Skan  fn_type = build_method_type_directly (type, return_type, parameter_types);
1068169689Skan  if (raises)
1069169689Skan    fn_type = build_exception_variant (fn_type, raises);
1070169689Skan  fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
1071169689Skan  DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type));
1072169689Skan  if (kind == sfk_constructor || kind == sfk_copy_constructor)
1073169689Skan    DECL_CONSTRUCTOR_P (fn) = 1;
1074169689Skan  else if (kind == sfk_destructor)
1075169689Skan    DECL_DESTRUCTOR_P (fn) = 1;
1076169689Skan  else
1077169689Skan    {
1078169689Skan      DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
1079169689Skan      SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
1080169689Skan    }
1081169689Skan  /* Create the explicit arguments.  */
1082169689Skan  if (rhs_parm_type)
1083169689Skan    {
1084169689Skan      /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we
1085169689Skan	 want its type to be included in the mangled function
1086169689Skan	 name.  */
1087169689Skan      DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
1088169689Skan      TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
1089169689Skan    }
1090169689Skan  /* Add the "this" parameter.  */
1091169689Skan  this_parm = build_this_parm (fn_type, TYPE_UNQUALIFIED);
1092169689Skan  TREE_CHAIN (this_parm) = DECL_ARGUMENTS (fn);
1093169689Skan  DECL_ARGUMENTS (fn) = this_parm;
109490075Sobrien
1095169689Skan  grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL);
1096169689Skan  set_linkage_according_to_type (type, fn);
1097169689Skan  rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
1098169689Skan  DECL_IN_AGGR_P (fn) = 1;
109990075Sobrien  DECL_ARTIFICIAL (fn) = 1;
110090075Sobrien  DECL_NOT_REALLY_EXTERN (fn) = 1;
110190075Sobrien  DECL_DECLARED_INLINE_P (fn) = 1;
110290075Sobrien  DECL_INLINE (fn) = 1;
1103169689Skan  gcc_assert (!TREE_USED (fn));
1104169689Skan
1105169689Skan  /* Restore PROCESSING_TEMPLATE_DECL.  */
1106169689Skan  processing_template_decl = saved_processing_template_decl;
1107169689Skan
110890075Sobrien  return fn;
110990075Sobrien}
111090075Sobrien
1111169689Skan/* Add an implicit declaration to TYPE for the kind of function
1112169689Skan   indicated by SFK.  Return the FUNCTION_DECL for the new implicit
1113169689Skan   declaration.  */
1114169689Skan
1115169689Skantree
1116169689Skanlazily_declare_fn (special_function_kind sfk, tree type)
1117169689Skan{
1118169689Skan  tree fn;
1119169689Skan  bool const_p;
1120169689Skan
1121169689Skan  /* Figure out whether or not the argument has a const reference
1122169689Skan     type.  */
1123169689Skan  if (sfk == sfk_copy_constructor)
1124169689Skan    const_p = TYPE_HAS_CONST_INIT_REF (type);
1125169689Skan  else if (sfk == sfk_assignment_operator)
1126169689Skan    const_p = TYPE_HAS_CONST_ASSIGN_REF (type);
1127169689Skan  else
1128169689Skan    /* In this case, CONST_P will be ignored.  */
1129169689Skan    const_p = false;
1130169689Skan  /* Declare the function.  */
1131169689Skan  fn = implicitly_declare_fn (sfk, type, const_p);
1132169689Skan  /* A destructor may be virtual.  */
1133169689Skan  if (sfk == sfk_destructor)
1134169689Skan    check_for_override (fn, type);
1135169689Skan  /* Add it to CLASSTYPE_METHOD_VEC.  */
1136169689Skan  add_method (type, fn, NULL_TREE);
1137169689Skan  /* Add it to TYPE_METHODS.  */
1138169689Skan  if (sfk == sfk_destructor
1139169689Skan      && DECL_VIRTUAL_P (fn)
1140169689Skan      && abi_version_at_least (2))
1141169689Skan    /* The ABI requires that a virtual destructor go at the end of the
1142169689Skan       vtable.  */
1143169689Skan    TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn);
1144169689Skan  else
1145169689Skan    {
1146169689Skan      /* G++ 3.2 put the implicit destructor at the *beginning* of the
1147169689Skan	 TYPE_METHODS list, which cause the destructor to be emitted
1148169689Skan	 in an incorrect location in the vtable.  */
1149169689Skan      if (warn_abi && DECL_VIRTUAL_P (fn))
1150169689Skan	warning (OPT_Wabi, "vtable layout for class %qT may not be ABI-compliant"
1151169689Skan		 "and may change in a future version of GCC due to "
1152169689Skan		 "implicit virtual destructor",
1153169689Skan		 type);
1154169689Skan      TREE_CHAIN (fn) = TYPE_METHODS (type);
1155169689Skan      TYPE_METHODS (type) = fn;
1156169689Skan    }
1157169689Skan  maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0);
1158169689Skan  if (sfk == sfk_assignment_operator)
1159169689Skan    CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0;
1160169689Skan  else
1161169689Skan    {
1162169689Skan      /* Remember that the function has been created.  */
1163169689Skan      if (sfk == sfk_constructor)
1164169689Skan	CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0;
1165169689Skan      else if (sfk == sfk_copy_constructor)
1166169689Skan	CLASSTYPE_LAZY_COPY_CTOR (type) = 0;
1167169689Skan      else if (sfk == sfk_destructor)
1168169689Skan	CLASSTYPE_LAZY_DESTRUCTOR (type) = 0;
1169169689Skan      /* Create appropriate clones.  */
1170169689Skan      clone_function_decl (fn, /*update_method_vec=*/true);
1171169689Skan    }
1172169689Skan
1173169689Skan  return fn;
1174169689Skan}
1175169689Skan
117690075Sobrien/* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST
117790075Sobrien   as there are artificial parms in FN.  */
117890075Sobrien
117990075Sobrientree
1180132718Skanskip_artificial_parms_for (tree fn, tree list)
118190075Sobrien{
118290075Sobrien  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
118390075Sobrien    list = TREE_CHAIN (list);
118490075Sobrien  else
118590075Sobrien    return list;
118690075Sobrien
118790075Sobrien  if (DECL_HAS_IN_CHARGE_PARM_P (fn))
118890075Sobrien    list = TREE_CHAIN (list);
118990075Sobrien  if (DECL_HAS_VTT_PARM_P (fn))
119090075Sobrien    list = TREE_CHAIN (list);
119190075Sobrien  return list;
119290075Sobrien}
1193132718Skan
1194132718Skan#include "gt-cp-method.h"
1195