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