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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [cp/] [method.c] - Blame information for rev 478

Go to most recent revision | Details | Compare with Previous | View Log

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