OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [cp/] [method.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Handle the hair of processing (but not expanding) inline functions.
2
   Also manage function and variable name overloading.
3
   Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4
   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
5
   Contributed by Michael Tiemann (tiemann@cygnus.com)
6
 
7
This file is part of GCC.
8
 
9
GCC is free software; you can redistribute it and/or modify
10
it under the terms of the GNU General Public License as published by
11
the Free Software Foundation; either version 2, or (at your option)
12
any later version.
13
 
14
GCC is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
GNU General Public License for more details.
18
 
19
You should have received a copy of the GNU General Public License
20
along with GCC; see the file COPYING.  If not, write to
21
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22
Boston, MA 02110-1301, USA.  */
23
 
24
 
25
/* Handle method declarations.  */
26
#include "config.h"
27
#include "system.h"
28
#include "coretypes.h"
29
#include "tm.h"
30
#include "tree.h"
31
#include "cp-tree.h"
32
#include "rtl.h"
33
#include "expr.h"
34
#include "output.h"
35
#include "flags.h"
36
#include "toplev.h"
37
#include "tm_p.h"
38
#include "target.h"
39
#include "tree-pass.h"
40
#include "diagnostic.h"
41
 
42
/* Various flags to control the mangling process.  */
43
 
44
enum mangling_flags
45
{
46
  /* No flags.  */
47
  mf_none = 0,
48
  /* The thing we are presently mangling is part of a template type,
49
     rather than a fully instantiated type.  Therefore, we may see
50
     complex expressions where we would normally expect to see a
51
     simple integer constant.  */
52
  mf_maybe_uninstantiated = 1,
53
  /* When mangling a numeric value, use the form `_XX_' (instead of
54
     just `XX') if the value has more than one digit.  */
55
  mf_use_underscores_around_value = 2
56
};
57
 
58
typedef enum mangling_flags mangling_flags;
59
 
60
static tree thunk_adjust (tree, bool, HOST_WIDE_INT, tree);
61
static void do_build_assign_ref (tree);
62
static void do_build_copy_constructor (tree);
63
static tree synthesize_exception_spec (tree, tree (*) (tree, void *), void *);
64
static tree locate_dtor (tree, void *);
65
static tree locate_ctor (tree, void *);
66
static tree locate_copy (tree, void *);
67
static tree make_alias_for_thunk (tree);
68
 
69
/* Called once to initialize method.c.  */
70
 
71
void
72
init_method (void)
73
{
74
  init_mangle ();
75
}
76
 
77
/* Return a this or result adjusting thunk to FUNCTION.  THIS_ADJUSTING
78
   indicates whether it is a this or result adjusting thunk.
79
   FIXED_OFFSET and VIRTUAL_OFFSET indicate how to do the adjustment
80
   (see thunk_adjust).  VIRTUAL_OFFSET can be NULL, but FIXED_OFFSET
81
   never is.  VIRTUAL_OFFSET is the /index/ into the vtable for this
82
   adjusting thunks, we scale it to a byte offset. For covariant
83
   thunks VIRTUAL_OFFSET is the virtual binfo.  You must post process
84
   the returned thunk with finish_thunk.  */
85
 
86
tree
87
make_thunk (tree function, bool this_adjusting,
88
            tree fixed_offset, tree virtual_offset)
89
{
90
  HOST_WIDE_INT d;
91
  tree thunk;
92
 
93
  gcc_assert (TREE_CODE (function) == FUNCTION_DECL);
94
  /* We can have this thunks to covariant thunks, but not vice versa.  */
95
  gcc_assert (!DECL_THIS_THUNK_P (function));
96
  gcc_assert (!DECL_RESULT_THUNK_P (function) || this_adjusting);
97
 
98
  /* Scale the VIRTUAL_OFFSET to be in terms of bytes.  */
99
  if (this_adjusting && virtual_offset)
100
    virtual_offset
101
      = size_binop (MULT_EXPR,
102
                    virtual_offset,
103
                    convert (ssizetype,
104
                             TYPE_SIZE_UNIT (vtable_entry_type)));
105
 
106
  d = tree_low_cst (fixed_offset, 0);
107
 
108
  /* See if we already have the thunk in question.  For this_adjusting
109
     thunks VIRTUAL_OFFSET will be an INTEGER_CST, for covariant thunks it
110
     will be a BINFO.  */
111
  for (thunk = DECL_THUNKS (function); thunk; thunk = TREE_CHAIN (thunk))
112
    if (DECL_THIS_THUNK_P (thunk) == this_adjusting
113
        && THUNK_FIXED_OFFSET (thunk) == d
114
        && !virtual_offset == !THUNK_VIRTUAL_OFFSET (thunk)
115
        && (!virtual_offset
116
            || (this_adjusting
117
                ? tree_int_cst_equal (THUNK_VIRTUAL_OFFSET (thunk),
118
                                      virtual_offset)
119
                : THUNK_VIRTUAL_OFFSET (thunk) == virtual_offset)))
120
      return thunk;
121
 
122
  /* All thunks must be created before FUNCTION is actually emitted;
123
     the ABI requires that all thunks be emitted together with the
124
     function to which they transfer control.  */
125
  gcc_assert (!TREE_ASM_WRITTEN (function));
126
  /* Likewise, we can only be adding thunks to a function declared in
127
     the class currently being laid out.  */
128
  gcc_assert (TYPE_SIZE (DECL_CONTEXT (function))
129
              && TYPE_BEING_DEFINED (DECL_CONTEXT (function)));
130
 
131
  thunk = build_decl (FUNCTION_DECL, NULL_TREE, TREE_TYPE (function));
132
  DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function);
133
  cxx_dup_lang_specific_decl (thunk);
134
  DECL_THUNKS (thunk) = NULL_TREE;
135
 
136
  DECL_CONTEXT (thunk) = DECL_CONTEXT (function);
137
  TREE_READONLY (thunk) = TREE_READONLY (function);
138
  TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (function);
139
  TREE_PUBLIC (thunk) = TREE_PUBLIC (function);
140
  if (flag_weak)
141
    comdat_linkage (thunk);
142
  SET_DECL_THUNK_P (thunk, this_adjusting);
143
  THUNK_TARGET (thunk) = function;
144
  THUNK_FIXED_OFFSET (thunk) = d;
145
  THUNK_VIRTUAL_OFFSET (thunk) = virtual_offset;
146
  THUNK_ALIAS (thunk) = NULL_TREE;
147
 
148
  /* The thunk itself is not a constructor or destructor, even if
149
     the thing it is thunking to is.  */
150
  DECL_INTERFACE_KNOWN (thunk) = 1;
151
  DECL_NOT_REALLY_EXTERN (thunk) = 1;
152
  DECL_SAVED_FUNCTION_DATA (thunk) = NULL;
153
  DECL_DESTRUCTOR_P (thunk) = 0;
154
  DECL_CONSTRUCTOR_P (thunk) = 0;
155
  DECL_EXTERNAL (thunk) = 1;
156
  DECL_ARTIFICIAL (thunk) = 1;
157
  /* Even if this thunk is a member of a local class, we don't
158
     need a static chain.  */
159
  DECL_NO_STATIC_CHAIN (thunk) = 1;
160
  /* The THUNK is not a pending inline, even if the FUNCTION is.  */
161
  DECL_PENDING_INLINE_P (thunk) = 0;
162
  DECL_INLINE (thunk) = 0;
163
  DECL_DECLARED_INLINE_P (thunk) = 0;
164
  /* Nor has it been deferred.  */
165
  DECL_DEFERRED_FN (thunk) = 0;
166
 
167
  /* Add it to the list of thunks associated with FUNCTION.  */
168
  TREE_CHAIN (thunk) = DECL_THUNKS (function);
169
  DECL_THUNKS (function) = thunk;
170
 
171
  return thunk;
172
}
173
 
174
/* Finish THUNK, a thunk decl.  */
175
 
176
void
177
finish_thunk (tree thunk)
178
{
179
  tree function, name;
180
  tree fixed_offset = ssize_int (THUNK_FIXED_OFFSET (thunk));
181
  tree virtual_offset = THUNK_VIRTUAL_OFFSET (thunk);
182
 
183
  gcc_assert (!DECL_NAME (thunk) && DECL_THUNK_P (thunk));
184
  if (virtual_offset && DECL_RESULT_THUNK_P (thunk))
185
    virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
186
  function = THUNK_TARGET (thunk);
187
  name = mangle_thunk (function, DECL_THIS_THUNK_P (thunk),
188
                       fixed_offset, virtual_offset);
189
 
190
  /* We can end up with declarations of (logically) different
191
     covariant thunks, that do identical adjustments.  The two thunks
192
     will be adjusting between within different hierarchies, which
193
     happen to have the same layout.  We must nullify one of them to
194
     refer to the other.  */
195
  if (DECL_RESULT_THUNK_P (thunk))
196
    {
197
      tree cov_probe;
198
 
199
      for (cov_probe = DECL_THUNKS (function);
200
           cov_probe; cov_probe = TREE_CHAIN (cov_probe))
201
        if (DECL_NAME (cov_probe) == name)
202
          {
203
            gcc_assert (!DECL_THUNKS (thunk));
204
            THUNK_ALIAS (thunk) = (THUNK_ALIAS (cov_probe)
205
                                   ? THUNK_ALIAS (cov_probe) : cov_probe);
206
            break;
207
          }
208
    }
209
 
210
  DECL_NAME (thunk) = name;
211
  SET_DECL_ASSEMBLER_NAME (thunk, name);
212
}
213
 
214
/* Adjust PTR by the constant FIXED_OFFSET, and by the vtable
215
   offset indicated by VIRTUAL_OFFSET, if that is
216
   non-null. THIS_ADJUSTING is nonzero for a this adjusting thunk and
217
   zero for a result adjusting thunk.  */
218
 
219
static tree
220
thunk_adjust (tree ptr, bool this_adjusting,
221
              HOST_WIDE_INT fixed_offset, tree virtual_offset)
222
{
223
  if (this_adjusting)
224
    /* Adjust the pointer by the constant.  */
225
    ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr,
226
                       ssize_int (fixed_offset));
227
 
228
  /* If there's a virtual offset, look up that value in the vtable and
229
     adjust the pointer again.  */
230
  if (virtual_offset)
231
    {
232
      tree vtable;
233
 
234
      ptr = save_expr (ptr);
235
      /* The vptr is always at offset zero in the object.  */
236
      vtable = build1 (NOP_EXPR,
237
                       build_pointer_type (build_pointer_type
238
                                           (vtable_entry_type)),
239
                       ptr);
240
      /* Form the vtable address.  */
241
      vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
242
      /* Find the entry with the vcall offset.  */
243
      vtable = build2 (PLUS_EXPR, TREE_TYPE (vtable), vtable, virtual_offset);
244
      /* Get the offset itself.  */
245
      vtable = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (vtable)), vtable);
246
      /* Adjust the `this' pointer.  */
247
      ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr, vtable);
248
    }
249
 
250
  if (!this_adjusting)
251
    /* Adjust the pointer by the constant.  */
252
    ptr = fold_build2 (PLUS_EXPR, TREE_TYPE (ptr), ptr,
253
                       ssize_int (fixed_offset));
254
 
255
  return ptr;
256
}
257
 
258
static GTY (()) int thunk_labelno;
259
 
260
/* Create a static alias to function.  */
261
 
262
tree
263
make_alias_for (tree function, tree newid)
264
{
265
  tree alias = build_decl (FUNCTION_DECL, newid, TREE_TYPE (function));
266
  DECL_LANG_SPECIFIC (alias) = DECL_LANG_SPECIFIC (function);
267
  cxx_dup_lang_specific_decl (alias);
268
  DECL_CONTEXT (alias) = NULL;
269
  TREE_READONLY (alias) = TREE_READONLY (function);
270
  TREE_THIS_VOLATILE (alias) = TREE_THIS_VOLATILE (function);
271
  TREE_PUBLIC (alias) = 0;
272
  DECL_INTERFACE_KNOWN (alias) = 1;
273
  DECL_NOT_REALLY_EXTERN (alias) = 1;
274
  DECL_THIS_STATIC (alias) = 1;
275
  DECL_SAVED_FUNCTION_DATA (alias) = NULL;
276
  DECL_DESTRUCTOR_P (alias) = 0;
277
  DECL_CONSTRUCTOR_P (alias) = 0;
278
  DECL_CLONED_FUNCTION (alias) = NULL_TREE;
279
  DECL_EXTERNAL (alias) = 0;
280
  DECL_ARTIFICIAL (alias) = 1;
281
  DECL_NO_STATIC_CHAIN (alias) = 1;
282
  DECL_PENDING_INLINE_P (alias) = 0;
283
  DECL_INLINE (alias) = 0;
284
  DECL_DECLARED_INLINE_P (alias) = 0;
285
  DECL_DEFERRED_FN (alias) = 0;
286
  DECL_USE_TEMPLATE (alias) = 0;
287
  DECL_TEMPLATE_INSTANTIATED (alias) = 0;
288
  DECL_TEMPLATE_INFO (alias) = NULL;
289
  DECL_INITIAL (alias) = error_mark_node;
290
  TREE_ADDRESSABLE (alias) = 1;
291
  TREE_USED (alias) = 1;
292
  SET_DECL_ASSEMBLER_NAME (alias, DECL_NAME (alias));
293
  TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias)) = 1;
294
  return alias;
295
}
296
 
297
static tree
298
make_alias_for_thunk (tree function)
299
{
300
  tree alias;
301
  char buf[256];
302
 
303
  ASM_GENERATE_INTERNAL_LABEL (buf, "LTHUNK", thunk_labelno);
304
  thunk_labelno++;
305
 
306
  alias = make_alias_for (function, get_identifier (buf));
307
 
308
  if (!flag_syntax_only)
309
    assemble_alias (alias, DECL_ASSEMBLER_NAME (function));
310
 
311
  return alias;
312
}
313
 
314
/* Emit the definition of a C++ multiple inheritance or covariant
315
   return vtable thunk.  If EMIT_P is nonzero, the thunk is emitted
316
   immediately.  */
317
 
318
void
319
use_thunk (tree thunk_fndecl, bool emit_p)
320
{
321
  tree a, t, function, alias;
322
  tree virtual_offset;
323
  HOST_WIDE_INT fixed_offset, virtual_value;
324
  bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl);
325
 
326
  /* We should have called finish_thunk to give it a name.  */
327
  gcc_assert (DECL_NAME (thunk_fndecl));
328
 
329
  /* We should never be using an alias, always refer to the
330
     aliased thunk.  */
331
  gcc_assert (!THUNK_ALIAS (thunk_fndecl));
332
 
333
  if (TREE_ASM_WRITTEN (thunk_fndecl))
334
    return;
335
 
336
  function = THUNK_TARGET (thunk_fndecl);
337
  if (DECL_RESULT (thunk_fndecl))
338
    /* We already turned this thunk into an ordinary function.
339
       There's no need to process this thunk again.  */
340
    return;
341
 
342
  if (DECL_THUNK_P (function))
343
    /* The target is itself a thunk, process it now.  */
344
    use_thunk (function, emit_p);
345
 
346
  /* Thunks are always addressable; they only appear in vtables.  */
347
  TREE_ADDRESSABLE (thunk_fndecl) = 1;
348
 
349
  /* Figure out what function is being thunked to.  It's referenced in
350
     this translation unit.  */
351
  TREE_ADDRESSABLE (function) = 1;
352
  mark_used (function);
353
  if (!emit_p)
354
    return;
355
 
356
  if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function))
357
   alias = make_alias_for_thunk (function);
358
  else
359
   alias = function;
360
 
361
  fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl);
362
  virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl);
363
 
364
  if (virtual_offset)
365
    {
366
      if (!this_adjusting)
367
        virtual_offset = BINFO_VPTR_FIELD (virtual_offset);
368
      virtual_value = tree_low_cst (virtual_offset, /*pos=*/0);
369
      gcc_assert (virtual_value);
370
    }
371
  else
372
    virtual_value = 0;
373
 
374
  /* And, if we need to emit the thunk, it's used.  */
375
  mark_used (thunk_fndecl);
376
  /* This thunk is actually defined.  */
377
  DECL_EXTERNAL (thunk_fndecl) = 0;
378
  /* The linkage of the function may have changed.  FIXME in linkage
379
     rewrite.  */
380
  TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function);
381
  DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function);
382
  DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
383
    = DECL_VISIBILITY_SPECIFIED (function);
384
  if (flag_weak && TREE_PUBLIC (thunk_fndecl))
385
    comdat_linkage (thunk_fndecl);
386
 
387
  if (flag_syntax_only)
388
    {
389
      TREE_ASM_WRITTEN (thunk_fndecl) = 1;
390
      return;
391
    }
392
 
393
  push_to_top_level ();
394
 
395
  if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)
396
      && targetm.have_named_sections)
397
    {
398
      resolve_unique_section (function, 0, flag_function_sections);
399
 
400
      if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function))
401
        {
402
          resolve_unique_section (thunk_fndecl, 0, flag_function_sections);
403
 
404
          /* Output the thunk into the same section as function.  */
405
          DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function);
406
        }
407
    }
408
 
409
  /* The back-end expects DECL_INITIAL to contain a BLOCK, so we
410
     create one.  */
411
  DECL_INITIAL (thunk_fndecl) = make_node (BLOCK);
412
 
413
  /* Set up cloned argument trees for the thunk.  */
414
  t = NULL_TREE;
415
  for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a))
416
    {
417
      tree x = copy_node (a);
418
      TREE_CHAIN (x) = t;
419
      DECL_CONTEXT (x) = thunk_fndecl;
420
      SET_DECL_RTL (x, NULL_RTX);
421
      t = x;
422
    }
423
  a = nreverse (t);
424
  DECL_ARGUMENTS (thunk_fndecl) = a;
425
  BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a;
426
 
427
  if (this_adjusting
428
      && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
429
                                              virtual_value, alias))
430
    {
431
      const char *fnname;
432
      current_function_decl = thunk_fndecl;
433
      DECL_RESULT (thunk_fndecl)
434
        = build_decl (RESULT_DECL, 0, integer_type_node);
435
      fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0);
436
      init_function_start (thunk_fndecl);
437
      current_function_is_thunk = 1;
438
      assemble_start_function (thunk_fndecl, fnname);
439
 
440
      targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl,
441
                                       fixed_offset, virtual_value, alias);
442
 
443
      assemble_end_function (thunk_fndecl, fnname);
444
      init_insn_lengths ();
445
      current_function_decl = 0;
446
      cfun = 0;
447
      TREE_ASM_WRITTEN (thunk_fndecl) = 1;
448
    }
449
  else
450
    {
451
      /* If this is a covariant thunk, or we don't have the necessary
452
         code for efficient thunks, generate a thunk function that
453
         just makes a call to the real function.  Unfortunately, this
454
         doesn't work for varargs.  */
455
 
456
      if (varargs_function_p (function))
457
        error ("generic thunk code fails for method %q#D which uses %<...%>",
458
               function);
459
 
460
      DECL_RESULT (thunk_fndecl) = NULL_TREE;
461
 
462
      start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED);
463
      /* We don't bother with a body block for thunks.  */
464
 
465
      /* There's no need to check accessibility inside the thunk body.  */
466
      push_deferring_access_checks (dk_no_check);
467
 
468
      t = a;
469
      if (this_adjusting)
470
        t = thunk_adjust (t, /*this_adjusting=*/1,
471
                          fixed_offset, virtual_offset);
472
 
473
      /* Build up the call to the real function.  */
474
      t = tree_cons (NULL_TREE, t, NULL_TREE);
475
      for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a))
476
        t = tree_cons (NULL_TREE, a, t);
477
      t = nreverse (t);
478
      t = build_call (alias, t);
479
      CALL_FROM_THUNK_P (t) = 1;
480
 
481
      if (VOID_TYPE_P (TREE_TYPE (t)))
482
        finish_expr_stmt (t);
483
      else
484
        {
485
          if (!this_adjusting)
486
            {
487
              tree cond = NULL_TREE;
488
 
489
              if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
490
                {
491
                  /* If the return type is a pointer, we need to
492
                     protect against NULL.  We know there will be an
493
                     adjustment, because that's why we're emitting a
494
                     thunk.  */
495
                  t = save_expr (t);
496
                  cond = cp_convert (boolean_type_node, t);
497
                }
498
 
499
              t = thunk_adjust (t, /*this_adjusting=*/0,
500
                                fixed_offset, virtual_offset);
501
              if (cond)
502
                t = build3 (COND_EXPR, TREE_TYPE (t), cond, t,
503
                            cp_convert (TREE_TYPE (t), integer_zero_node));
504
            }
505
          if (IS_AGGR_TYPE (TREE_TYPE (t)))
506
            t = build_cplus_new (TREE_TYPE (t), t);
507
          finish_return_stmt (t);
508
        }
509
 
510
      /* Since we want to emit the thunk, we explicitly mark its name as
511
         referenced.  */
512
      mark_decl_referenced (thunk_fndecl);
513
 
514
      /* But we don't want debugging information about it.  */
515
      DECL_IGNORED_P (thunk_fndecl) = 1;
516
 
517
      /* Re-enable access control.  */
518
      pop_deferring_access_checks ();
519
 
520
      thunk_fndecl = finish_function (0);
521
      tree_lowering_passes (thunk_fndecl);
522
      expand_body (thunk_fndecl);
523
    }
524
 
525
  pop_from_top_level ();
526
}
527
 
528
/* Code for synthesizing methods which have default semantics defined.  */
529
 
530
/* Generate code for default X(X&) constructor.  */
531
 
532
static void
533
do_build_copy_constructor (tree fndecl)
534
{
535
  tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
536
 
537
  parm = convert_from_reference (parm);
538
 
539
  if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)
540
      && is_empty_class (current_class_type))
541
    /* Don't copy the padding byte; it might not have been allocated
542
       if *this is a base subobject.  */;
543
  else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
544
    {
545
      tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
546
      finish_expr_stmt (t);
547
    }
548
  else
549
    {
550
      tree fields = TYPE_FIELDS (current_class_type);
551
      tree member_init_list = NULL_TREE;
552
      int cvquals = cp_type_quals (TREE_TYPE (parm));
553
      int i;
554
      tree binfo, base_binfo;
555
      VEC(tree,gc) *vbases;
556
 
557
      /* Initialize all the base-classes with the parameter converted
558
         to their type so that we get their copy constructor and not
559
         another constructor that takes current_class_type.  We must
560
         deal with the binfo's directly as a direct base might be
561
         inaccessible due to ambiguity.  */
562
      for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0;
563
           VEC_iterate (tree, vbases, i, binfo); i++)
564
        {
565
          member_init_list
566
            = tree_cons (binfo,
567
                         build_tree_list (NULL_TREE,
568
                                          build_base_path (PLUS_EXPR, parm,
569
                                                           binfo, 1)),
570
                         member_init_list);
571
        }
572
 
573
      for (binfo = TYPE_BINFO (current_class_type), i = 0;
574
           BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
575
        {
576
          if (BINFO_VIRTUAL_P (base_binfo))
577
            continue;
578
 
579
          member_init_list
580
            = tree_cons (base_binfo,
581
                         build_tree_list (NULL_TREE,
582
                                          build_base_path (PLUS_EXPR, parm,
583
                                                           base_binfo, 1)),
584
                         member_init_list);
585
        }
586
 
587
      for (; fields; fields = TREE_CHAIN (fields))
588
        {
589
          tree init = parm;
590
          tree field = fields;
591
          tree expr_type;
592
 
593
          if (TREE_CODE (field) != FIELD_DECL)
594
            continue;
595
 
596
          expr_type = TREE_TYPE (field);
597
          if (DECL_NAME (field))
598
            {
599
              if (VFIELD_NAME_P (DECL_NAME (field)))
600
                continue;
601
            }
602
          else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
603
            /* Just use the field; anonymous types can't have
604
               nontrivial copy ctors or assignment ops.  */;
605
          else
606
            continue;
607
 
608
          /* Compute the type of "init->field".  If the copy-constructor
609
             parameter is, for example, "const S&", and the type of
610
             the field is "T", then the type will usually be "const
611
             T".  (There are no cv-qualified variants of reference
612
             types.)  */
613
          if (TREE_CODE (expr_type) != REFERENCE_TYPE)
614
            {
615
              int quals = cvquals;
616
 
617
              if (DECL_MUTABLE_P (field))
618
                quals &= ~TYPE_QUAL_CONST;
619
              expr_type = cp_build_qualified_type (expr_type, quals);
620
            }
621
 
622
          init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
623
          init = build_tree_list (NULL_TREE, init);
624
 
625
          member_init_list = tree_cons (field, init, member_init_list);
626
        }
627
      finish_mem_initializers (member_init_list);
628
    }
629
}
630
 
631
static void
632
do_build_assign_ref (tree fndecl)
633
{
634
  tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
635
  tree compound_stmt;
636
 
637
  compound_stmt = begin_compound_stmt (0);
638
  parm = convert_from_reference (parm);
639
 
640
  if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
641
      && is_empty_class (current_class_type))
642
    /* Don't copy the padding byte; it might not have been allocated
643
       if *this is a base subobject.  */;
644
  else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type))
645
    {
646
      tree t = build2 (MODIFY_EXPR, void_type_node, current_class_ref, parm);
647
      finish_expr_stmt (t);
648
    }
649
  else
650
    {
651
      tree fields;
652
      int cvquals = cp_type_quals (TREE_TYPE (parm));
653
      int i;
654
      tree binfo, base_binfo;
655
 
656
      /* Assign to each of the direct base classes.  */
657
      for (binfo = TYPE_BINFO (current_class_type), i = 0;
658
           BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
659
        {
660
          tree converted_parm;
661
 
662
          /* We must convert PARM directly to the base class
663
             explicitly since the base class may be ambiguous.  */
664
          converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
665
          /* Call the base class assignment operator.  */
666
          finish_expr_stmt
667
            (build_special_member_call (current_class_ref,
668
                                        ansi_assopname (NOP_EXPR),
669
                                        build_tree_list (NULL_TREE,
670
                                                         converted_parm),
671
                                        base_binfo,
672
                                        LOOKUP_NORMAL | LOOKUP_NONVIRTUAL));
673
        }
674
 
675
      /* Assign to each of the non-static data members.  */
676
      for (fields = TYPE_FIELDS (current_class_type);
677
           fields;
678
           fields = TREE_CHAIN (fields))
679
        {
680
          tree comp = current_class_ref;
681
          tree init = parm;
682
          tree field = fields;
683
          tree expr_type;
684
          int quals;
685
 
686
          if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
687
            continue;
688
 
689
          expr_type = TREE_TYPE (field);
690
 
691
          if (CP_TYPE_CONST_P (expr_type))
692
            {
693
              error ("non-static const member %q#D, can't use default "
694
                     "assignment operator", field);
695
              continue;
696
            }
697
          else if (TREE_CODE (expr_type) == REFERENCE_TYPE)
698
            {
699
              error ("non-static reference member %q#D, can't use "
700
                     "default assignment operator", field);
701
              continue;
702
            }
703
 
704
          if (DECL_NAME (field))
705
            {
706
              if (VFIELD_NAME_P (DECL_NAME (field)))
707
                continue;
708
            }
709
          else if (ANON_AGGR_TYPE_P (expr_type)
710
                   && TYPE_FIELDS (expr_type) != NULL_TREE)
711
            /* Just use the field; anonymous types can't have
712
               nontrivial copy ctors or assignment ops.  */;
713
          else
714
            continue;
715
 
716
          comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE);
717
 
718
          /* Compute the type of init->field  */
719
          quals = cvquals;
720
          if (DECL_MUTABLE_P (field))
721
            quals &= ~TYPE_QUAL_CONST;
722
          expr_type = cp_build_qualified_type (expr_type, quals);
723
 
724
          init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
725
 
726
          if (DECL_NAME (field))
727
            init = build_modify_expr (comp, NOP_EXPR, init);
728
          else
729
            init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
730
          finish_expr_stmt (init);
731
        }
732
    }
733
  finish_return_stmt (current_class_ref);
734
  finish_compound_stmt (compound_stmt);
735
}
736
 
737
/* Synthesize FNDECL, a non-static member function.   */
738
 
739
void
740
synthesize_method (tree fndecl)
741
{
742
  bool nested = (current_function_decl != NULL_TREE);
743
  tree context = decl_function_context (fndecl);
744
  bool need_body = true;
745
  tree stmt;
746
  location_t save_input_location = input_location;
747
  int error_count = errorcount;
748
  int warning_count = warningcount;
749
 
750
  /* Reset the source location, we might have been previously
751
     deferred, and thus have saved where we were first needed.  */
752
  DECL_SOURCE_LOCATION (fndecl)
753
    = DECL_SOURCE_LOCATION (TYPE_NAME (DECL_CONTEXT (fndecl)));
754
 
755
  /* If we've been asked to synthesize a clone, just synthesize the
756
     cloned function instead.  Doing so will automatically fill in the
757
     body for the clone.  */
758
  if (DECL_CLONED_FUNCTION_P (fndecl))
759
    fndecl = DECL_CLONED_FUNCTION (fndecl);
760
 
761
  /* We may be in the middle of deferred access check.  Disable
762
     it now.  */
763
  push_deferring_access_checks (dk_no_deferred);
764
 
765
  if (! context)
766
    push_to_top_level ();
767
  else if (nested)
768
    push_function_context_to (context);
769
 
770
  input_location = DECL_SOURCE_LOCATION (fndecl);
771
 
772
  start_preparsed_function (fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
773
  stmt = begin_function_body ();
774
 
775
  if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
776
    {
777
      do_build_assign_ref (fndecl);
778
      need_body = false;
779
    }
780
  else if (DECL_CONSTRUCTOR_P (fndecl))
781
    {
782
      tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl);
783
      if (arg_chain != void_list_node)
784
        do_build_copy_constructor (fndecl);
785
      else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
786
        finish_mem_initializers (NULL_TREE);
787
    }
788
 
789
  /* If we haven't yet generated the body of the function, just
790
     generate an empty compound statement.  */
791
  if (need_body)
792
    {
793
      tree compound_stmt;
794
      compound_stmt = begin_compound_stmt (BCS_FN_BODY);
795
      finish_compound_stmt (compound_stmt);
796
    }
797
 
798
  finish_function_body (stmt);
799
  expand_or_defer_fn (finish_function (0));
800
 
801
  input_location = save_input_location;
802
 
803
  if (! context)
804
    pop_from_top_level ();
805
  else if (nested)
806
    pop_function_context_from (context);
807
 
808
  pop_deferring_access_checks ();
809
 
810
  if (error_count != errorcount || warning_count != warningcount)
811
    inform ("%Hsynthesized method %qD first required here ",
812
            &input_location, fndecl);
813
}
814
 
815
/* Use EXTRACTOR to locate the relevant function called for each base &
816
   class field of TYPE. CLIENT allows additional information to be passed
817
   to EXTRACTOR.  Generates the union of all exceptions generated by those
818
   functions.  Note that we haven't updated TYPE_FIELDS and such of any
819
   variants yet, so we need to look at the main one.  */
820
 
821
static tree
822
synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
823
                           void *client)
824
{
825
  tree raises = empty_except_spec;
826
  tree fields = TYPE_FIELDS (type);
827
  tree binfo, base_binfo;
828
  int i;
829
 
830
  for (binfo = TYPE_BINFO (type), i = 0;
831
       BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
832
    {
833
      tree fn = (*extractor) (BINFO_TYPE (base_binfo), client);
834
      if (fn)
835
        {
836
          tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
837
 
838
          raises = merge_exception_specifiers (raises, fn_raises);
839
        }
840
    }
841
  for (; fields; fields = TREE_CHAIN (fields))
842
    {
843
      tree type = TREE_TYPE (fields);
844
      tree fn;
845
 
846
      if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
847
        continue;
848
      while (TREE_CODE (type) == ARRAY_TYPE)
849
        type = TREE_TYPE (type);
850
      if (!CLASS_TYPE_P (type))
851
        continue;
852
 
853
      fn = (*extractor) (type, client);
854
      if (fn)
855
        {
856
          tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
857
 
858
          raises = merge_exception_specifiers (raises, fn_raises);
859
        }
860
    }
861
  return raises;
862
}
863
 
864
/* Locate the dtor of TYPE.  */
865
 
866
static tree
867
locate_dtor (tree type, void *client ATTRIBUTE_UNUSED)
868
{
869
  return CLASSTYPE_DESTRUCTORS (type);
870
}
871
 
872
/* Locate the default ctor of TYPE.  */
873
 
874
static tree
875
locate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
876
{
877
  tree fns;
878
 
879
  if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
880
    return NULL_TREE;
881
 
882
  /* Call lookup_fnfields_1 to create the constructor declarations, if
883
     necessary.  */
884
  if (CLASSTYPE_LAZY_DEFAULT_CTOR (type))
885
    return lazily_declare_fn (sfk_constructor, type);
886
 
887
  for (fns = CLASSTYPE_CONSTRUCTORS (type); fns; fns = OVL_NEXT (fns))
888
    {
889
      tree fn = OVL_CURRENT (fns);
890
      tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
891
 
892
      parms = skip_artificial_parms_for (fn, parms);
893
 
894
      if (sufficient_parms_p (parms))
895
        return fn;
896
    }
897
  gcc_unreachable ();
898
}
899
 
900
struct copy_data
901
{
902
  tree name;
903
  int quals;
904
};
905
 
906
/* Locate the copy ctor or copy assignment of TYPE. CLIENT_
907
   points to a COPY_DATA holding the name (NULL for the ctor)
908
   and desired qualifiers of the source operand.  */
909
 
910
static tree
911
locate_copy (tree type, void *client_)
912
{
913
  struct copy_data *client = (struct copy_data *)client_;
914
  tree fns;
915
  tree best = NULL_TREE;
916
  bool excess_p = false;
917
 
918
  if (client->name)
919
    {
920
      int ix;
921
      ix = lookup_fnfields_1 (type, client->name);
922
      if (ix < 0)
923
        return NULL_TREE;
924
      fns = VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
925
    }
926
  else if (TYPE_HAS_INIT_REF (type))
927
    {
928
      /* If construction of the copy constructor was postponed, create
929
         it now.  */
930
      if (CLASSTYPE_LAZY_COPY_CTOR (type))
931
        lazily_declare_fn (sfk_copy_constructor, type);
932
      fns = CLASSTYPE_CONSTRUCTORS (type);
933
    }
934
  else
935
    return NULL_TREE;
936
  for (; fns; fns = OVL_NEXT (fns))
937
    {
938
      tree fn = OVL_CURRENT (fns);
939
      tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
940
      tree src_type;
941
      int excess;
942
      int quals;
943
 
944
      parms = skip_artificial_parms_for (fn, parms);
945
      if (!parms)
946
        continue;
947
      src_type = non_reference (TREE_VALUE (parms));
948
      if (!same_type_ignoring_top_level_qualifiers_p (src_type, type))
949
        continue;
950
      if (!sufficient_parms_p (TREE_CHAIN (parms)))
951
        continue;
952
      quals = cp_type_quals (src_type);
953
      if (client->quals & ~quals)
954
        continue;
955
      excess = quals & ~client->quals;
956
      if (!best || (excess_p && !excess))
957
        {
958
          best = fn;
959
          excess_p = excess;
960
        }
961
      else
962
        /* Ambiguous */
963
        return NULL_TREE;
964
    }
965
  return best;
966
}
967
 
968
/* Implicitly declare the special function indicated by KIND, as a
969
   member of TYPE.  For copy constructors and assignment operators,
970
   CONST_P indicates whether these functions should take a const
971
   reference argument or a non-const reference.  Returns the
972
   FUNCTION_DECL for the implicitly declared function.  */
973
 
974
tree
975
implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
976
{
977
  tree fn;
978
  tree parameter_types = void_list_node;
979
  tree return_type;
980
  tree fn_type;
981
  tree raises = empty_except_spec;
982
  tree rhs_parm_type = NULL_TREE;
983
  tree name;
984
  HOST_WIDE_INT saved_processing_template_decl;
985
 
986
  /* Because we create declarations for implicitly declared functions
987
     lazily, we may be creating the declaration for a member of TYPE
988
     while in some completely different context.  However, TYPE will
989
     never be a dependent class (because we never want to do lookups
990
     for implicitly defined functions in a dependent class).
991
     Furthermore, we must set PROCESSING_TEMPLATE_DECL to zero here
992
     because we only create clones for constructors and destructors
993
     when not in a template.  */
994
  gcc_assert (!dependent_type_p (type));
995
  saved_processing_template_decl = processing_template_decl;
996
  processing_template_decl = 0;
997
 
998
  type = TYPE_MAIN_VARIANT (type);
999
 
1000
  if (targetm.cxx.cdtor_returns_this () && !TYPE_FOR_JAVA (type))
1001
    {
1002
      if (kind == sfk_destructor)
1003
        /* See comment in check_special_function_return_type.  */
1004
        return_type = build_pointer_type (void_type_node);
1005
      else
1006
        return_type = build_pointer_type (type);
1007
    }
1008
  else
1009
    return_type = void_type_node;
1010
 
1011
  switch (kind)
1012
    {
1013
    case sfk_destructor:
1014
      /* Destructor.  */
1015
      name = constructor_name (type);
1016
      raises = synthesize_exception_spec (type, &locate_dtor, 0);
1017
      break;
1018
 
1019
    case sfk_constructor:
1020
      /* Default constructor.  */
1021
      name = constructor_name (type);
1022
      raises = synthesize_exception_spec (type, &locate_ctor, 0);
1023
      break;
1024
 
1025
    case sfk_copy_constructor:
1026
    case sfk_assignment_operator:
1027
    {
1028
      struct copy_data data;
1029
 
1030
      data.name = NULL;
1031
      data.quals = 0;
1032
      if (kind == sfk_assignment_operator)
1033
        {
1034
          return_type = build_reference_type (type);
1035
          name = ansi_assopname (NOP_EXPR);
1036
          data.name = name;
1037
        }
1038
      else
1039
        name = constructor_name (type);
1040
 
1041
      if (const_p)
1042
        {
1043
          data.quals = TYPE_QUAL_CONST;
1044
          rhs_parm_type = build_qualified_type (type, TYPE_QUAL_CONST);
1045
        }
1046
      else
1047
        rhs_parm_type = type;
1048
      rhs_parm_type = build_reference_type (rhs_parm_type);
1049
      parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types);
1050
      raises = synthesize_exception_spec (type, &locate_copy, &data);
1051
      break;
1052
    }
1053
    default:
1054
      gcc_unreachable ();
1055
    }
1056
 
1057
  /* Create the function.  */
1058
  fn_type = build_method_type_directly (type, return_type, parameter_types);
1059
  if (raises)
1060
    fn_type = build_exception_variant (fn_type, raises);
1061
  fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
1062
  DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type));
1063
  if (kind == sfk_constructor || kind == sfk_copy_constructor)
1064
    DECL_CONSTRUCTOR_P (fn) = 1;
1065
  else if (kind == sfk_destructor)
1066
    DECL_DESTRUCTOR_P (fn) = 1;
1067
  else
1068
    {
1069
      DECL_ASSIGNMENT_OPERATOR_P (fn) = 1;
1070
      SET_OVERLOADED_OPERATOR_CODE (fn, NOP_EXPR);
1071
    }
1072
  /* Create the argument list.  The call to "grokclassfn" will add the
1073
     "this" parameter and any other implicit parameters.  */
1074
  if (rhs_parm_type)
1075
    {
1076
      /* Note that this parameter is *not* marked DECL_ARTIFICIAL; we
1077
         want its type to be included in the mangled function
1078
         name.  */
1079
      DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
1080
      TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
1081
    }
1082
 
1083
  grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
1084
               TYPE_UNQUALIFIED);
1085
  grok_special_member_properties (fn);
1086
  set_linkage_according_to_type (type, fn);
1087
  rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
1088
  DECL_IN_AGGR_P (fn) = 1;
1089
  DECL_ARTIFICIAL (fn) = 1;
1090
  DECL_NOT_REALLY_EXTERN (fn) = 1;
1091
  DECL_DECLARED_INLINE_P (fn) = 1;
1092
  DECL_INLINE (fn) = 1;
1093
  gcc_assert (!TREE_USED (fn));
1094
 
1095
  /* Restore PROCESSING_TEMPLATE_DECL.  */
1096
  processing_template_decl = saved_processing_template_decl;
1097
 
1098
  return fn;
1099
}
1100
 
1101
/* Add an implicit declaration to TYPE for the kind of function
1102
   indicated by SFK.  Return the FUNCTION_DECL for the new implicit
1103
   declaration.  */
1104
 
1105
tree
1106
lazily_declare_fn (special_function_kind sfk, tree type)
1107
{
1108
  tree fn;
1109
  bool const_p;
1110
 
1111
  /* Figure out whether or not the argument has a const reference
1112
     type.  */
1113
  if (sfk == sfk_copy_constructor)
1114
    const_p = TYPE_HAS_CONST_INIT_REF (type);
1115
  else if (sfk == sfk_assignment_operator)
1116
    const_p = TYPE_HAS_CONST_ASSIGN_REF (type);
1117
  else
1118
    /* In this case, CONST_P will be ignored.  */
1119
    const_p = false;
1120
  /* Declare the function.  */
1121
  fn = implicitly_declare_fn (sfk, type, const_p);
1122
  /* A destructor may be virtual.  */
1123
  if (sfk == sfk_destructor)
1124
    check_for_override (fn, type);
1125
  /* Add it to CLASSTYPE_METHOD_VEC.  */
1126
  add_method (type, fn, NULL_TREE);
1127
  /* Add it to TYPE_METHODS.  */
1128
  if (sfk == sfk_destructor
1129
      && DECL_VIRTUAL_P (fn)
1130
      && abi_version_at_least (2))
1131
    /* The ABI requires that a virtual destructor go at the end of the
1132
       vtable.  */
1133
    TYPE_METHODS (type) = chainon (TYPE_METHODS (type), fn);
1134
  else
1135
    {
1136
      /* G++ 3.2 put the implicit destructor at the *beginning* of the
1137
         TYPE_METHODS list, which cause the destructor to be emitted
1138
         in an incorrect location in the vtable.  */
1139
      if (warn_abi && DECL_VIRTUAL_P (fn))
1140
        warning (0, "vtable layout for class %qT may not be ABI-compliant"
1141
                 "and may change in a future version of GCC due to "
1142
                 "implicit virtual destructor",
1143
                 type);
1144
      TREE_CHAIN (fn) = TYPE_METHODS (type);
1145
      TYPE_METHODS (type) = fn;
1146
    }
1147
  maybe_add_class_template_decl_list (type, fn, /*friend_p=*/0);
1148
  if (sfk == sfk_assignment_operator)
1149
    CLASSTYPE_LAZY_ASSIGNMENT_OP (type) = 0;
1150
  else
1151
    {
1152
      /* Remember that the function has been created.  */
1153
      if (sfk == sfk_constructor)
1154
        CLASSTYPE_LAZY_DEFAULT_CTOR (type) = 0;
1155
      else if (sfk == sfk_copy_constructor)
1156
        CLASSTYPE_LAZY_COPY_CTOR (type) = 0;
1157
      else if (sfk == sfk_destructor)
1158
        CLASSTYPE_LAZY_DESTRUCTOR (type) = 0;
1159
      /* Create appropriate clones.  */
1160
      clone_function_decl (fn, /*update_method_vec=*/true);
1161
    }
1162
 
1163
  return fn;
1164
}
1165
 
1166
/* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST
1167
   as there are artificial parms in FN.  */
1168
 
1169
tree
1170
skip_artificial_parms_for (tree fn, tree list)
1171
{
1172
  if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
1173
    list = TREE_CHAIN (list);
1174
  else
1175
    return list;
1176
 
1177
  if (DECL_HAS_IN_CHARGE_PARM_P (fn))
1178
    list = TREE_CHAIN (list);
1179
  if (DECL_HAS_VTT_PARM_P (fn))
1180
    list = TREE_CHAIN (list);
1181
  return list;
1182
}
1183
 
1184
#include "gt-cp-method.h"

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.