]>
Commit | Line | Data |
---|---|---|
8d08fdba MS |
1 | /* Handle the hair of processing (but not expanding) inline functions. |
2 | Also manage function and variable name overloading. | |
d6a8bdff JL |
3 | Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, |
4 | 1999, 2000 Free Software Foundation, Inc. | |
8d08fdba MS |
5 | Contributed by Michael Tiemann (tiemann@cygnus.com) |
6 | ||
e5e809f4 | 7 | This file is part of GNU CC. |
8d08fdba MS |
8 | |
9 | GNU CC 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 | GNU CC 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 GNU CC; see the file COPYING. If not, write to | |
e9fa0c7c RK |
21 | the Free Software Foundation, 59 Temple Place - Suite 330, |
22 | Boston, MA 02111-1307, USA. */ | |
8d08fdba MS |
23 | |
24 | ||
8d08fdba | 25 | /* Handle method declarations. */ |
8d08fdba | 26 | #include "config.h" |
e817b5e3 | 27 | #include "system.h" |
8d08fdba MS |
28 | #include "tree.h" |
29 | #include "cp-tree.h" | |
8926095f MS |
30 | #include "rtl.h" |
31 | #include "expr.h" | |
32 | #include "output.h" | |
8926095f | 33 | #include "flags.h" |
54f92bfb | 34 | #include "toplev.h" |
9cd64686 | 35 | #include "ggc.h" |
b1afd7f4 | 36 | #include "tm_p.h" |
483ab821 | 37 | #include "target.h" |
8d08fdba | 38 | |
669ec2b4 JM |
39 | /* Various flags to control the mangling process. */ |
40 | ||
41 | enum mangling_flags | |
42 | { | |
43 | /* No flags. */ | |
44 | mf_none = 0, | |
45 | /* The thing we are presently mangling is part of a template type, | |
46 | rather than a fully instantiated type. Therefore, we may see | |
47 | complex expressions where we would normally expect to see a | |
48 | simple integer constant. */ | |
49 | mf_maybe_uninstantiated = 1, | |
50 | /* When mangling a numeric value, use the form `_XX_' (instead of | |
51 | just `XX') if the value has more than one digit. */ | |
52 | mf_use_underscores_around_value = 2, | |
53 | }; | |
54 | ||
55 | typedef enum mangling_flags mangling_flags; | |
56 | ||
158991b7 KG |
57 | static void do_build_assign_ref PARAMS ((tree)); |
58 | static void do_build_copy_constructor PARAMS ((tree)); | |
03378143 NS |
59 | static tree synthesize_exception_spec PARAMS ((tree, tree (*) (tree, void *), void *)); |
60 | static tree locate_dtor PARAMS ((tree, void *)); | |
61 | static tree locate_ctor PARAMS ((tree, void *)); | |
62 | static tree locate_copy PARAMS ((tree, void *)); | |
669ec2b4 | 63 | |
669ec2b4 JM |
64 | /* Called once to initialize method.c. */ |
65 | ||
66 | void | |
67 | init_method () | |
68 | { | |
1f84ec23 | 69 | init_mangle (); |
669ec2b4 JM |
70 | } |
71 | ||
669ec2b4 | 72 | \f |
36a117a5 | 73 | /* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */ |
386b8a85 | 74 | |
c1def683 | 75 | void |
36a117a5 | 76 | set_mangled_name_for_decl (decl) |
9a68c51f | 77 | tree decl; |
386b8a85 | 78 | { |
6b4b3deb MM |
79 | if (processing_template_decl) |
80 | /* There's no need to mangle the name of a template function. */ | |
81 | return; | |
82 | ||
92643fea | 83 | mangle_decl (decl); |
669ec2b4 JM |
84 | } |
85 | ||
8d08fdba MS |
86 | \f |
87 | /* Given a tree_code CODE, and some arguments (at least one), | |
88 | attempt to use an overloaded operator on the arguments. | |
89 | ||
90 | For unary operators, only the first argument need be checked. | |
91 | For binary operators, both arguments may need to be checked. | |
92 | ||
93 | Member functions can convert class references to class pointers, | |
94 | for one-level deep indirection. More than that is not supported. | |
95 | Operators [](), ()(), and ->() must be member functions. | |
96 | ||
97 | We call function call building calls with LOOKUP_COMPLAIN if they | |
98 | are our only hope. This is true when we see a vanilla operator | |
99 | applied to something of aggregate type. If this fails, we are free | |
100 | to return `error_mark_node', because we will have reported the | |
101 | error. | |
102 | ||
103 | Operators NEW and DELETE overload in funny ways: operator new takes | |
104 | a single `size' parameter, and operator delete takes a pointer to the | |
105 | storage being deleted. When overloading these operators, success is | |
106 | assumed. If there is a failure, report an error message and return | |
107 | `error_mark_node'. */ | |
108 | ||
109 | /* NOSTRICT */ | |
110 | tree | |
111 | build_opfncall (code, flags, xarg1, xarg2, arg3) | |
112 | enum tree_code code; | |
113 | int flags; | |
114 | tree xarg1, xarg2, arg3; | |
115 | { | |
277294d7 | 116 | return build_new_op (code, flags, xarg1, xarg2, arg3); |
8d08fdba MS |
117 | } |
118 | \f | |
119 | /* This function takes an identifier, ID, and attempts to figure out what | |
120 | it means. There are a number of possible scenarios, presented in increasing | |
121 | order of hair: | |
122 | ||
123 | 1) not in a class's scope | |
124 | 2) in class's scope, member name of the class's method | |
125 | 3) in class's scope, but not a member name of the class | |
126 | 4) in class's scope, member name of a class's variable | |
127 | ||
128 | NAME is $1 from the bison rule. It is an IDENTIFIER_NODE. | |
129 | VALUE is $$ from the bison rule. It is the value returned by lookup_name ($1) | |
8d08fdba MS |
130 | |
131 | As a last ditch, try to look up the name as a label and return that | |
132 | address. | |
133 | ||
134 | Values which are declared as being of REFERENCE_TYPE are | |
135 | automatically dereferenced here (as a hack to make the | |
136 | compiler faster). */ | |
137 | ||
138 | tree | |
5566b478 | 139 | hack_identifier (value, name) |
8d08fdba | 140 | tree value, name; |
8d08fdba | 141 | { |
de22184b | 142 | tree type; |
8d08fdba | 143 | |
bd6dd845 | 144 | if (value == error_mark_node) |
7437519c | 145 | return error_mark_node; |
8d08fdba MS |
146 | |
147 | type = TREE_TYPE (value); | |
148 | if (TREE_CODE (value) == FIELD_DECL) | |
149 | { | |
4ac14744 | 150 | if (current_class_ptr == NULL_TREE) |
8d08fdba | 151 | { |
672476cb MM |
152 | if (current_function_decl |
153 | && DECL_STATIC_FUNCTION_P (current_function_decl)) | |
33bd39a2 | 154 | error ("invalid use of member `%D' in static member function", |
672476cb MM |
155 | value); |
156 | else | |
157 | /* We can get here when processing a bad default | |
158 | argument, like: | |
159 | struct S { int a; void f(int i = a); } */ | |
33bd39a2 | 160 | error ("invalid use of member `%D'", value); |
672476cb | 161 | |
8d08fdba MS |
162 | return error_mark_node; |
163 | } | |
4ac14744 | 164 | TREE_USED (current_class_ptr) = 1; |
50ad9642 MM |
165 | if (processing_template_decl) |
166 | value = build_min_nt (COMPONENT_REF, current_class_ref, name); | |
167 | else | |
168 | { | |
169 | tree access_type = current_class_type; | |
170 | ||
171 | while (!DERIVED_FROM_P (context_for_name_lookup (value), | |
172 | access_type)) | |
173 | { | |
174 | access_type = TYPE_CONTEXT (access_type); | |
175 | while (DECL_P (access_type)) | |
176 | access_type = DECL_CONTEXT (access_type); | |
177 | } | |
178 | ||
179 | enforce_access (access_type, value); | |
180 | value | |
181 | = build_class_member_access_expr (current_class_ref, value, | |
182 | /*access_path=*/NULL_TREE, | |
183 | /*preserve_reference=*/false); | |
184 | } | |
8d08fdba | 185 | } |
8f032717 MM |
186 | else if ((TREE_CODE (value) == FUNCTION_DECL |
187 | && DECL_FUNCTION_MEMBER_P (value)) | |
188 | || (TREE_CODE (value) == OVERLOAD | |
189 | && DECL_FUNCTION_MEMBER_P (OVL_CURRENT (value)))) | |
51924768 JM |
190 | { |
191 | tree decl; | |
192 | ||
8f032717 MM |
193 | if (TREE_CODE (value) == OVERLOAD) |
194 | value = OVL_CURRENT (value); | |
195 | ||
4f1c5b7d | 196 | decl = maybe_dummy_object (DECL_CONTEXT (value), 0); |
50ad9642 | 197 | value = finish_class_member_access_expr (decl, name); |
51924768 | 198 | } |
6b5fbb55 | 199 | else if (really_overloaded_fn (value)) |
8f032717 | 200 | ; |
2c73f9f5 ML |
201 | else if (TREE_CODE (value) == OVERLOAD) |
202 | /* not really overloaded function */ | |
203 | mark_used (OVL_FUNCTION (value)); | |
a5ef9010 JM |
204 | else if (TREE_CODE (value) == TREE_LIST) |
205 | { | |
72b7eeff | 206 | /* Ambiguous reference to base members, possibly other cases?. */ |
a5ef9010 JM |
207 | tree t = value; |
208 | while (t && TREE_CODE (t) == TREE_LIST) | |
209 | { | |
72b7eeff | 210 | mark_used (TREE_VALUE (t)); |
a5ef9010 JM |
211 | t = TREE_CHAIN (t); |
212 | } | |
213 | } | |
2c73f9f5 | 214 | else if (TREE_CODE (value) == NAMESPACE_DECL) |
0e607f34 | 215 | { |
33bd39a2 | 216 | error ("use of namespace `%D' as expression", value); |
0e607f34 JM |
217 | return error_mark_node; |
218 | } | |
219 | else if (DECL_CLASS_TEMPLATE_P (value)) | |
220 | { | |
33bd39a2 | 221 | error ("use of class template `%T' as expression", value); |
0e607f34 JM |
222 | return error_mark_node; |
223 | } | |
8d08fdba | 224 | else |
72b7eeff | 225 | mark_used (value); |
8d08fdba | 226 | |
c6882a35 JM |
227 | if (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == PARM_DECL |
228 | || TREE_CODE (value) == RESULT_DECL) | |
5566b478 MS |
229 | { |
230 | tree context = decl_function_context (value); | |
231 | if (context != NULL_TREE && context != current_function_decl | |
232 | && ! TREE_STATIC (value)) | |
233 | { | |
33bd39a2 | 234 | error ("use of %s from containing function", |
5566b478 MS |
235 | (TREE_CODE (value) == VAR_DECL |
236 | ? "`auto' variable" : "parameter")); | |
8251199e | 237 | cp_error_at (" `%#D' declared here", value); |
e76a2646 | 238 | value = error_mark_node; |
5566b478 MS |
239 | } |
240 | } | |
241 | ||
2f939d94 | 242 | if (DECL_P (value) && DECL_NONLOCAL (value)) |
8d08fdba | 243 | { |
70adf8a9 | 244 | if (DECL_CLASS_SCOPE_P (value) |
4f1c5b7d | 245 | && DECL_CONTEXT (value) != current_class_type) |
8d08fdba | 246 | { |
d6479fe7 | 247 | tree path; |
4f1c5b7d | 248 | path = currently_open_derived_class (DECL_CONTEXT (value)); |
70adf8a9 | 249 | enforce_access (path, value); |
8d08fdba | 250 | } |
8d08fdba | 251 | } |
280f9385 MM |
252 | else if (TREE_CODE (value) == TREE_LIST |
253 | && TREE_TYPE (value) == error_mark_node) | |
8d08fdba | 254 | { |
33bd39a2 | 255 | error ("\ |
bd0d5d4a JM |
256 | request for member `%D' is ambiguous in multiple inheritance lattice", |
257 | name); | |
66543169 | 258 | print_candidates (value); |
0cfdd854 | 259 | return error_mark_node; |
8d08fdba MS |
260 | } |
261 | ||
75d587eb | 262 | if (! processing_template_decl) |
6b5fbb55 | 263 | value = convert_from_reference (value); |
8d08fdba MS |
264 | return value; |
265 | } | |
266 | ||
8926095f | 267 | \f |
1f6e1acc AS |
268 | /* Return a thunk to FUNCTION. For a virtual thunk, DELTA is the |
269 | offset to this used to locate the vptr, and VCALL_INDEX is used to | |
270 | look up the eventual subobject location. For a non-virtual thunk, | |
85a9a0a2 | 271 | DELTA is the offset to this and VCALL_INDEX is NULL. */ |
1f6e1acc | 272 | |
8926095f | 273 | tree |
d0cd8b44 | 274 | make_thunk (function, delta, vcall_index) |
8926095f | 275 | tree function; |
31f8e4f3 MM |
276 | tree delta; |
277 | tree vcall_index; | |
8926095f | 278 | { |
b87692e5 | 279 | tree thunk_id; |
8926095f | 280 | tree thunk; |
8926095f | 281 | tree func_decl; |
31f8e4f3 MM |
282 | tree vcall_offset; |
283 | HOST_WIDE_INT d; | |
284 | ||
285 | /* Scale the VCALL_INDEX to be in terms of bytes. */ | |
286 | if (vcall_index) | |
287 | vcall_offset | |
288 | = size_binop (MULT_EXPR, | |
289 | vcall_index, | |
290 | convert (ssizetype, | |
291 | TYPE_SIZE_UNIT (vtable_entry_type))); | |
292 | else | |
293 | vcall_offset = NULL_TREE; | |
294 | ||
295 | d = tree_low_cst (delta, 0); | |
cc600f33 | 296 | |
8926095f MS |
297 | if (TREE_CODE (function) != ADDR_EXPR) |
298 | abort (); | |
299 | func_decl = TREE_OPERAND (function, 0); | |
300 | if (TREE_CODE (func_decl) != FUNCTION_DECL) | |
301 | abort (); | |
cc600f33 | 302 | |
1f84ec23 MM |
303 | thunk_id = mangle_thunk (TREE_OPERAND (function, 0), |
304 | delta, vcall_offset); | |
a0a33927 | 305 | thunk = IDENTIFIER_GLOBAL_VALUE (thunk_id); |
eb68cb58 | 306 | if (thunk && !DECL_THUNK_P (thunk)) |
a0a33927 | 307 | { |
33bd39a2 | 308 | error ("implementation-reserved name `%D' used", thunk_id); |
2c73f9f5 ML |
309 | thunk = NULL_TREE; |
310 | SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk); | |
a0a33927 MS |
311 | } |
312 | if (thunk == NULL_TREE) | |
313 | { | |
eb448459 | 314 | thunk = build_decl (FUNCTION_DECL, thunk_id, TREE_TYPE (func_decl)); |
6462c441 | 315 | DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (func_decl); |
63e1b1c4 | 316 | cxx_dup_lang_specific_decl (func_decl); |
92643fea | 317 | SET_DECL_ASSEMBLER_NAME (thunk, thunk_id); |
6462c441 | 318 | DECL_CONTEXT (thunk) = DECL_CONTEXT (func_decl); |
eb448459 MS |
319 | TREE_READONLY (thunk) = TREE_READONLY (func_decl); |
320 | TREE_THIS_VOLATILE (thunk) = TREE_THIS_VOLATILE (func_decl); | |
15eb1e43 JM |
321 | TREE_PUBLIC (thunk) = TREE_PUBLIC (func_decl); |
322 | if (flag_weak) | |
323 | comdat_linkage (thunk); | |
eb68cb58 | 324 | SET_DECL_THUNK_P (thunk); |
a0a33927 | 325 | DECL_INITIAL (thunk) = function; |
31f8e4f3 | 326 | THUNK_DELTA (thunk) = d; |
1f6e1acc | 327 | THUNK_VCALL_OFFSET (thunk) = vcall_offset; |
6462c441 | 328 | /* The thunk itself is not a constructor or destructor, even if |
bfc8e1e2 | 329 | the thing it is thunking to is. */ |
6462c441 MM |
330 | DECL_INTERFACE_KNOWN (thunk) = 1; |
331 | DECL_NOT_REALLY_EXTERN (thunk) = 1; | |
332 | DECL_SAVED_FUNCTION_DATA (thunk) = NULL; | |
333 | DECL_DESTRUCTOR_P (thunk) = 0; | |
334 | DECL_CONSTRUCTOR_P (thunk) = 0; | |
bbb53468 NS |
335 | /* And neither is it a clone. */ |
336 | DECL_CLONED_FUNCTION (thunk) = NULL_TREE; | |
72b7eeff | 337 | DECL_EXTERNAL (thunk) = 1; |
eb448459 | 338 | DECL_ARTIFICIAL (thunk) = 1; |
eb68cb58 MM |
339 | /* Even if this thunk is a member of a local class, we don't |
340 | need a static chain. */ | |
341 | DECL_NO_STATIC_CHAIN (thunk) = 1; | |
6462c441 MM |
342 | /* The THUNK is not a pending inline, even if the FUNC_DECL is. */ |
343 | DECL_PENDING_INLINE_P (thunk) = 0; | |
344 | /* Nor has it been deferred. */ | |
345 | DECL_DEFERRED_FN (thunk) = 0; | |
a0a33927 MS |
346 | /* So that finish_file can write out any thunks that need to be: */ |
347 | pushdecl_top_level (thunk); | |
92643fea | 348 | SET_IDENTIFIER_GLOBAL_VALUE (thunk_id, thunk); |
a0a33927 | 349 | } |
8926095f MS |
350 | return thunk; |
351 | } | |
352 | ||
1b28d441 | 353 | /* Emit the definition of a C++ multiple inheritance vtable thunk. If |
838dfd8a | 354 | EMIT_P is nonzero, the thunk is emitted immediately. */ |
eb448459 | 355 | |
8926095f | 356 | void |
31f8e4f3 | 357 | use_thunk (thunk_fndecl, emit_p) |
824b9a4c | 358 | tree thunk_fndecl; |
31f8e4f3 | 359 | int emit_p; |
8926095f | 360 | { |
6462c441 MM |
361 | tree fnaddr; |
362 | tree function; | |
31f8e4f3 MM |
363 | tree vcall_offset; |
364 | HOST_WIDE_INT delta; | |
8926095f MS |
365 | |
366 | if (TREE_ASM_WRITTEN (thunk_fndecl)) | |
367 | return; | |
31f8e4f3 MM |
368 | |
369 | fnaddr = DECL_INITIAL (thunk_fndecl); | |
6462c441 MM |
370 | if (TREE_CODE (DECL_INITIAL (thunk_fndecl)) != ADDR_EXPR) |
371 | /* We already turned this thunk into an ordinary function. | |
dff94ad7 | 372 | There's no need to process this thunk again. */ |
6462c441 MM |
373 | return; |
374 | ||
31f8e4f3 MM |
375 | /* Thunks are always addressable; they only appear in vtables. */ |
376 | TREE_ADDRESSABLE (thunk_fndecl) = 1; | |
a0a33927 | 377 | |
31f8e4f3 MM |
378 | /* Figure out what function is being thunked to. It's referenced in |
379 | this translation unit. */ | |
380 | function = TREE_OPERAND (fnaddr, 0); | |
809c8c30 JM |
381 | TREE_ADDRESSABLE (function) = 1; |
382 | mark_used (function); | |
31f8e4f3 MM |
383 | TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (function)) = 1; |
384 | if (!emit_p) | |
385 | return; | |
809c8c30 | 386 | |
31f8e4f3 MM |
387 | delta = THUNK_DELTA (thunk_fndecl); |
388 | vcall_offset = THUNK_VCALL_OFFSET (thunk_fndecl); | |
389 | ||
390 | /* And, if we need to emit the thunk, it's used. */ | |
391 | mark_used (thunk_fndecl); | |
392 | /* This thunk is actually defined. */ | |
393 | DECL_EXTERNAL (thunk_fndecl) = 0; | |
15eb1e43 JM |
394 | /* The linkage of the function may have changed. FIXME in linkage |
395 | rewrite. */ | |
396 | TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function); | |
a0128b67 | 397 | |
6462c441 MM |
398 | if (flag_syntax_only) |
399 | { | |
400 | TREE_ASM_WRITTEN (thunk_fndecl) = 1; | |
401 | return; | |
402 | } | |
403 | ||
31f8e4f3 MM |
404 | push_to_top_level (); |
405 | ||
14691f8d RH |
406 | /* The back-end expects DECL_INITIAL to contain a BLOCK, so we |
407 | create one. */ | |
408 | DECL_INITIAL (thunk_fndecl) = make_node (BLOCK); | |
409 | BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) | |
410 | = DECL_ARGUMENTS (thunk_fndecl); | |
411 | ||
483ab821 MM |
412 | if (targetm.asm_out.output_mi_vcall_thunk |
413 | || (targetm.asm_out.output_mi_thunk && !vcall_offset)) | |
3b62f224 | 414 | { |
3cce094d | 415 | const char *fnname; |
3b62f224 | 416 | current_function_decl = thunk_fndecl; |
3b62f224 MM |
417 | DECL_RESULT (thunk_fndecl) |
418 | = build_decl (RESULT_DECL, 0, integer_type_node); | |
419 | fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); | |
420 | init_function_start (thunk_fndecl, input_filename, lineno); | |
421 | current_function_is_thunk = 1; | |
422 | assemble_start_function (thunk_fndecl, fnname); | |
483ab821 MM |
423 | if (targetm.asm_out.output_mi_vcall_thunk) |
424 | { | |
eb0424da MM |
425 | HOST_WIDE_INT vcall_value; |
426 | ||
427 | if (vcall_offset) | |
428 | vcall_value = tree_low_cst (vcall_offset, /*pos=*/0); | |
429 | else | |
430 | vcall_value = 0; | |
483ab821 MM |
431 | targetm.asm_out.output_mi_vcall_thunk (asm_out_file, |
432 | thunk_fndecl, delta, | |
433 | vcall_value, | |
434 | function); | |
435 | } | |
436 | else | |
437 | targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, | |
438 | delta, function); | |
3b62f224 | 439 | assemble_end_function (thunk_fndecl, fnname); |
3b62f224 | 440 | current_function_decl = 0; |
01d939e8 | 441 | cfun = 0; |
6462c441 | 442 | TREE_ASM_WRITTEN (thunk_fndecl) = 1; |
3b62f224 | 443 | } |
4e7512c9 | 444 | else |
14691f8d | 445 | { |
483ab821 MM |
446 | /* If we don't have the necessary code for efficient thunks, |
447 | generate a thunk function that just makes a call to the real | |
448 | function. Unfortunately, this doesn't work for varargs. */ | |
14691f8d RH |
449 | |
450 | tree a, t; | |
451 | ||
452 | if (varargs_function_p (function)) | |
453 | error ("generic thunk code fails for method `%#D' which uses `...'", | |
454 | function); | |
455 | ||
456 | /* Set up clone argument trees for the thunk. */ | |
457 | t = NULL_TREE; | |
458 | for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) | |
459 | { | |
460 | tree x = copy_node (a); | |
461 | TREE_CHAIN (x) = t; | |
462 | DECL_CONTEXT (x) = thunk_fndecl; | |
463 | t = x; | |
464 | } | |
465 | a = nreverse (t); | |
466 | DECL_ARGUMENTS (thunk_fndecl) = a; | |
467 | DECL_RESULT (thunk_fndecl) = NULL_TREE; | |
468 | ||
469 | start_function (NULL_TREE, thunk_fndecl, NULL_TREE, SF_PRE_PARSED); | |
470 | /* We don't bother with a body block for thunks. */ | |
471 | ||
472 | /* Adjust the this pointer by the constant. */ | |
473 | t = ssize_int (delta); | |
474 | t = fold (build (PLUS_EXPR, TREE_TYPE (a), a, t)); | |
475 | ||
476 | /* If there's a vcall offset, look up that value in the vtable and | |
477 | adjust the `this' pointer again. */ | |
478 | if (vcall_offset && !integer_zerop (vcall_offset)) | |
479 | { | |
480 | tree orig_this; | |
481 | ||
482 | t = save_expr (t); | |
483 | orig_this = t; | |
484 | /* The vptr is always at offset zero in the object. */ | |
485 | t = build1 (NOP_EXPR, | |
486 | build_pointer_type (build_pointer_type | |
487 | (vtable_entry_type)), | |
488 | t); | |
489 | /* Form the vtable address. */ | |
490 | t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); | |
491 | /* Find the entry with the vcall offset. */ | |
492 | t = build (PLUS_EXPR, TREE_TYPE (t), t, vcall_offset); | |
493 | /* Calculate the offset itself. */ | |
494 | t = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (t)), t); | |
495 | /* Adjust the `this' pointer. */ | |
496 | t = fold (build (PLUS_EXPR, | |
497 | TREE_TYPE (orig_this), | |
498 | orig_this, | |
499 | t)); | |
500 | } | |
501 | ||
502 | /* Build up the call to the real function. */ | |
503 | t = tree_cons (NULL_TREE, t, NULL_TREE); | |
504 | for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) | |
505 | t = tree_cons (NULL_TREE, a, t); | |
506 | t = nreverse (t); | |
507 | t = build_call (function, t); | |
508 | if (VOID_TYPE_P (TREE_TYPE (t))) | |
509 | finish_expr_stmt (t); | |
510 | else | |
511 | finish_return_stmt (t); | |
512 | ||
513 | /* Since we want to emit the thunk, we explicitly mark its name as | |
514 | referenced. */ | |
515 | TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (thunk_fndecl)) = 1; | |
516 | ||
517 | /* But we don't want debugging information about it. */ | |
518 | DECL_IGNORED_P (thunk_fndecl) = 1; | |
519 | ||
520 | expand_body (finish_function (0)); | |
521 | } | |
31f8e4f3 MM |
522 | |
523 | pop_from_top_level (); | |
8926095f | 524 | } |
f376e137 MS |
525 | \f |
526 | /* Code for synthesizing methods which have default semantics defined. */ | |
527 | ||
f376e137 | 528 | /* Generate code for default X(X&) constructor. */ |
e92cc029 | 529 | |
824b9a4c | 530 | static void |
db5ae43f | 531 | do_build_copy_constructor (fndecl) |
f376e137 MS |
532 | tree fndecl; |
533 | { | |
e0fff4b3 | 534 | tree parm = FUNCTION_FIRST_USER_PARM (fndecl); |
f376e137 MS |
535 | tree t; |
536 | ||
f376e137 MS |
537 | parm = convert_from_reference (parm); |
538 | ||
a59ca936 JM |
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)) | |
f376e137 | 544 | { |
4ac14744 | 545 | t = build (INIT_EXPR, void_type_node, current_class_ref, parm); |
f1dedc31 | 546 | finish_expr_stmt (t); |
f376e137 MS |
547 | } |
548 | else | |
549 | { | |
550 | tree fields = TYPE_FIELDS (current_class_type); | |
551 | int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); | |
552 | tree binfos = TYPE_BINFO_BASETYPES (current_class_type); | |
fd74ca0b | 553 | tree member_init_list = NULL_TREE; |
89d684bb | 554 | int cvquals = cp_type_quals (TREE_TYPE (parm)); |
f376e137 MS |
555 | int i; |
556 | ||
713ccd0c NS |
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. */ | |
f376e137 MS |
562 | for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; |
563 | t = TREE_CHAIN (t)) | |
01f9e964 | 564 | { |
713ccd0c NS |
565 | tree binfo = TREE_VALUE (t); |
566 | ||
2282d28d MM |
567 | member_init_list |
568 | = tree_cons (binfo, | |
569 | build_tree_list (NULL_TREE, | |
570 | build_base_path (PLUS_EXPR, parm, | |
571 | binfo, 1)), | |
572 | member_init_list); | |
01f9e964 JM |
573 | } |
574 | ||
f376e137 MS |
575 | for (i = 0; i < n_bases; ++i) |
576 | { | |
713ccd0c NS |
577 | tree binfo = TREE_VEC_ELT (binfos, i); |
578 | if (TREE_VIA_VIRTUAL (binfo)) | |
8ccc31eb | 579 | continue; |
f376e137 | 580 | |
2282d28d MM |
581 | member_init_list |
582 | = tree_cons (binfo, | |
583 | build_tree_list (NULL_TREE, | |
584 | build_base_path (PLUS_EXPR, parm, | |
585 | binfo, 1)), | |
586 | member_init_list); | |
f376e137 | 587 | } |
1b5f5f76 | 588 | |
f376e137 MS |
589 | for (; fields; fields = TREE_CHAIN (fields)) |
590 | { | |
01f9e964 | 591 | tree init; |
a5894242 | 592 | tree field = fields; |
33dd07ee | 593 | tree expr_type; |
a5894242 MS |
594 | |
595 | if (TREE_CODE (field) != FIELD_DECL) | |
f376e137 | 596 | continue; |
8dff1027 MS |
597 | |
598 | init = parm; | |
a5894242 | 599 | if (DECL_NAME (field)) |
f376e137 | 600 | { |
a5894242 | 601 | if (VFIELD_NAME_P (DECL_NAME (field))) |
f376e137 | 602 | continue; |
f376e137 MS |
603 | |
604 | /* True for duplicate members. */ | |
a5894242 | 605 | if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) |
f376e137 MS |
606 | continue; |
607 | } | |
a5894242 | 608 | else if ((t = TREE_TYPE (field)) != NULL_TREE |
6bdb8141 | 609 | && ANON_AGGR_TYPE_P (t) |
0171aeab | 610 | && TYPE_FIELDS (t) != NULL_TREE) |
6bdb8141 JM |
611 | /* Just use the field; anonymous types can't have |
612 | nontrivial copy ctors or assignment ops. */; | |
0171aeab JM |
613 | else |
614 | continue; | |
f376e137 | 615 | |
33dd07ee MM |
616 | /* Compute the type of "init->field". If the copy-constructor |
617 | parameter is, for example, "const S&", and the type of | |
618 | the field is "T", then the type will usually be "const | |
619 | T". (There are no cv-qualified variants of reference | |
620 | types.) */ | |
621 | expr_type = TREE_TYPE (field); | |
622 | if (TREE_CODE (expr_type) != REFERENCE_TYPE) | |
623 | expr_type = cp_build_qualified_type (expr_type, cvquals); | |
624 | init = build (COMPONENT_REF, expr_type, init, field); | |
f376e137 MS |
625 | init = build_tree_list (NULL_TREE, init); |
626 | ||
fd74ca0b MM |
627 | member_init_list |
628 | = tree_cons (field, init, member_init_list); | |
f376e137 | 629 | } |
2282d28d | 630 | finish_mem_initializers (member_init_list); |
f376e137 | 631 | } |
f376e137 MS |
632 | } |
633 | ||
824b9a4c | 634 | static void |
db5ae43f | 635 | do_build_assign_ref (fndecl) |
f376e137 MS |
636 | tree fndecl; |
637 | { | |
638 | tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); | |
f1dedc31 | 639 | tree compound_stmt; |
f376e137 | 640 | |
f1dedc31 | 641 | compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); |
f376e137 MS |
642 | parm = convert_from_reference (parm); |
643 | ||
a59ca936 JM |
644 | if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type) |
645 | && is_empty_class (current_class_type)) | |
646 | /* Don't copy the padding byte; it might not have been allocated | |
647 | if *this is a base subobject. */; | |
648 | else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)) | |
f376e137 | 649 | { |
4ac14744 | 650 | tree t = build (MODIFY_EXPR, void_type_node, current_class_ref, parm); |
f1dedc31 | 651 | finish_expr_stmt (t); |
f376e137 MS |
652 | } |
653 | else | |
654 | { | |
4ba126e4 | 655 | tree fields; |
89d684bb | 656 | int cvquals = cp_type_quals (TREE_TYPE (parm)); |
f376e137 MS |
657 | int i; |
658 | ||
4ba126e4 MM |
659 | /* Assign to each of thedirect base classes. */ |
660 | for (i = 0; i < CLASSTYPE_N_BASECLASSES (current_class_type); ++i) | |
f376e137 | 661 | { |
4ba126e4 MM |
662 | tree binfo; |
663 | tree converted_parm; | |
664 | ||
665 | binfo = BINFO_BASETYPE (TYPE_BINFO (current_class_type), i); | |
666 | /* We must convert PARM directly to the base class | |
667 | explicitly since the base class may be ambiguous. */ | |
668 | converted_parm = build_base_path (PLUS_EXPR, parm, binfo, 1); | |
669 | /* Call the base class assignment operator. */ | |
670 | finish_expr_stmt | |
671 | (build_special_member_call (current_class_ref, | |
672 | ansi_assopname (NOP_EXPR), | |
673 | build_tree_list (NULL_TREE, | |
674 | converted_parm), | |
675 | binfo, | |
676 | LOOKUP_NORMAL | LOOKUP_NONVIRTUAL)); | |
f376e137 | 677 | } |
4ba126e4 MM |
678 | |
679 | /* Assign to each of the non-static data members. */ | |
680 | for (fields = TYPE_FIELDS (current_class_type); | |
681 | fields; | |
682 | fields = TREE_CHAIN (fields)) | |
f376e137 | 683 | { |
0171aeab | 684 | tree comp, init, t; |
a5894242 MS |
685 | tree field = fields; |
686 | ||
17bbb839 | 687 | if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) |
f376e137 | 688 | continue; |
e349ee73 | 689 | |
1b8899d1 | 690 | if (CP_TYPE_CONST_P (TREE_TYPE (field))) |
e349ee73 | 691 | { |
33bd39a2 | 692 | error ("non-static const member `%#D', can't use default assignment operator", field); |
e349ee73 MS |
693 | continue; |
694 | } | |
695 | else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) | |
696 | { | |
33bd39a2 | 697 | error ("non-static reference member `%#D', can't use default assignment operator", field); |
e349ee73 MS |
698 | continue; |
699 | } | |
700 | ||
8dff1027 MS |
701 | comp = current_class_ref; |
702 | init = parm; | |
703 | ||
a5894242 | 704 | if (DECL_NAME (field)) |
f376e137 | 705 | { |
a5894242 | 706 | if (VFIELD_NAME_P (DECL_NAME (field))) |
f376e137 | 707 | continue; |
f376e137 MS |
708 | |
709 | /* True for duplicate members. */ | |
a5894242 | 710 | if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field) |
f376e137 MS |
711 | continue; |
712 | } | |
a5894242 | 713 | else if ((t = TREE_TYPE (field)) != NULL_TREE |
6bdb8141 | 714 | && ANON_AGGR_TYPE_P (t) |
0171aeab | 715 | && TYPE_FIELDS (t) != NULL_TREE) |
6bdb8141 JM |
716 | /* Just use the field; anonymous types can't have |
717 | nontrivial copy ctors or assignment ops. */; | |
0171aeab JM |
718 | else |
719 | continue; | |
f376e137 | 720 | |
8dff1027 | 721 | comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field); |
31b1b957 | 722 | init = build (COMPONENT_REF, |
451c0899 | 723 | cp_build_qualified_type (TREE_TYPE (field), cvquals), |
31b1b957 | 724 | init, field); |
f376e137 | 725 | |
a1c2b86d JJ |
726 | if (DECL_NAME (field)) |
727 | finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); | |
728 | else | |
729 | finish_expr_stmt (build (MODIFY_EXPR, TREE_TYPE (comp), comp, | |
730 | init)); | |
f376e137 MS |
731 | } |
732 | } | |
62409b39 | 733 | finish_return_stmt (current_class_ref); |
f1dedc31 | 734 | finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); |
f376e137 MS |
735 | } |
736 | ||
737 | void | |
db5ae43f | 738 | synthesize_method (fndecl) |
f376e137 MS |
739 | tree fndecl; |
740 | { | |
db5ae43f | 741 | int nested = (current_function_decl != NULL_TREE); |
4f1c5b7d | 742 | tree context = decl_function_context (fndecl); |
62409b39 | 743 | int need_body = 1; |
ade3dc07 | 744 | tree stmt; |
db5ae43f | 745 | |
b7067a12 JM |
746 | if (at_eof) |
747 | import_export_decl (fndecl); | |
748 | ||
db9b2174 MM |
749 | /* If we've been asked to synthesize a clone, just synthesize the |
750 | cloned function instead. Doing so will automatically fill in the | |
751 | body for the clone. */ | |
752 | if (DECL_CLONED_FUNCTION_P (fndecl)) | |
753 | { | |
754 | synthesize_method (DECL_CLONED_FUNCTION (fndecl)); | |
755 | return; | |
756 | } | |
757 | ||
9a3b49ac MS |
758 | if (! context) |
759 | push_to_top_level (); | |
760 | else if (nested) | |
99dccabc | 761 | push_function_context_to (context); |
db5ae43f | 762 | |
62409b39 MM |
763 | /* Put the function definition at the position where it is needed, |
764 | rather than within the body of the class. That way, an error | |
765 | during the generation of the implicit body points at the place | |
766 | where the attempt to generate the function occurs, giving the | |
767 | user a hint as to why we are attempting to generate the | |
c6002625 | 768 | function. */ |
62409b39 MM |
769 | DECL_SOURCE_LINE (fndecl) = lineno; |
770 | DECL_SOURCE_FILE (fndecl) = input_filename; | |
771 | ||
e76a2646 | 772 | interface_unknown = 1; |
a8f73d4b | 773 | start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); |
f1dedc31 | 774 | clear_last_expr (); |
ade3dc07 | 775 | stmt = begin_function_body (); |
db5ae43f | 776 | |
596ea4e5 | 777 | if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR) |
62409b39 MM |
778 | { |
779 | do_build_assign_ref (fndecl); | |
780 | need_body = 0; | |
781 | } | |
cdd2559c | 782 | else if (DECL_CONSTRUCTOR_P (fndecl)) |
db5ae43f | 783 | { |
e0fff4b3 | 784 | tree arg_chain = FUNCTION_FIRST_USER_PARMTYPE (fndecl); |
db5ae43f MS |
785 | if (arg_chain != void_list_node) |
786 | do_build_copy_constructor (fndecl); | |
787 | else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) | |
cdd2559c | 788 | finish_mem_initializers (NULL_TREE); |
62409b39 | 789 | } |
f18a14bc | 790 | |
62409b39 MM |
791 | /* If we haven't yet generated the body of the function, just |
792 | generate an empty compound statement. */ | |
793 | if (need_body) | |
794 | { | |
795 | tree compound_stmt; | |
796 | compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); | |
797 | finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); | |
db5ae43f MS |
798 | } |
799 | ||
ade3dc07 | 800 | finish_function_body (stmt); |
0acf7199 | 801 | expand_body (finish_function (0)); |
28cbf42c | 802 | |
db5ae43f | 803 | extract_interface_info (); |
9a3b49ac MS |
804 | if (! context) |
805 | pop_from_top_level (); | |
806 | else if (nested) | |
99dccabc | 807 | pop_function_context_from (context); |
f376e137 | 808 | } |
9eb71d8c | 809 | |
03378143 NS |
810 | /* Use EXTRACTOR to locate the relevant function called for each base & |
811 | class field of TYPE. CLIENT allows additional information to be passed | |
f62ea157 JM |
812 | to EXTRACTOR. Generates the union of all exceptions generated by those |
813 | functions. Note that we haven't updated TYPE_FIELDS and such of any | |
814 | variants yet, so we need to look at the main one. */ | |
03378143 NS |
815 | |
816 | static tree | |
817 | synthesize_exception_spec (type, extractor, client) | |
818 | tree type; | |
819 | tree (*extractor) (tree, void *); | |
820 | void *client; | |
821 | { | |
822 | tree raises = empty_except_spec; | |
823 | tree fields = TYPE_FIELDS (type); | |
824 | int i, n_bases = CLASSTYPE_N_BASECLASSES (type); | |
825 | tree binfos = TYPE_BINFO_BASETYPES (type); | |
f62ea157 | 826 | |
03378143 NS |
827 | for (i = 0; i != n_bases; i++) |
828 | { | |
829 | tree base = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); | |
830 | tree fn = (*extractor) (base, client); | |
831 | if (fn) | |
832 | { | |
833 | tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); | |
834 | ||
835 | raises = merge_exception_specifiers (raises, fn_raises); | |
836 | } | |
837 | } | |
838 | for (; fields; fields = TREE_CHAIN (fields)) | |
839 | { | |
840 | tree type = TREE_TYPE (fields); | |
841 | tree fn; | |
842 | ||
17bbb839 | 843 | if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields)) |
03378143 NS |
844 | continue; |
845 | while (TREE_CODE (type) == ARRAY_TYPE) | |
846 | type = TREE_TYPE (type); | |
847 | if (TREE_CODE (type) != RECORD_TYPE) | |
848 | continue; | |
849 | ||
850 | fn = (*extractor) (type, client); | |
851 | if (fn) | |
852 | { | |
853 | tree fn_raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); | |
854 | ||
855 | raises = merge_exception_specifiers (raises, fn_raises); | |
856 | } | |
857 | } | |
858 | return raises; | |
859 | } | |
860 | ||
861 | /* Locate the dtor of TYPE. */ | |
862 | ||
863 | static tree | |
864 | locate_dtor (type, client) | |
865 | tree type; | |
866 | void *client ATTRIBUTE_UNUSED; | |
867 | { | |
868 | tree fns; | |
869 | ||
870 | if (!TYPE_HAS_DESTRUCTOR (type)) | |
871 | return NULL_TREE; | |
872 | fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), | |
873 | CLASSTYPE_DESTRUCTOR_SLOT); | |
874 | return fns; | |
875 | } | |
876 | ||
877 | /* Locate the default ctor of TYPE. */ | |
878 | ||
879 | static tree | |
880 | locate_ctor (type, client) | |
881 | tree type; | |
882 | void *client ATTRIBUTE_UNUSED; | |
883 | { | |
884 | tree fns; | |
885 | ||
886 | if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) | |
887 | return NULL_TREE; | |
888 | ||
889 | fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), | |
890 | CLASSTYPE_CONSTRUCTOR_SLOT); | |
891 | for (; fns; fns = OVL_NEXT (fns)) | |
892 | { | |
893 | tree fn = OVL_CURRENT (fns); | |
894 | tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); | |
895 | ||
896 | if (sufficient_parms_p (TREE_CHAIN (parms))) | |
897 | return fn; | |
898 | } | |
899 | return NULL_TREE; | |
900 | } | |
901 | ||
902 | struct copy_data | |
903 | { | |
904 | tree name; | |
905 | int quals; | |
906 | }; | |
907 | ||
908 | /* Locate the copy ctor or copy assignment of TYPE. CLIENT_ | |
909 | points to a COPY_DATA holding the name (NULL for the ctor) | |
910 | and desired qualifiers of the source operand. */ | |
911 | ||
912 | static tree | |
913 | locate_copy (type, client_) | |
914 | tree type; | |
915 | void *client_; | |
916 | { | |
917 | struct copy_data *client = (struct copy_data *)client_; | |
918 | tree fns; | |
919 | int ix = -1; | |
920 | tree best = NULL_TREE; | |
921 | int excess_p = 0; | |
922 | ||
923 | if (client->name) | |
924 | { | |
925 | if (TYPE_HAS_ASSIGN_REF (type)) | |
926 | ix = lookup_fnfields_1 (type, client->name); | |
927 | } | |
928 | else if (TYPE_HAS_INIT_REF (type)) | |
929 | ix = CLASSTYPE_CONSTRUCTOR_SLOT; | |
930 | if (ix < 0) | |
931 | return NULL_TREE; | |
932 | fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), ix); | |
933 | ||
934 | for (; fns; fns = OVL_NEXT (fns)) | |
935 | { | |
936 | tree fn = OVL_CURRENT (fns); | |
937 | tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn)); | |
938 | tree src_type; | |
939 | int excess; | |
940 | int quals; | |
941 | ||
942 | parms = TREE_CHAIN (parms); | |
943 | if (!parms) | |
944 | continue; | |
945 | src_type = TREE_VALUE (parms); | |
946 | if (TREE_CODE (src_type) == REFERENCE_TYPE) | |
947 | src_type = TREE_TYPE (src_type); | |
948 | if (!same_type_ignoring_top_level_qualifiers_p (src_type, type)) | |
949 | continue; | |
950 | if (!sufficient_parms_p (TREE_CHAIN (parms))) | |
951 | continue; | |
89d684bb | 952 | quals = cp_type_quals (src_type); |
03378143 NS |
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 | ||
9eb71d8c MM |
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. */ | |
972 | ||
973 | tree | |
974 | implicitly_declare_fn (kind, type, const_p) | |
975 | special_function_kind kind; | |
976 | tree type; | |
977 | int const_p; | |
978 | { | |
979 | tree declspecs = NULL_TREE; | |
980 | tree fn, args = NULL_TREE; | |
03378143 | 981 | tree raises = empty_except_spec; |
9eb71d8c | 982 | int retref = 0; |
a2095778 | 983 | int has_parm = 0; |
9eb71d8c MM |
984 | tree name = constructor_name (TYPE_IDENTIFIER (type)); |
985 | ||
986 | switch (kind) | |
987 | { | |
9eb71d8c | 988 | case sfk_destructor: |
03378143 | 989 | /* Destructor. */ |
718b8ea5 | 990 | name = build_nt (BIT_NOT_EXPR, name); |
9eb71d8c | 991 | args = void_list_node; |
03378143 | 992 | raises = synthesize_exception_spec (type, &locate_dtor, 0); |
9eb71d8c MM |
993 | break; |
994 | ||
995 | case sfk_constructor: | |
996 | /* Default constructor. */ | |
997 | args = void_list_node; | |
03378143 | 998 | raises = synthesize_exception_spec (type, &locate_ctor, 0); |
9eb71d8c MM |
999 | break; |
1000 | ||
1001 | case sfk_copy_constructor: | |
9eb71d8c | 1002 | case sfk_assignment_operator: |
03378143 NS |
1003 | { |
1004 | struct copy_data data; | |
f62ea157 | 1005 | tree argtype = type; |
03378143 | 1006 | |
a2095778 NS |
1007 | has_parm = 1; |
1008 | data.name = NULL; | |
1009 | data.quals = 0; | |
1010 | if (kind == sfk_assignment_operator) | |
1011 | { | |
1012 | retref = 1; | |
1013 | declspecs = build_tree_list (NULL_TREE, type); | |
9eb71d8c | 1014 | |
a2095778 NS |
1015 | name = ansi_assopname (NOP_EXPR); |
1016 | data.name = name; | |
1017 | } | |
9eb71d8c | 1018 | if (const_p) |
a2095778 NS |
1019 | { |
1020 | data.quals = TYPE_QUAL_CONST; | |
f62ea157 | 1021 | argtype = build_qualified_type (argtype, TYPE_QUAL_CONST); |
a2095778 NS |
1022 | } |
1023 | ||
f62ea157 | 1024 | argtype = build_reference_type (argtype); |
a2095778 NS |
1025 | args = build_tree_list (hash_tree_chain (argtype, NULL_TREE), |
1026 | get_identifier ("_ctor_arg")); | |
1027 | args = tree_cons (NULL_TREE, args, void_list_node); | |
1028 | ||
03378143 | 1029 | raises = synthesize_exception_spec (type, &locate_copy, &data); |
9eb71d8c | 1030 | break; |
03378143 | 1031 | } |
9eb71d8c | 1032 | default: |
a98facb0 | 1033 | abort (); |
9eb71d8c MM |
1034 | } |
1035 | ||
1036 | TREE_PARMLIST (args) = 1; | |
1037 | ||
1038 | { | |
03378143 | 1039 | tree declarator = make_call_declarator (name, args, NULL_TREE, raises); |
a2095778 | 1040 | |
9eb71d8c | 1041 | if (retref) |
718b8ea5 | 1042 | declarator = build_nt (ADDR_EXPR, declarator); |
9eb71d8c MM |
1043 | |
1044 | fn = grokfield (declarator, declspecs, NULL_TREE, NULL_TREE, NULL_TREE); | |
a2095778 NS |
1045 | if (has_parm) |
1046 | TREE_USED (FUNCTION_FIRST_USER_PARM (fn)) = 1; | |
9eb71d8c MM |
1047 | } |
1048 | ||
1049 | my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 20000408); | |
1050 | ||
c727aa5e | 1051 | DECL_ARTIFICIAL (fn) = 1; |
9eb71d8c | 1052 | DECL_NOT_REALLY_EXTERN (fn) = 1; |
79065db2 | 1053 | DECL_DECLARED_INLINE_P (fn) = 1; |
9eb71d8c MM |
1054 | DECL_INLINE (fn) = 1; |
1055 | defer_fn (fn); | |
1056 | ||
1057 | return fn; | |
1058 | } | |
e0fff4b3 JM |
1059 | |
1060 | /* Given a FUNCTION_DECL FN and a chain LIST, skip as many elements of LIST | |
1061 | as there are artificial parms in FN. */ | |
1062 | ||
1063 | tree | |
1064 | skip_artificial_parms_for (fn, list) | |
1065 | tree fn, list; | |
1066 | { | |
1067 | if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) | |
1068 | list = TREE_CHAIN (list); | |
1069 | else | |
1070 | return list; | |
1071 | ||
1072 | if (DECL_HAS_IN_CHARGE_PARM_P (fn)) | |
1073 | list = TREE_CHAIN (list); | |
1074 | if (DECL_HAS_VTT_PARM_P (fn)) | |
1075 | list = TREE_CHAIN (list); | |
1076 | return list; | |
1077 | } |