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