]>
Commit | Line | Data |
---|---|---|
8d08fdba MS |
1 | /* Report error messages, build initializers, and perform |
2 | some front-end optimizations for C++ compiler. | |
66543169 | 3 | Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc. |
8d08fdba MS |
4 | Hacked by Michael Tiemann (tiemann@cygnus.com) |
5 | ||
6 | This file is part of GNU CC. | |
7 | ||
8 | GNU CC is free software; you can redistribute it and/or modify | |
9 | it under the terms of the GNU General Public License as published by | |
10 | the Free Software Foundation; either version 2, or (at your option) | |
11 | any later version. | |
12 | ||
13 | GNU CC is distributed in the hope that it will be useful, | |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | GNU General Public License for more details. | |
17 | ||
18 | You should have received a copy of the GNU General Public License | |
19 | along with GNU CC; see the file COPYING. If not, write to | |
6bc06b8f RK |
20 | the Free Software Foundation, 59 Temple Place - Suite 330, |
21 | Boston, MA 02111-1307, USA. */ | |
8d08fdba MS |
22 | |
23 | ||
24 | /* This file is part of the C++ front end. | |
25 | It contains routines to build C++ expressions given their operands, | |
26 | including computing the types of the result, C and C++ specific error | |
27 | checks, and some optimization. | |
28 | ||
29 | There are also routines to build RETURN_STMT nodes and CASE_STMT nodes, | |
30 | and to process initializations in declarations (since they work | |
31 | like a strange sort of assignment). */ | |
32 | ||
33 | #include "config.h" | |
8d052bc7 | 34 | #include "system.h" |
8d08fdba MS |
35 | #include "tree.h" |
36 | #include "cp-tree.h" | |
37 | #include "flags.h" | |
12027a89 | 38 | #include "toplev.h" |
8d08fdba | 39 | |
49c249e1 | 40 | static tree process_init_constructor PROTO((tree, tree, tree *)); |
d8e178a0 | 41 | static void ack PVPROTO ((const char *, ...)) ATTRIBUTE_PRINTF_1; |
8d08fdba | 42 | |
8d08fdba MS |
43 | /* Print an error message stemming from an attempt to use |
44 | BASETYPE as a base class for TYPE. */ | |
e92cc029 | 45 | |
8d08fdba MS |
46 | tree |
47 | error_not_base_type (basetype, type) | |
48 | tree basetype, type; | |
49 | { | |
50 | if (TREE_CODE (basetype) == FUNCTION_DECL) | |
51 | basetype = DECL_CLASS_CONTEXT (basetype); | |
8251199e | 52 | cp_error ("type `%T' is not a base type for type `%T'", basetype, type); |
8d08fdba MS |
53 | return error_mark_node; |
54 | } | |
55 | ||
56 | tree | |
57 | binfo_or_else (parent_or_type, type) | |
58 | tree parent_or_type, type; | |
59 | { | |
60 | tree binfo; | |
61 | if (TYPE_MAIN_VARIANT (parent_or_type) == TYPE_MAIN_VARIANT (type)) | |
a4443a08 | 62 | return TYPE_BINFO (parent_or_type); |
8926095f | 63 | if ((binfo = get_binfo (parent_or_type, TYPE_MAIN_VARIANT (type), 0))) |
8d08fdba MS |
64 | { |
65 | if (binfo == error_mark_node) | |
66 | return NULL_TREE; | |
67 | return binfo; | |
68 | } | |
69 | error_not_base_type (parent_or_type, type); | |
70 | return NULL_TREE; | |
71 | } | |
72 | ||
8d08fdba MS |
73 | /* According to ARM $7.1.6, "A `const' object may be initialized, but its |
74 | value may not be changed thereafter. Thus, we emit hard errors for these, | |
75 | rather than just pedwarns. If `SOFT' is 1, then we just pedwarn. (For | |
76 | example, conversions to references.) */ | |
e92cc029 | 77 | |
8d08fdba MS |
78 | void |
79 | readonly_error (arg, string, soft) | |
80 | tree arg; | |
d8e178a0 | 81 | const char *string; |
8d08fdba MS |
82 | int soft; |
83 | { | |
d8e178a0 KG |
84 | const char *fmt; |
85 | void (*fn) PVPROTO ((const char *, ...)); | |
8d08fdba MS |
86 | |
87 | if (soft) | |
fc378698 | 88 | fn = cp_pedwarn; |
8d08fdba | 89 | else |
fc378698 | 90 | fn = cp_error; |
8d08fdba MS |
91 | |
92 | if (TREE_CODE (arg) == COMPONENT_REF) | |
93 | { | |
94 | if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0)))) | |
8251199e | 95 | fmt = "%s of member `%D' in read-only structure"; |
8d08fdba | 96 | else |
8251199e JM |
97 | fmt = "%s of read-only member `%D'"; |
98 | (*fn) (fmt, string, TREE_OPERAND (arg, 1)); | |
8d08fdba MS |
99 | } |
100 | else if (TREE_CODE (arg) == VAR_DECL) | |
101 | { | |
102 | if (DECL_LANG_SPECIFIC (arg) | |
103 | && DECL_IN_AGGR_P (arg) | |
104 | && !TREE_STATIC (arg)) | |
8251199e | 105 | fmt = "%s of constant field `%D'"; |
8d08fdba | 106 | else |
8251199e JM |
107 | fmt = "%s of read-only variable `%D'"; |
108 | (*fn) (fmt, string, arg); | |
8d08fdba MS |
109 | } |
110 | else if (TREE_CODE (arg) == PARM_DECL) | |
8251199e | 111 | (*fn) ("%s of read-only parameter `%D'", string, arg); |
8d08fdba MS |
112 | else if (TREE_CODE (arg) == INDIRECT_REF |
113 | && TREE_CODE (TREE_TYPE (TREE_OPERAND (arg, 0))) == REFERENCE_TYPE | |
114 | && (TREE_CODE (TREE_OPERAND (arg, 0)) == VAR_DECL | |
115 | || TREE_CODE (TREE_OPERAND (arg, 0)) == PARM_DECL)) | |
8251199e | 116 | (*fn) ("%s of read-only reference `%D'", string, TREE_OPERAND (arg, 0)); |
8d08fdba | 117 | else if (TREE_CODE (arg) == RESULT_DECL) |
8251199e | 118 | (*fn) ("%s of read-only named return value `%D'", string, arg); |
69851283 MM |
119 | else if (TREE_CODE (arg) == FUNCTION_DECL) |
120 | (*fn) ("%s of function `%D'", string, arg); | |
121 | else | |
8251199e | 122 | (*fn) ("%s of read-only location", string); |
8d08fdba MS |
123 | } |
124 | ||
a7a64a77 MM |
125 | /* If TYPE has abstract virtual functions, issue an error about trying |
126 | to create an object of that type. DECL is the object declared, or | |
127 | NULL_TREE if the declaration is unavailable. Returns 1 if an error | |
128 | occurred; zero if all was well. */ | |
e92cc029 | 129 | |
a7a64a77 | 130 | int |
8d08fdba MS |
131 | abstract_virtuals_error (decl, type) |
132 | tree decl; | |
133 | tree type; | |
134 | { | |
a7a64a77 | 135 | tree u; |
4a67c9e9 MH |
136 | tree tu; |
137 | ||
a7a64a77 MM |
138 | if (!CLASS_TYPE_P (type) || !CLASSTYPE_ABSTRACT_VIRTUALS (type)) |
139 | return 0; | |
140 | ||
141 | u = CLASSTYPE_ABSTRACT_VIRTUALS (type); | |
8d08fdba MS |
142 | if (decl) |
143 | { | |
144 | if (TREE_CODE (decl) == RESULT_DECL) | |
a7a64a77 | 145 | return 0; |
8d08fdba MS |
146 | |
147 | if (TREE_CODE (decl) == VAR_DECL) | |
8251199e | 148 | cp_error ("cannot declare variable `%D' to be of type `%T'", |
8d08fdba MS |
149 | decl, type); |
150 | else if (TREE_CODE (decl) == PARM_DECL) | |
8251199e | 151 | cp_error ("cannot declare parameter `%D' to be of type `%T'", |
8d08fdba MS |
152 | decl, type); |
153 | else if (TREE_CODE (decl) == FIELD_DECL) | |
8251199e | 154 | cp_error ("cannot declare field `%D' to be of type `%T'", |
8d08fdba MS |
155 | decl, type); |
156 | else if (TREE_CODE (decl) == FUNCTION_DECL | |
157 | && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE) | |
8251199e | 158 | cp_error ("invalid return type for method `%#D'", decl); |
8d08fdba | 159 | else if (TREE_CODE (decl) == FUNCTION_DECL) |
8251199e | 160 | cp_error ("invalid return type for function `%#D'", decl); |
8d08fdba | 161 | } |
4a67c9e9 | 162 | else |
8251199e | 163 | cp_error ("cannot allocate an object of type `%T'", type); |
4a67c9e9 | 164 | |
8d08fdba MS |
165 | /* Only go through this once. */ |
166 | if (TREE_PURPOSE (u) == NULL_TREE) | |
167 | { | |
8d08fdba | 168 | TREE_PURPOSE (u) = error_mark_node; |
4a67c9e9 | 169 | |
8ebeee52 JM |
170 | error (" since the following virtual functions are abstract:"); |
171 | for (tu = u; tu; tu = TREE_CHAIN (tu)) | |
83f660b7 | 172 | cp_error_at ("\t%#D", TREE_VALUE (tu)); |
8d08fdba | 173 | } |
4a67c9e9 | 174 | else |
8ebeee52 | 175 | cp_error (" since type `%T' has abstract virtual functions", type); |
a7a64a77 MM |
176 | |
177 | return 1; | |
8d08fdba MS |
178 | } |
179 | ||
8d08fdba MS |
180 | /* Print an error message for invalid use of an incomplete type. |
181 | VALUE is the expression that was used (or 0 if that isn't known) | |
182 | and TYPE is the type that was invalid. */ | |
183 | ||
184 | void | |
185 | incomplete_type_error (value, type) | |
186 | tree value; | |
187 | tree type; | |
188 | { | |
8d08fdba MS |
189 | /* Avoid duplicate error message. */ |
190 | if (TREE_CODE (type) == ERROR_MARK) | |
191 | return; | |
192 | ||
66543169 NS |
193 | retry: |
194 | /* We must print an error message. Be clever about what it says. */ | |
195 | ||
196 | switch (TREE_CODE (type)) | |
8d08fdba | 197 | { |
66543169 NS |
198 | case RECORD_TYPE: |
199 | case UNION_TYPE: | |
200 | case ENUMERAL_TYPE: | |
201 | cp_error ("invalid use of undefined type `%#T'", type); | |
202 | cp_error_at ("forward declaration of `%#T'", type); | |
203 | break; | |
204 | ||
205 | case VOID_TYPE: | |
206 | cp_error ("invalid use of void expression"); | |
207 | break; | |
208 | ||
209 | case ARRAY_TYPE: | |
210 | if (TYPE_DOMAIN (type)) | |
211 | { | |
212 | type = TREE_TYPE (type); | |
213 | goto retry; | |
214 | } | |
215 | cp_error ("invalid use of array with unspecified bounds"); | |
216 | break; | |
217 | ||
218 | case OFFSET_TYPE: | |
219 | bad_member: | |
220 | cp_error ("invalid use of member (did you forget the `&' ?)"); | |
221 | break; | |
222 | ||
223 | case TEMPLATE_TYPE_PARM: | |
224 | cp_error ("invalid use of template type parameter"); | |
225 | break; | |
226 | ||
227 | case UNKNOWN_TYPE: | |
228 | if (value && TREE_CODE (value) == COMPONENT_REF) | |
229 | goto bad_member; | |
230 | else if (value && TREE_CODE (value) == ADDR_EXPR) | |
231 | cp_error ("address of overloaded function with no contextual type information"); | |
232 | else if (value && TREE_CODE (value) == OVERLOAD) | |
233 | cp_error ("overloaded function with no contextual type information"); | |
234 | else | |
235 | cp_error ("insufficient contextual information to determine type"); | |
236 | break; | |
237 | ||
238 | default: | |
239 | my_friendly_abort (108); | |
8d08fdba | 240 | } |
66543169 NS |
241 | |
242 | if (value != 0 && (TREE_CODE (value) == VAR_DECL | |
243 | || TREE_CODE (value) == PARM_DECL)) | |
244 | cp_error_at ("incomplete `%D' defined here", value); | |
8d08fdba MS |
245 | } |
246 | ||
247 | /* Like error(), but don't call report_error_function(). */ | |
e92cc029 | 248 | |
8d08fdba | 249 | static void |
d8e178a0 | 250 | ack VPROTO ((const char *msg, ...)) |
8d08fdba | 251 | { |
d8e178a0 KG |
252 | #ifndef ANSI_PROTOTYPES |
253 | const char *msg; | |
254 | #endif | |
255 | va_list ap; | |
8d08fdba | 256 | |
d8e178a0 KG |
257 | VA_START (ap, msg); |
258 | ||
259 | #ifndef ANSI_PROTOTYPES | |
260 | msg = va_arg (ap, const char *); | |
261 | #endif | |
262 | ||
8d08fdba MS |
263 | if (input_filename) |
264 | fprintf (stderr, "%s:%d: ", input_filename, lineno); | |
265 | else | |
266 | fprintf (stderr, "%s: ", progname); | |
267 | ||
d8e178a0 KG |
268 | vfprintf (stderr, msg, ap); |
269 | va_end (ap); | |
270 | ||
8d08fdba MS |
271 | fprintf (stderr, "\n"); |
272 | } | |
273 | ||
274 | /* There are times when the compiler can get very confused, confused | |
275 | to the point of giving up by aborting, simply because of previous | |
276 | input errors. It is much better to have the user go back and | |
277 | correct those errors first, and see if it makes us happier, than it | |
278 | is to abort on him. This is because when one has a 10,000 line | |
279 | program, and the compiler comes back with ``core dump'', the user | |
280 | is left not knowing even where to begin to fix things and no place | |
281 | to even try and work around things. | |
282 | ||
283 | The parameter is to uniquely identify the problem to the user, so | |
284 | that they can say, I am having problem 59, and know that fix 7 will | |
285 | probably solve their problem. Or, we can document what problem | |
286 | 59 is, so they can understand how to work around it, should they | |
287 | ever run into it. | |
288 | ||
8d08fdba MS |
289 | We used to tell people to "fix the above error[s] and try recompiling |
290 | the program" via a call to fatal, but that message tended to look | |
291 | silly. So instead, we just do the equivalent of a call to fatal in the | |
51924768 | 292 | same situation (call exit). |
8d08fdba | 293 | |
51924768 JM |
294 | We used to assign sequential numbers for the aborts; now we use an |
295 | encoding of the date the abort was added, since that has more meaning | |
296 | when we only see the error message. */ | |
8d08fdba MS |
297 | |
298 | static int abortcount = 0; | |
299 | ||
300 | void | |
301 | my_friendly_abort (i) | |
302 | int i; | |
303 | { | |
304 | /* if the previous error came through here, i.e. report_error_function | |
305 | ended up calling us again, don't just exit; we want a diagnostic of | |
306 | some kind. */ | |
307 | if (abortcount == 1) | |
308 | current_function_decl = NULL_TREE; | |
309 | else if (errorcount > 0 || sorrycount > 0) | |
310 | { | |
311 | if (abortcount > 1) | |
312 | { | |
313 | if (i == 0) | |
314 | ack ("Internal compiler error."); | |
315 | else | |
316 | ack ("Internal compiler error %d.", i); | |
70ade953 | 317 | ack ("Please submit a full bug report."); |
7fc2d503 | 318 | ack ("See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions."); |
8d08fdba MS |
319 | } |
320 | else | |
8251199e | 321 | error ("confused by earlier errors, bailing out"); |
8d08fdba MS |
322 | |
323 | exit (34); | |
324 | } | |
325 | ++abortcount; | |
326 | ||
327 | if (i == 0) | |
8251199e | 328 | error ("Internal compiler error."); |
8d08fdba | 329 | else |
8251199e | 330 | error ("Internal compiler error %d.", i); |
8d08fdba | 331 | |
70ade953 | 332 | error ("Please submit a full bug report."); |
e547bb67 | 333 | fatal ("See <URL:http://www.gnu.org/software/gcc/faq.html#bugreport> for instructions."); |
8d08fdba MS |
334 | } |
335 | ||
336 | void | |
337 | my_friendly_assert (cond, where) | |
338 | int cond, where; | |
339 | { | |
340 | if (cond == 0) | |
341 | my_friendly_abort (where); | |
342 | } | |
343 | \f | |
8d08fdba MS |
344 | /* Perform appropriate conversions on the initial value of a variable, |
345 | store it in the declaration DECL, | |
346 | and print any error messages that are appropriate. | |
347 | If the init is invalid, store an ERROR_MARK. | |
348 | ||
349 | C++: Note that INIT might be a TREE_LIST, which would mean that it is | |
350 | a base class initializer for some aggregate type, hopefully compatible | |
351 | with DECL. If INIT is a single element, and DECL is an aggregate | |
352 | type, we silently convert INIT into a TREE_LIST, allowing a constructor | |
353 | to be called. | |
354 | ||
355 | If INIT is a TREE_LIST and there is no constructor, turn INIT | |
356 | into a CONSTRUCTOR and use standard initialization techniques. | |
357 | Perhaps a warning should be generated? | |
358 | ||
359 | Returns value of initializer if initialization could not be | |
360 | performed for static variable. In that case, caller must do | |
361 | the storing. */ | |
362 | ||
363 | tree | |
364 | store_init_value (decl, init) | |
365 | tree decl, init; | |
366 | { | |
367 | register tree value, type; | |
368 | ||
369 | /* If variable's type was invalidly declared, just ignore it. */ | |
370 | ||
371 | type = TREE_TYPE (decl); | |
372 | if (TREE_CODE (type) == ERROR_MARK) | |
373 | return NULL_TREE; | |
374 | ||
878cd289 MS |
375 | #if 0 |
376 | /* This breaks arrays, and should not have any effect for other decls. */ | |
8d08fdba MS |
377 | /* Take care of C++ business up here. */ |
378 | type = TYPE_MAIN_VARIANT (type); | |
878cd289 | 379 | #endif |
8d08fdba | 380 | |
e8abc66f | 381 | if (IS_AGGR_TYPE (type)) |
8d08fdba | 382 | { |
e8abc66f MS |
383 | if (! TYPE_HAS_TRIVIAL_INIT_REF (type) |
384 | && TREE_CODE (init) != CONSTRUCTOR) | |
385 | my_friendly_abort (109); | |
386 | ||
6eabb241 | 387 | if (TREE_CODE (init) == TREE_LIST) |
8d08fdba | 388 | { |
8251199e | 389 | cp_error ("constructor syntax used, but no constructor declared for type `%T'", type); |
8d08fdba MS |
390 | init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init)); |
391 | } | |
392 | #if 0 | |
393 | if (TREE_CODE (init) == CONSTRUCTOR) | |
394 | { | |
395 | tree field; | |
8d08fdba MS |
396 | |
397 | /* Check that we're really an aggregate as ARM 8.4.1 defines it. */ | |
398 | if (CLASSTYPE_N_BASECLASSES (type)) | |
8251199e | 399 | cp_error_at ("initializer list construction invalid for derived class object `%D'", decl); |
8d08fdba | 400 | if (CLASSTYPE_VTBL_PTR (type)) |
8251199e | 401 | cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl); |
8d08fdba MS |
402 | if (TYPE_NEEDS_CONSTRUCTING (type)) |
403 | { | |
8251199e JM |
404 | cp_error_at ("initializer list construction invalid for `%D'", decl); |
405 | error ("due to the presence of a constructor"); | |
8d08fdba MS |
406 | } |
407 | for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) | |
408 | if (TREE_PRIVATE (field) || TREE_PROTECTED (field)) | |
409 | { | |
8251199e JM |
410 | cp_error_at ("initializer list construction invalid for `%D'", decl); |
411 | cp_error_at ("due to non-public access of member `%D'", field); | |
8d08fdba | 412 | } |
72b7eeff MS |
413 | for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field)) |
414 | if (TREE_PRIVATE (field) || TREE_PROTECTED (field)) | |
8d08fdba | 415 | { |
8251199e JM |
416 | cp_error_at ("initializer list construction invalid for `%D'", decl); |
417 | cp_error_at ("due to non-public access of member `%D'", field); | |
8d08fdba MS |
418 | } |
419 | } | |
420 | #endif | |
421 | } | |
422 | else if (TREE_CODE (init) == TREE_LIST | |
423 | && TREE_TYPE (init) != unknown_type_node) | |
424 | { | |
425 | if (TREE_CODE (decl) == RESULT_DECL) | |
426 | { | |
427 | if (TREE_CHAIN (init)) | |
428 | { | |
8251199e | 429 | warning ("comma expression used to initialize return value"); |
8d08fdba MS |
430 | init = build_compound_expr (init); |
431 | } | |
432 | else | |
433 | init = TREE_VALUE (init); | |
434 | } | |
8d08fdba MS |
435 | else if (TREE_CODE (init) == TREE_LIST |
436 | && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) | |
437 | { | |
8251199e | 438 | error ("cannot initialize arrays using this syntax"); |
8d08fdba MS |
439 | return NULL_TREE; |
440 | } | |
441 | else | |
442 | { | |
443 | /* We get here with code like `int a (2);' */ | |
444 | ||
445 | if (TREE_CHAIN (init) != NULL_TREE) | |
446 | { | |
8251199e | 447 | pedwarn ("initializer list being treated as compound expression"); |
8d08fdba MS |
448 | init = build_compound_expr (init); |
449 | } | |
450 | else | |
451 | init = TREE_VALUE (init); | |
452 | } | |
453 | } | |
454 | ||
455 | /* End of special C++ code. */ | |
456 | ||
457 | /* Digest the specified initializer into an expression. */ | |
458 | ||
459 | value = digest_init (type, init, (tree *) 0); | |
460 | ||
461 | /* Store the expression if valid; else report error. */ | |
462 | ||
463 | if (TREE_CODE (value) == ERROR_MARK) | |
464 | ; | |
7834ab39 MS |
465 | /* Other code expects that initializers for objects of types that need |
466 | constructing never make it into DECL_INITIAL, and passes 'init' to | |
f1dedc31 | 467 | build_aggr_init without checking DECL_INITIAL. So just return. */ |
7834ab39 MS |
468 | else if (TYPE_NEEDS_CONSTRUCTING (type)) |
469 | return value; | |
8d08fdba MS |
470 | else if (TREE_STATIC (decl) |
471 | && (! TREE_CONSTANT (value) | |
8ccc31eb | 472 | || ! initializer_constant_valid_p (value, TREE_TYPE (value)) |
8926095f MS |
473 | #if 0 |
474 | /* A STATIC PUBLIC int variable doesn't have to be | |
475 | run time inited when doing pic. (mrs) */ | |
8d08fdba MS |
476 | /* Since ctors and dtors are the only things that can |
477 | reference vtables, and they are always written down | |
38e01259 | 478 | the vtable definition, we can leave the |
8d08fdba MS |
479 | vtables in initialized data space. |
480 | However, other initialized data cannot be initialized | |
481 | this way. Instead a global file-level initializer | |
482 | must do the job. */ | |
8926095f MS |
483 | || (flag_pic && !DECL_VIRTUAL_P (decl) && TREE_PUBLIC (decl)) |
484 | #endif | |
485 | )) | |
486 | ||
8d08fdba | 487 | return value; |
f376e137 | 488 | #if 0 /* No, that's C. jason 9/19/94 */ |
8d08fdba MS |
489 | else |
490 | { | |
6eabb241 | 491 | if (pedantic && TREE_CODE (value) == CONSTRUCTOR) |
8d08fdba MS |
492 | { |
493 | if (! TREE_CONSTANT (value) || ! TREE_STATIC (value)) | |
8251199e | 494 | pedwarn ("ANSI C++ forbids non-constant aggregate initializer expressions"); |
8d08fdba MS |
495 | } |
496 | } | |
f376e137 | 497 | #endif |
4d6abc1c MM |
498 | |
499 | /* Store the VALUE in DECL_INITIAL. If we're building a | |
500 | statement-tree we will actually expand the initialization later | |
501 | when we output this function. */ | |
8d08fdba MS |
502 | DECL_INITIAL (decl) = value; |
503 | return NULL_TREE; | |
504 | } | |
505 | \f | |
506 | /* Digest the parser output INIT as an initializer for type TYPE. | |
507 | Return a C expression of type TYPE to represent the initial value. | |
508 | ||
509 | If TAIL is nonzero, it points to a variable holding a list of elements | |
510 | of which INIT is the first. We update the list stored there by | |
511 | removing from the head all the elements that we use. | |
512 | Normally this is only one; we use more than one element only if | |
513 | TYPE is an aggregate and INIT is not a constructor. */ | |
514 | ||
515 | tree | |
516 | digest_init (type, init, tail) | |
517 | tree type, init, *tail; | |
518 | { | |
519 | enum tree_code code = TREE_CODE (type); | |
00595019 | 520 | tree element = NULL_TREE; |
a703fb38 | 521 | tree old_tail_contents = NULL_TREE; |
8d08fdba MS |
522 | /* Nonzero if INIT is a braced grouping, which comes in as a CONSTRUCTOR |
523 | tree node which has no TREE_TYPE. */ | |
524 | int raw_constructor; | |
525 | ||
526 | /* By default, assume we use one element from a list. | |
527 | We correct this later in the sole case where it is not true. */ | |
528 | ||
529 | if (tail) | |
530 | { | |
531 | old_tail_contents = *tail; | |
532 | *tail = TREE_CHAIN (*tail); | |
533 | } | |
534 | ||
535 | if (init == error_mark_node || (TREE_CODE (init) == TREE_LIST | |
536 | && TREE_VALUE (init) == error_mark_node)) | |
537 | return error_mark_node; | |
538 | ||
539 | /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ | |
540 | if (TREE_CODE (init) == NON_LVALUE_EXPR) | |
541 | init = TREE_OPERAND (init, 0); | |
542 | ||
e6267549 JM |
543 | if (TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == type) |
544 | return init; | |
545 | ||
8d08fdba MS |
546 | raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0; |
547 | ||
dc26f471 | 548 | if (raw_constructor |
8d08fdba MS |
549 | && CONSTRUCTOR_ELTS (init) != 0 |
550 | && TREE_CHAIN (CONSTRUCTOR_ELTS (init)) == 0) | |
551 | { | |
552 | element = TREE_VALUE (CONSTRUCTOR_ELTS (init)); | |
553 | /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */ | |
554 | if (element && TREE_CODE (element) == NON_LVALUE_EXPR) | |
555 | element = TREE_OPERAND (element, 0); | |
556 | if (element == error_mark_node) | |
557 | return element; | |
558 | } | |
559 | ||
8d08fdba MS |
560 | /* Initialization of an array of chars from a string constant |
561 | optionally enclosed in braces. */ | |
562 | ||
563 | if (code == ARRAY_TYPE) | |
564 | { | |
8c90d611 JM |
565 | tree typ1; |
566 | ||
567 | if (TREE_CODE (init) == TREE_LIST) | |
568 | { | |
8251199e | 569 | error ("initializing array with parameter list"); |
8c90d611 JM |
570 | return error_mark_node; |
571 | } | |
572 | ||
573 | typ1 = TYPE_MAIN_VARIANT (TREE_TYPE (type)); | |
8d08fdba MS |
574 | if ((typ1 == char_type_node |
575 | || typ1 == signed_char_type_node | |
576 | || typ1 == unsigned_char_type_node | |
577 | || typ1 == unsigned_wchar_type_node | |
578 | || typ1 == signed_wchar_type_node) | |
579 | && ((init && TREE_CODE (init) == STRING_CST) | |
580 | || (element && TREE_CODE (element) == STRING_CST))) | |
581 | { | |
582 | tree string = element ? element : init; | |
583 | ||
584 | if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) | |
585 | != char_type_node) | |
586 | && TYPE_PRECISION (typ1) == BITS_PER_UNIT) | |
587 | { | |
8251199e | 588 | error ("char-array initialized from wide string"); |
8d08fdba MS |
589 | return error_mark_node; |
590 | } | |
591 | if ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (string))) | |
592 | == char_type_node) | |
593 | && TYPE_PRECISION (typ1) != BITS_PER_UNIT) | |
594 | { | |
8251199e | 595 | error ("int-array initialized from non-wide string"); |
8d08fdba MS |
596 | return error_mark_node; |
597 | } | |
598 | ||
8d08fdba MS |
599 | TREE_TYPE (string) = type; |
600 | if (TYPE_DOMAIN (type) != 0 | |
601 | && TREE_CONSTANT (TYPE_SIZE (type))) | |
602 | { | |
603 | register int size | |
604 | = TREE_INT_CST_LOW (TYPE_SIZE (type)); | |
605 | size = (size + BITS_PER_UNIT - 1) / BITS_PER_UNIT; | |
606 | /* In C it is ok to subtract 1 from the length of the string | |
607 | because it's ok to ignore the terminating null char that is | |
608 | counted in the length of the constant, but in C++ this would | |
609 | be invalid. */ | |
610 | if (size < TREE_STRING_LENGTH (string)) | |
8251199e | 611 | pedwarn ("initializer-string for array of chars is too long"); |
8d08fdba MS |
612 | } |
613 | return string; | |
614 | } | |
615 | } | |
616 | ||
617 | /* Handle scalar types, including conversions, | |
618 | and signature pointers and references. */ | |
619 | ||
620 | if (code == INTEGER_TYPE || code == REAL_TYPE || code == POINTER_TYPE | |
621 | || code == ENUMERAL_TYPE || code == REFERENCE_TYPE | |
37c46b43 | 622 | || code == BOOLEAN_TYPE || code == COMPLEX_TYPE |
6eabb241 | 623 | || TYPE_PTRMEMFUNC_P (type)) |
8d08fdba MS |
624 | { |
625 | if (raw_constructor) | |
626 | { | |
627 | if (element == 0) | |
628 | { | |
8251199e | 629 | error ("initializer for scalar variable requires one element"); |
8d08fdba MS |
630 | return error_mark_node; |
631 | } | |
632 | init = element; | |
633 | } | |
dc26f471 | 634 | while (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init)) |
b7484fbe | 635 | { |
8251199e | 636 | cp_pedwarn ("braces around scalar initializer for `%T'", type); |
b7484fbe MS |
637 | init = CONSTRUCTOR_ELTS (init); |
638 | if (TREE_CHAIN (init)) | |
8251199e | 639 | cp_pedwarn ("ignoring extra initializers for `%T'", type); |
b7484fbe MS |
640 | init = TREE_VALUE (init); |
641 | } | |
8d08fdba MS |
642 | |
643 | return convert_for_initialization (0, type, init, LOOKUP_NORMAL, | |
644 | "initialization", NULL_TREE, 0); | |
645 | } | |
646 | ||
647 | /* Come here only for records and arrays (and unions with constructors). */ | |
648 | ||
649 | if (TYPE_SIZE (type) && ! TREE_CONSTANT (TYPE_SIZE (type))) | |
650 | { | |
8251199e | 651 | cp_error ("variable-sized object of type `%T' may not be initialized", |
7177d104 | 652 | type); |
8d08fdba MS |
653 | return error_mark_node; |
654 | } | |
655 | ||
829fd7e0 | 656 | if (code == ARRAY_TYPE || IS_AGGR_TYPE_CODE (code)) |
8d08fdba | 657 | { |
f30432d7 MS |
658 | if (raw_constructor && TYPE_NON_AGGREGATE_CLASS (type)) |
659 | { | |
8251199e | 660 | cp_error ("subobject of type `%T' must be initialized by constructor, not by `%E'", |
f30432d7 MS |
661 | type, init); |
662 | return error_mark_node; | |
663 | } | |
664 | else if (raw_constructor) | |
8d08fdba | 665 | return process_init_constructor (type, init, (tree *)0); |
dc26f471 JM |
666 | else if (can_convert_arg (type, TREE_TYPE (init), init) |
667 | || TYPE_NON_AGGREGATE_CLASS (type)) | |
668 | /* These are never initialized from multiple constructor elements. */; | |
8d08fdba MS |
669 | else if (tail != 0) |
670 | { | |
671 | *tail = old_tail_contents; | |
672 | return process_init_constructor (type, 0, tail); | |
673 | } | |
d22c8596 | 674 | |
8d08fdba | 675 | if (code != ARRAY_TYPE) |
dc26f471 JM |
676 | { |
677 | int flags = LOOKUP_NORMAL; | |
678 | /* Initialization from { } is copy-initialization. */ | |
679 | if (tail) | |
680 | flags |= LOOKUP_ONLYCONVERTING; | |
681 | ||
682 | return convert_for_initialization (NULL_TREE, type, init, flags, | |
683 | "initialization", NULL_TREE, 0); | |
684 | } | |
8d08fdba MS |
685 | } |
686 | ||
8251199e | 687 | error ("invalid initializer"); |
8d08fdba MS |
688 | return error_mark_node; |
689 | } | |
690 | \f | |
691 | /* Process a constructor for a variable of type TYPE. | |
692 | The constructor elements may be specified either with INIT or with ELTS, | |
693 | only one of which should be non-null. | |
694 | ||
695 | If INIT is specified, it is a CONSTRUCTOR node which is specifically | |
696 | and solely for initializing this datum. | |
697 | ||
698 | If ELTS is specified, it is the address of a variable containing | |
699 | a list of expressions. We take as many elements as we need | |
700 | from the head of the list and update the list. | |
701 | ||
702 | In the resulting constructor, TREE_CONSTANT is set if all elts are | |
703 | constant, and TREE_STATIC is set if, in addition, all elts are simple enough | |
704 | constants that the assembler and linker can compute them. */ | |
705 | ||
706 | static tree | |
707 | process_init_constructor (type, init, elts) | |
708 | tree type, init, *elts; | |
709 | { | |
8d08fdba MS |
710 | register tree tail; |
711 | /* List of the elements of the result constructor, | |
712 | in reverse order. */ | |
713 | register tree members = NULL; | |
e6267549 | 714 | register tree next1; |
8d08fdba MS |
715 | tree result; |
716 | int allconstant = 1; | |
717 | int allsimple = 1; | |
718 | int erroneous = 0; | |
719 | ||
720 | /* Make TAIL be the list of elements to use for the initialization, | |
721 | no matter how the data was given to us. */ | |
722 | ||
723 | if (elts) | |
724 | { | |
725 | if (warn_missing_braces) | |
8251199e | 726 | warning ("aggregate has a partly bracketed initializer"); |
8d08fdba MS |
727 | tail = *elts; |
728 | } | |
729 | else | |
730 | tail = CONSTRUCTOR_ELTS (init); | |
731 | ||
732 | /* Gobble as many elements as needed, and make a constructor or initial value | |
733 | for each element of this aggregate. Chain them together in result. | |
734 | If there are too few, use 0 for each scalar ultimate component. */ | |
735 | ||
736 | if (TREE_CODE (type) == ARRAY_TYPE) | |
737 | { | |
738 | tree domain = TYPE_DOMAIN (type); | |
739 | register long len; | |
740 | register int i; | |
741 | ||
742 | if (domain) | |
743 | len = (TREE_INT_CST_LOW (TYPE_MAX_VALUE (domain)) | |
744 | - TREE_INT_CST_LOW (TYPE_MIN_VALUE (domain)) | |
745 | + 1); | |
746 | else | |
747 | len = -1; /* Take as many as there are */ | |
748 | ||
e6267549 | 749 | for (i = 0; len < 0 || i < len; i++) |
8d08fdba | 750 | { |
e6267549 | 751 | if (tail) |
8d08fdba | 752 | { |
e6267549 JM |
753 | if (TREE_PURPOSE (tail) |
754 | && (TREE_CODE (TREE_PURPOSE (tail)) != INTEGER_CST | |
755 | || TREE_INT_CST_LOW (TREE_PURPOSE (tail)) != i)) | |
756 | sorry ("non-trivial labeled initializers"); | |
757 | ||
758 | if (TREE_VALUE (tail) != 0) | |
a5894242 | 759 | { |
e6267549 JM |
760 | tree tail1 = tail; |
761 | next1 = digest_init (TREE_TYPE (type), | |
762 | TREE_VALUE (tail), &tail1); | |
0db982be ML |
763 | if (next1 == error_mark_node) |
764 | return next1; | |
7e2067ca JM |
765 | my_friendly_assert |
766 | (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)), | |
767 | TYPE_MAIN_VARIANT (TREE_TYPE (next1))), | |
768 | 981123); | |
e6267549 JM |
769 | my_friendly_assert (tail1 == 0 |
770 | || TREE_CODE (tail1) == TREE_LIST, 319); | |
771 | if (tail == tail1 && len < 0) | |
772 | { | |
773 | error ("non-empty initializer for array of empty elements"); | |
774 | /* Just ignore what we were supposed to use. */ | |
775 | tail1 = NULL_TREE; | |
776 | } | |
777 | tail = tail1; | |
a5894242 | 778 | } |
e6267549 | 779 | else |
8d08fdba | 780 | { |
e6267549 JM |
781 | next1 = error_mark_node; |
782 | tail = TREE_CHAIN (tail); | |
8d08fdba | 783 | } |
8d08fdba | 784 | } |
e6267549 JM |
785 | else if (len < 0) |
786 | /* We're done. */ | |
787 | break; | |
788 | else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type))) | |
8d08fdba | 789 | { |
e6267549 JM |
790 | /* If this type needs constructors run for |
791 | default-initialization, we can't rely on the backend to do it | |
792 | for us, so build up TARGET_EXPRs. If the type in question is | |
793 | a class, just build one up; if it's an array, recurse. */ | |
794 | ||
795 | if (IS_AGGR_TYPE (TREE_TYPE (type))) | |
796 | next1 = build_functional_cast (TREE_TYPE (type), NULL_TREE); | |
797 | else | |
798 | next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE); | |
799 | next1 = digest_init (TREE_TYPE (type), next1, 0); | |
8d08fdba | 800 | } |
e6267549 JM |
801 | else |
802 | /* The default zero-initialization is fine for us; don't | |
803 | add anything to the CONSTRUCTOR. */ | |
804 | break; | |
8d08fdba MS |
805 | |
806 | if (next1 == error_mark_node) | |
807 | erroneous = 1; | |
808 | else if (!TREE_CONSTANT (next1)) | |
809 | allconstant = 0; | |
8ccc31eb | 810 | else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) |
8d08fdba | 811 | allsimple = 0; |
e66d884e | 812 | members = expr_tree_cons (NULL_TREE, next1, members); |
8d08fdba MS |
813 | } |
814 | } | |
8a72a046 | 815 | else if (TREE_CODE (type) == RECORD_TYPE) |
8d08fdba MS |
816 | { |
817 | register tree field; | |
818 | ||
819 | if (tail) | |
820 | { | |
821 | if (TYPE_USES_VIRTUAL_BASECLASSES (type)) | |
822 | { | |
823 | sorry ("initializer list for object of class with virtual baseclasses"); | |
824 | return error_mark_node; | |
825 | } | |
826 | ||
827 | if (TYPE_BINFO_BASETYPES (type)) | |
828 | { | |
829 | sorry ("initializer list for object of class with baseclasses"); | |
830 | return error_mark_node; | |
831 | } | |
832 | ||
833 | if (TYPE_VIRTUAL_P (type)) | |
834 | { | |
835 | sorry ("initializer list for object using virtual functions"); | |
836 | return error_mark_node; | |
837 | } | |
838 | } | |
839 | ||
e6267549 | 840 | for (field = TYPE_FIELDS (type); field; |
8d08fdba MS |
841 | field = TREE_CHAIN (field)) |
842 | { | |
c8c133cd | 843 | if (! DECL_NAME (field) && DECL_C_BIT_FIELD (field)) |
8d08fdba | 844 | { |
e66d884e | 845 | members = expr_tree_cons (field, integer_zero_node, members); |
8d08fdba MS |
846 | continue; |
847 | } | |
848 | ||
2986ae00 | 849 | if (TREE_CODE (field) != FIELD_DECL) |
8d08fdba MS |
850 | continue; |
851 | ||
e6267549 JM |
852 | if (tail) |
853 | { | |
854 | if (TREE_PURPOSE (tail) | |
855 | && TREE_PURPOSE (tail) != field | |
856 | && TREE_PURPOSE (tail) != DECL_NAME (field)) | |
857 | sorry ("non-trivial labeled initializers"); | |
858 | ||
859 | if (TREE_VALUE (tail) != 0) | |
860 | { | |
861 | tree tail1 = tail; | |
c8fcb331 | 862 | |
e6267549 JM |
863 | next1 = digest_init (TREE_TYPE (field), |
864 | TREE_VALUE (tail), &tail1); | |
865 | my_friendly_assert (tail1 == 0 | |
866 | || TREE_CODE (tail1) == TREE_LIST, 320); | |
867 | tail = tail1; | |
868 | } | |
869 | else | |
870 | { | |
871 | next1 = error_mark_node; | |
872 | tail = TREE_CHAIN (tail); | |
873 | } | |
874 | } | |
875 | else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field))) | |
8d08fdba | 876 | { |
e6267549 JM |
877 | /* If this type needs constructors run for |
878 | default-initialization, we can't rely on the backend to do it | |
879 | for us, so build up TARGET_EXPRs. If the type in question is | |
880 | a class, just build one up; if it's an array, recurse. */ | |
881 | ||
882 | if (IS_AGGR_TYPE (TREE_TYPE (field))) | |
883 | next1 = build_functional_cast (TREE_TYPE (field), | |
884 | NULL_TREE); | |
885 | else | |
886 | next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, | |
887 | NULL_TREE); | |
888 | next1 = digest_init (TREE_TYPE (field), next1, 0); | |
8d08fdba | 889 | |
e6267549 JM |
890 | /* Warn when some struct elements are implicitly initialized. */ |
891 | if (extra_warnings) | |
892 | cp_warning ("missing initializer for member `%D'", field); | |
8d08fdba MS |
893 | } |
894 | else | |
895 | { | |
e6267549 JM |
896 | if (TREE_READONLY (field)) |
897 | cp_error ("uninitialized const member `%D'", field); | |
898 | else if (TYPE_LANG_SPECIFIC (TREE_TYPE (field)) | |
899 | && CLASSTYPE_READONLY_FIELDS_NEED_INIT (TREE_TYPE (field))) | |
900 | cp_error ("member `%D' with uninitialized const fields", | |
901 | field); | |
902 | else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) | |
903 | cp_error ("member `%D' is uninitialized reference", field); | |
904 | ||
905 | /* Warn when some struct elements are implicitly initialized | |
906 | to zero. */ | |
907 | if (extra_warnings) | |
908 | cp_warning ("missing initializer for member `%D'", field); | |
909 | ||
910 | /* The default zero-initialization is fine for us; don't | |
911 | add anything to the CONSTRUCTOR. */ | |
912 | continue; | |
8d08fdba MS |
913 | } |
914 | ||
915 | if (next1 == error_mark_node) | |
916 | erroneous = 1; | |
917 | else if (!TREE_CONSTANT (next1)) | |
918 | allconstant = 0; | |
8ccc31eb | 919 | else if (! initializer_constant_valid_p (next1, TREE_TYPE (next1))) |
8d08fdba | 920 | allsimple = 0; |
e66d884e | 921 | members = expr_tree_cons (field, next1, members); |
8d08fdba | 922 | } |
8d08fdba | 923 | } |
8a72a046 | 924 | else if (TREE_CODE (type) == UNION_TYPE) |
8d08fdba MS |
925 | { |
926 | register tree field = TYPE_FIELDS (type); | |
8d08fdba MS |
927 | |
928 | /* Find the first named field. ANSI decided in September 1990 | |
929 | that only named fields count here. */ | |
6467930b MS |
930 | while (field && (DECL_NAME (field) == 0 |
931 | || TREE_CODE (field) != FIELD_DECL)) | |
8d08fdba MS |
932 | field = TREE_CHAIN (field); |
933 | ||
934 | /* If this element specifies a field, initialize via that field. */ | |
935 | if (TREE_PURPOSE (tail) != NULL_TREE) | |
936 | { | |
937 | int win = 0; | |
938 | ||
939 | if (TREE_CODE (TREE_PURPOSE (tail)) == FIELD_DECL) | |
940 | /* Handle the case of a call by build_c_cast. */ | |
941 | field = TREE_PURPOSE (tail), win = 1; | |
942 | else if (TREE_CODE (TREE_PURPOSE (tail)) != IDENTIFIER_NODE) | |
8251199e | 943 | error ("index value instead of field name in union initializer"); |
8d08fdba MS |
944 | else |
945 | { | |
946 | tree temp; | |
947 | for (temp = TYPE_FIELDS (type); | |
948 | temp; | |
949 | temp = TREE_CHAIN (temp)) | |
950 | if (DECL_NAME (temp) == TREE_PURPOSE (tail)) | |
951 | break; | |
952 | if (temp) | |
953 | field = temp, win = 1; | |
954 | else | |
e6267549 JM |
955 | cp_error ("no field `%D' in union being initialized", |
956 | TREE_PURPOSE (tail)); | |
8d08fdba MS |
957 | } |
958 | if (!win) | |
959 | TREE_VALUE (tail) = error_mark_node; | |
960 | } | |
7177d104 MS |
961 | else if (field == 0) |
962 | { | |
8251199e | 963 | cp_error ("union `%T' with no named members cannot be initialized", |
7177d104 MS |
964 | type); |
965 | TREE_VALUE (tail) = error_mark_node; | |
966 | } | |
8d08fdba MS |
967 | |
968 | if (TREE_VALUE (tail) != 0) | |
969 | { | |
970 | tree tail1 = tail; | |
971 | ||
972 | next1 = digest_init (TREE_TYPE (field), | |
973 | TREE_VALUE (tail), &tail1); | |
974 | if (tail1 != 0 && TREE_CODE (tail1) != TREE_LIST) | |
7177d104 | 975 | my_friendly_abort (357); |
8d08fdba MS |
976 | tail = tail1; |
977 | } | |
978 | else | |
979 | { | |
980 | next1 = error_mark_node; | |
981 | tail = TREE_CHAIN (tail); | |
982 | } | |
983 | ||
984 | if (next1 == error_mark_node) | |
985 | erroneous = 1; | |
986 | else if (!TREE_CONSTANT (next1)) | |
987 | allconstant = 0; | |
8ccc31eb | 988 | else if (initializer_constant_valid_p (next1, TREE_TYPE (next1)) == 0) |
8d08fdba | 989 | allsimple = 0; |
e66d884e | 990 | members = expr_tree_cons (field, next1, members); |
8d08fdba MS |
991 | } |
992 | ||
993 | /* If arguments were specified as a list, just remove the ones we used. */ | |
994 | if (elts) | |
995 | *elts = tail; | |
996 | /* If arguments were specified as a constructor, | |
997 | complain unless we used all the elements of the constructor. */ | |
998 | else if (tail) | |
8251199e | 999 | pedwarn ("excess elements in aggregate initializer"); |
8d08fdba MS |
1000 | |
1001 | if (erroneous) | |
1002 | return error_mark_node; | |
1003 | ||
1004 | result = build (CONSTRUCTOR, type, NULL_TREE, nreverse (members)); | |
1005 | if (init) | |
1006 | TREE_HAS_CONSTRUCTOR (result) = TREE_HAS_CONSTRUCTOR (init); | |
1007 | if (allconstant) TREE_CONSTANT (result) = 1; | |
1008 | if (allconstant && allsimple) TREE_STATIC (result) = 1; | |
1009 | return result; | |
1010 | } | |
1011 | \f | |
1012 | /* Given a structure or union value DATUM, construct and return | |
1013 | the structure or union component which results from narrowing | |
be99da77 | 1014 | that value by the type specified in BASETYPE. For example, given the |
8d08fdba MS |
1015 | hierarchy |
1016 | ||
1017 | class L { int ii; }; | |
1018 | class A : L { ... }; | |
1019 | class B : L { ... }; | |
1020 | class C : A, B { ... }; | |
1021 | ||
1022 | and the declaration | |
1023 | ||
1024 | C x; | |
1025 | ||
1026 | then the expression | |
1027 | ||
be99da77 | 1028 | x.A::ii refers to the ii member of the L part of |
38e01259 | 1029 | the A part of the C object named by X. In this case, |
e92cc029 | 1030 | DATUM would be x, and BASETYPE would be A. */ |
8d08fdba MS |
1031 | |
1032 | tree | |
be99da77 | 1033 | build_scoped_ref (datum, basetype) |
8d08fdba | 1034 | tree datum; |
be99da77 | 1035 | tree basetype; |
8d08fdba MS |
1036 | { |
1037 | tree ref; | |
1038 | tree type = TREE_TYPE (datum); | |
1039 | ||
1040 | if (datum == error_mark_node) | |
1041 | return error_mark_node; | |
1042 | ||
1043 | if (TREE_CODE (type) == REFERENCE_TYPE) | |
1044 | type = TREE_TYPE (type); | |
1045 | ||
1046 | type = TYPE_MAIN_VARIANT (type); | |
1047 | ||
8d08fdba | 1048 | /* This is an easy conversion. */ |
be99da77 | 1049 | if (is_aggr_type (basetype, 1)) |
8d08fdba | 1050 | { |
be99da77 | 1051 | tree binfo = TYPE_BINFO (basetype); |
8d08fdba MS |
1052 | if (binfo != TYPE_BINFO (type)) |
1053 | { | |
1054 | binfo = get_binfo (binfo, type, 1); | |
1055 | if (binfo == error_mark_node) | |
1056 | return error_mark_node; | |
1057 | if (binfo == 0) | |
be99da77 | 1058 | return error_not_base_type (basetype, type); |
8d08fdba MS |
1059 | } |
1060 | ||
1061 | switch (TREE_CODE (datum)) | |
1062 | { | |
1063 | case NOP_EXPR: | |
1064 | case CONVERT_EXPR: | |
1065 | case FLOAT_EXPR: | |
1066 | case FIX_TRUNC_EXPR: | |
1067 | case FIX_FLOOR_EXPR: | |
1068 | case FIX_ROUND_EXPR: | |
1069 | case FIX_CEIL_EXPR: | |
1070 | ref = convert_pointer_to (binfo, | |
1071 | build_unary_op (ADDR_EXPR, TREE_OPERAND (datum, 0), 0)); | |
1072 | break; | |
1073 | default: | |
1074 | ref = convert_pointer_to (binfo, | |
1075 | build_unary_op (ADDR_EXPR, datum, 0)); | |
1076 | } | |
1077 | return build_indirect_ref (ref, "(compiler error in build_scoped_ref)"); | |
1078 | } | |
1079 | return error_mark_node; | |
1080 | } | |
1081 | ||
1082 | /* Build a reference to an object specified by the C++ `->' operator. | |
1083 | Usually this just involves dereferencing the object, but if the | |
1084 | `->' operator is overloaded, then such overloads must be | |
1085 | performed until an object which does not have the `->' operator | |
1086 | overloaded is found. An error is reported when circular pointer | |
1087 | delegation is detected. */ | |
e92cc029 | 1088 | |
8d08fdba MS |
1089 | tree |
1090 | build_x_arrow (datum) | |
1091 | tree datum; | |
1092 | { | |
1093 | tree types_memoized = NULL_TREE; | |
1094 | register tree rval = datum; | |
1095 | tree type = TREE_TYPE (rval); | |
a703fb38 | 1096 | tree last_rval = NULL_TREE; |
8d08fdba MS |
1097 | |
1098 | if (type == error_mark_node) | |
1099 | return error_mark_node; | |
1100 | ||
5156628f | 1101 | if (processing_template_decl) |
5566b478 MS |
1102 | return build_min_nt (ARROW_EXPR, rval); |
1103 | ||
a0a33927 MS |
1104 | if (TREE_CODE (rval) == OFFSET_REF) |
1105 | { | |
1106 | rval = resolve_offset_ref (datum); | |
1107 | type = TREE_TYPE (rval); | |
1108 | } | |
1109 | ||
8d08fdba MS |
1110 | if (TREE_CODE (type) == REFERENCE_TYPE) |
1111 | { | |
1112 | rval = convert_from_reference (rval); | |
1113 | type = TREE_TYPE (rval); | |
1114 | } | |
1115 | ||
3c215895 | 1116 | if (IS_AGGR_TYPE (type)) |
8d08fdba | 1117 | { |
3c215895 JM |
1118 | while ((rval = build_opfncall (COMPONENT_REF, LOOKUP_NORMAL, rval, |
1119 | NULL_TREE, NULL_TREE))) | |
8d08fdba MS |
1120 | { |
1121 | if (rval == error_mark_node) | |
1122 | return error_mark_node; | |
1123 | ||
1124 | if (value_member (TREE_TYPE (rval), types_memoized)) | |
1125 | { | |
8251199e | 1126 | error ("circular pointer delegation detected"); |
8d08fdba MS |
1127 | return error_mark_node; |
1128 | } | |
1129 | else | |
1130 | { | |
1131 | types_memoized = tree_cons (NULL_TREE, TREE_TYPE (rval), | |
1132 | types_memoized); | |
1133 | } | |
1134 | last_rval = rval; | |
1135 | } | |
297dcfb3 MM |
1136 | |
1137 | if (last_rval == NULL_TREE) | |
1138 | { | |
8251199e | 1139 | cp_error ("base operand of `->' has non-pointer type `%T'", type); |
297dcfb3 MM |
1140 | return error_mark_node; |
1141 | } | |
1142 | ||
8d08fdba MS |
1143 | if (TREE_CODE (TREE_TYPE (last_rval)) == REFERENCE_TYPE) |
1144 | last_rval = convert_from_reference (last_rval); | |
1145 | } | |
1146 | else | |
1147 | last_rval = default_conversion (rval); | |
1148 | ||
8d08fdba MS |
1149 | if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE) |
1150 | return build_indirect_ref (last_rval, NULL_PTR); | |
1151 | ||
8d08fdba | 1152 | if (types_memoized) |
8251199e | 1153 | error ("result of `operator->()' yields non-pointer result"); |
8d08fdba | 1154 | else |
8251199e | 1155 | error ("base operand of `->' is not a pointer"); |
8d08fdba MS |
1156 | return error_mark_node; |
1157 | } | |
1158 | ||
1159 | /* Make an expression to refer to the COMPONENT field of | |
1160 | structure or union value DATUM. COMPONENT is an arbitrary | |
1161 | expression. DATUM has not already been checked out to be of | |
1162 | aggregate type. | |
1163 | ||
1164 | For C++, COMPONENT may be a TREE_LIST. This happens when we must | |
1165 | return an object of member type to a method of the current class, | |
1166 | but there is not yet enough typing information to know which one. | |
1167 | As a special case, if there is only one method by that name, | |
1168 | it is returned. Otherwise we return an expression which other | |
1169 | routines will have to know how to deal with later. */ | |
e92cc029 | 1170 | |
8d08fdba MS |
1171 | tree |
1172 | build_m_component_ref (datum, component) | |
1173 | tree datum, component; | |
1174 | { | |
1175 | tree type; | |
1176 | tree objtype = TREE_TYPE (datum); | |
1177 | tree rettype; | |
71851aaa | 1178 | tree binfo; |
8d08fdba | 1179 | |
5156628f | 1180 | if (processing_template_decl) |
5566b478 MS |
1181 | return build_min_nt (DOTSTAR_EXPR, datum, component); |
1182 | ||
8d08fdba MS |
1183 | if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component))) |
1184 | { | |
1185 | type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component))); | |
1186 | rettype = type; | |
1187 | } | |
1188 | else | |
1189 | { | |
162bc98d | 1190 | type = TREE_TYPE (TREE_TYPE (component)); |
4ac14744 | 1191 | rettype = TREE_TYPE (type); |
8d08fdba MS |
1192 | } |
1193 | ||
1194 | if (datum == error_mark_node || component == error_mark_node) | |
1195 | return error_mark_node; | |
1196 | ||
8d08fdba MS |
1197 | if (TREE_CODE (type) != OFFSET_TYPE && TREE_CODE (type) != METHOD_TYPE) |
1198 | { | |
8251199e | 1199 | cp_error ("`%E' cannot be used as a member pointer, since it is of type `%T'", component, type); |
8d08fdba MS |
1200 | return error_mark_node; |
1201 | } | |
1202 | ||
1203 | if (TREE_CODE (objtype) == REFERENCE_TYPE) | |
1204 | objtype = TREE_TYPE (objtype); | |
db5ae43f | 1205 | objtype = TYPE_MAIN_VARIANT (objtype); |
8d08fdba | 1206 | |
51c184be MS |
1207 | if (! IS_AGGR_TYPE (objtype)) |
1208 | { | |
8251199e JM |
1209 | cp_error ("cannot apply member pointer `%E' to `%E'", component, datum); |
1210 | cp_error ("which is of non-aggregate type `%T'", objtype); | |
51c184be MS |
1211 | return error_mark_node; |
1212 | } | |
71851aaa MS |
1213 | |
1214 | binfo = get_binfo (TYPE_METHOD_BASETYPE (type), objtype, 1); | |
1215 | if (binfo == NULL_TREE) | |
8d08fdba | 1216 | { |
8251199e | 1217 | cp_error ("member type `%T::' incompatible with object type `%T'", |
8d08fdba MS |
1218 | TYPE_METHOD_BASETYPE (type), objtype); |
1219 | return error_mark_node; | |
1220 | } | |
71851aaa MS |
1221 | else if (binfo == error_mark_node) |
1222 | return error_mark_node; | |
8d08fdba | 1223 | |
d2e5ee5c MS |
1224 | component = build (OFFSET_REF, rettype, datum, component); |
1225 | if (TREE_CODE (type) == OFFSET_TYPE) | |
1226 | component = resolve_offset_ref (component); | |
1227 | return component; | |
8d08fdba MS |
1228 | } |
1229 | ||
fc378698 | 1230 | /* Return a tree node for the expression TYPENAME '(' PARMS ')'. */ |
e92cc029 | 1231 | |
8d08fdba MS |
1232 | tree |
1233 | build_functional_cast (exp, parms) | |
1234 | tree exp; | |
1235 | tree parms; | |
1236 | { | |
1237 | /* This is either a call to a constructor, | |
1238 | or a C cast in C++'s `functional' notation. */ | |
fc378698 | 1239 | tree type; |
8d08fdba MS |
1240 | |
1241 | if (exp == error_mark_node || parms == error_mark_node) | |
1242 | return error_mark_node; | |
1243 | ||
1244 | if (TREE_CODE (exp) == IDENTIFIER_NODE) | |
1245 | { | |
8d08fdba MS |
1246 | if (IDENTIFIER_HAS_TYPE_VALUE (exp)) |
1247 | /* Either an enum or an aggregate type. */ | |
1248 | type = IDENTIFIER_TYPE_VALUE (exp); | |
1249 | else | |
1250 | { | |
1251 | type = lookup_name (exp, 1); | |
1252 | if (!type || TREE_CODE (type) != TYPE_DECL) | |
1253 | { | |
8251199e | 1254 | cp_error ("`%T' fails to be a typedef or built-in type", exp); |
8d08fdba MS |
1255 | return error_mark_node; |
1256 | } | |
1257 | type = TREE_TYPE (type); | |
1258 | } | |
1259 | } | |
45537677 MS |
1260 | else if (TREE_CODE (exp) == TYPE_DECL) |
1261 | type = TREE_TYPE (exp); | |
8d08fdba MS |
1262 | else |
1263 | type = exp; | |
1264 | ||
5156628f | 1265 | if (processing_template_decl) |
5566b478 MS |
1266 | return build_min (CAST_EXPR, type, parms); |
1267 | ||
8d08fdba MS |
1268 | if (! IS_AGGR_TYPE (type)) |
1269 | { | |
1270 | /* this must build a C cast */ | |
1271 | if (parms == NULL_TREE) | |
d18c083e | 1272 | parms = integer_zero_node; |
8ccc31eb | 1273 | else |
a0a33927 | 1274 | { |
8ccc31eb | 1275 | if (TREE_CHAIN (parms) != NULL_TREE) |
8251199e | 1276 | pedwarn ("initializer list being treated as compound expression"); |
a0a33927 MS |
1277 | parms = build_compound_expr (parms); |
1278 | } | |
8ccc31eb | 1279 | |
faf5394a | 1280 | return build_c_cast (type, parms); |
8d08fdba MS |
1281 | } |
1282 | ||
45537677 MS |
1283 | /* Prepare to evaluate as a call to a constructor. If this expression |
1284 | is actually used, for example, | |
1285 | ||
1286 | return X (arg1, arg2, ...); | |
1287 | ||
1288 | then the slot being initialized will be filled in. */ | |
1289 | ||
5566b478 | 1290 | if (TYPE_SIZE (complete_type (type)) == NULL_TREE) |
8d08fdba | 1291 | { |
8251199e | 1292 | cp_error ("type `%T' is not yet defined", type); |
8d08fdba MS |
1293 | return error_mark_node; |
1294 | } | |
a7a64a77 MM |
1295 | if (abstract_virtuals_error (NULL_TREE, type)) |
1296 | return error_mark_node; | |
8d08fdba MS |
1297 | |
1298 | if (parms && TREE_CHAIN (parms) == NULL_TREE) | |
faf5394a | 1299 | return build_c_cast (type, TREE_VALUE (parms)); |
8d08fdba | 1300 | |
3551c177 JM |
1301 | /* We need to zero-initialize POD types. Let's do that for everything |
1302 | that doesn't need a constructor. */ | |
1303 | if (parms == NULL_TREE && !TYPE_NEEDS_CONSTRUCTING (type) | |
1304 | && TYPE_HAS_DEFAULT_CONSTRUCTOR (type)) | |
1305 | { | |
1306 | exp = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE); | |
1307 | return get_target_expr (exp); | |
1308 | } | |
1309 | ||
fc378698 MS |
1310 | exp = build_method_call (NULL_TREE, ctor_identifier, parms, |
1311 | TYPE_BINFO (type), LOOKUP_NORMAL); | |
8d08fdba | 1312 | |
fc378698 | 1313 | if (exp == error_mark_node) |
a0a33927 | 1314 | return error_mark_node; |
8d08fdba | 1315 | |
fc378698 | 1316 | return build_cplus_new (type, exp); |
8d08fdba MS |
1317 | } |
1318 | \f | |
1319 | /* Return the character string for the name that encodes the | |
1320 | enumeral value VALUE in the domain TYPE. */ | |
e92cc029 | 1321 | |
8d08fdba MS |
1322 | char * |
1323 | enum_name_string (value, type) | |
1324 | tree value; | |
1325 | tree type; | |
1326 | { | |
1327 | register tree values = TYPE_VALUES (type); | |
1328 | register HOST_WIDE_INT intval = TREE_INT_CST_LOW (value); | |
1329 | ||
1330 | my_friendly_assert (TREE_CODE (type) == ENUMERAL_TYPE, 324); | |
1331 | while (values | |
1332 | && TREE_INT_CST_LOW (TREE_VALUE (values)) != intval) | |
1333 | values = TREE_CHAIN (values); | |
1334 | if (values == NULL_TREE) | |
1335 | { | |
1336 | char *buf = (char *)oballoc (16 + TYPE_NAME_LENGTH (type)); | |
1337 | ||
1338 | /* Value must have been cast. */ | |
63d088b7 KG |
1339 | sprintf (buf, "(enum %s)%ld", |
1340 | TYPE_NAME_STRING (type), (long) intval); | |
8d08fdba MS |
1341 | return buf; |
1342 | } | |
1343 | return IDENTIFIER_POINTER (TREE_PURPOSE (values)); | |
1344 | } | |
1345 | ||
f0e01782 | 1346 | #if 0 |
8d08fdba MS |
1347 | /* Print out a language-specific error message for |
1348 | (Pascal) case or (C) switch statements. | |
1349 | CODE tells what sort of message to print. | |
1350 | TYPE is the type of the switch index expression. | |
1351 | NEW is the new value that we were trying to add. | |
1352 | OLD is the old value that stopped us from adding it. */ | |
e92cc029 | 1353 | |
8d08fdba MS |
1354 | void |
1355 | report_case_error (code, type, new_value, old_value) | |
1356 | int code; | |
1357 | tree type; | |
1358 | tree new_value, old_value; | |
1359 | { | |
1360 | if (code == 1) | |
1361 | { | |
1362 | if (new_value) | |
8251199e | 1363 | error ("case label not within a switch statement"); |
8d08fdba | 1364 | else |
8251199e | 1365 | error ("default label not within a switch statement"); |
8d08fdba MS |
1366 | } |
1367 | else if (code == 2) | |
1368 | { | |
1369 | if (new_value == 0) | |
1370 | { | |
8251199e | 1371 | error ("multiple default labels in one switch"); |
8d08fdba MS |
1372 | return; |
1373 | } | |
1374 | if (TREE_CODE (new_value) == RANGE_EXPR) | |
1375 | if (TREE_CODE (old_value) == RANGE_EXPR) | |
1376 | { | |
1377 | char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type))); | |
1378 | if (TREE_CODE (type) == ENUMERAL_TYPE) | |
1379 | sprintf (buf, "overlapping ranges [%s..%s], [%s..%s] in case expression", | |
1380 | enum_name_string (TREE_OPERAND (new_value, 0), type), | |
1381 | enum_name_string (TREE_OPERAND (new_value, 1), type), | |
1382 | enum_name_string (TREE_OPERAND (old_value, 0), type), | |
1383 | enum_name_string (TREE_OPERAND (old_value, 1), type)); | |
1384 | else | |
1385 | sprintf (buf, "overlapping ranges [%d..%d], [%d..%d] in case expression", | |
1386 | TREE_INT_CST_LOW (TREE_OPERAND (new_value, 0)), | |
1387 | TREE_INT_CST_LOW (TREE_OPERAND (new_value, 1)), | |
1388 | TREE_INT_CST_LOW (TREE_OPERAND (old_value, 0)), | |
1389 | TREE_INT_CST_LOW (TREE_OPERAND (old_value, 1))); | |
1390 | error (buf); | |
1391 | } | |
1392 | else | |
1393 | { | |
1394 | char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type))); | |
1395 | if (TREE_CODE (type) == ENUMERAL_TYPE) | |
1396 | sprintf (buf, "range [%s..%s] includes element `%s' in case expression", | |
1397 | enum_name_string (TREE_OPERAND (new_value, 0), type), | |
1398 | enum_name_string (TREE_OPERAND (new_value, 1), type), | |
1399 | enum_name_string (old_value, type)); | |
1400 | else | |
1401 | sprintf (buf, "range [%d..%d] includes (%d) in case expression", | |
1402 | TREE_INT_CST_LOW (TREE_OPERAND (new_value, 0)), | |
1403 | TREE_INT_CST_LOW (TREE_OPERAND (new_value, 1)), | |
1404 | TREE_INT_CST_LOW (old_value)); | |
1405 | error (buf); | |
1406 | } | |
1407 | else if (TREE_CODE (old_value) == RANGE_EXPR) | |
1408 | { | |
1409 | char *buf = (char *)alloca (4 * (8 + TYPE_NAME_LENGTH (type))); | |
1410 | if (TREE_CODE (type) == ENUMERAL_TYPE) | |
1411 | sprintf (buf, "range [%s..%s] includes element `%s' in case expression", | |
1412 | enum_name_string (TREE_OPERAND (old_value, 0), type), | |
1413 | enum_name_string (TREE_OPERAND (old_value, 1), type), | |
1414 | enum_name_string (new_value, type)); | |
1415 | else | |
1416 | sprintf (buf, "range [%d..%d] includes (%d) in case expression", | |
1417 | TREE_INT_CST_LOW (TREE_OPERAND (old_value, 0)), | |
1418 | TREE_INT_CST_LOW (TREE_OPERAND (old_value, 1)), | |
1419 | TREE_INT_CST_LOW (new_value)); | |
1420 | error (buf); | |
1421 | } | |
1422 | else | |
1423 | { | |
1424 | if (TREE_CODE (type) == ENUMERAL_TYPE) | |
8251199e | 1425 | error ("duplicate label `%s' in switch statement", |
8d08fdba MS |
1426 | enum_name_string (new_value, type)); |
1427 | else | |
8251199e | 1428 | error ("duplicate label (%d) in switch statement", |
8d08fdba MS |
1429 | TREE_INT_CST_LOW (new_value)); |
1430 | } | |
1431 | } | |
1432 | else if (code == 3) | |
1433 | { | |
1434 | if (TREE_CODE (type) == ENUMERAL_TYPE) | |
8251199e | 1435 | warning ("case value out of range for enum %s", |
8d08fdba MS |
1436 | TYPE_NAME_STRING (type)); |
1437 | else | |
8251199e | 1438 | warning ("case value out of range"); |
8d08fdba MS |
1439 | } |
1440 | else if (code == 4) | |
1441 | { | |
1442 | if (TREE_CODE (type) == ENUMERAL_TYPE) | |
8251199e | 1443 | error ("range values `%s' and `%s' reversed", |
8d08fdba MS |
1444 | enum_name_string (new_value, type), |
1445 | enum_name_string (old_value, type)); | |
1446 | else | |
8251199e | 1447 | error ("range values reversed"); |
8d08fdba MS |
1448 | } |
1449 | } | |
f0e01782 | 1450 | #endif |
46b02c6d | 1451 | |
86910c53 JM |
1452 | /* Complain about defining new types in inappropriate places. We give an |
1453 | exception for C-style casts, to accommodate GNU C stylings. */ | |
1454 | ||
46b02c6d MS |
1455 | void |
1456 | check_for_new_type (string, inptree) | |
d8e178a0 | 1457 | const char *string; |
46b02c6d MS |
1458 | flagged_type_tree inptree; |
1459 | { | |
86910c53 JM |
1460 | if (inptree.new_type_flag |
1461 | && (pedantic || strcmp (string, "cast") != 0)) | |
8251199e | 1462 | pedwarn ("ANSI C++ forbids defining types within %s",string); |
46b02c6d | 1463 | } |
4cc1d462 NS |
1464 | |
1465 | /* Add new exception specifier SPEC, to the LIST we currently have. | |
1466 | If it's already in LIST then do nothing. | |
1467 | Moan if it's bad and we're allowed to. COMPLAIN < 0 means we | |
1468 | know what we're doing. */ | |
1469 | ||
1470 | tree | |
1471 | add_exception_specifier (list, spec, complain) | |
1472 | tree list, spec; | |
1473 | int complain; | |
1474 | { | |
1475 | int ok; | |
1476 | tree core = spec; | |
1477 | int is_ptr; | |
1478 | ||
1479 | if (spec == error_mark_node) | |
1480 | return list; | |
1481 | ||
1482 | my_friendly_assert (spec && (!list || TREE_VALUE (list)), 19990317); | |
1483 | ||
1484 | /* [except.spec] 1, type in an exception specifier shall not be | |
1485 | incomplete, or pointer or ref to incomplete other than pointer | |
1486 | to cv void. */ | |
1487 | is_ptr = TREE_CODE (core) == POINTER_TYPE; | |
1488 | if (is_ptr || TREE_CODE (core) == REFERENCE_TYPE) | |
1489 | core = TREE_TYPE (core); | |
1490 | if (complain < 0) | |
1491 | ok = 1; | |
1492 | else if (TYPE_MAIN_VARIANT (core) == void_type_node) | |
1493 | ok = is_ptr; | |
1494 | else if (TREE_CODE (core) == TEMPLATE_TYPE_PARM) | |
1495 | ok = 1; | |
1496 | else | |
76554ea3 | 1497 | ok = TYPE_SIZE (complete_type (core)) != NULL_TREE; |
4cc1d462 NS |
1498 | |
1499 | if (ok) | |
1500 | { | |
1501 | tree probe; | |
1502 | ||
1503 | for (probe = list; probe; probe = TREE_CHAIN (probe)) | |
1504 | if (same_type_p (TREE_VALUE (probe), spec)) | |
1505 | break; | |
1506 | if (!probe) | |
1507 | { | |
1508 | spec = build_decl_list (NULL_TREE, spec); | |
1509 | TREE_CHAIN (spec) = list; | |
1510 | list = spec; | |
1511 | } | |
1512 | } | |
1513 | else if (complain) | |
1514 | incomplete_type_error (NULL_TREE, core); | |
1515 | return list; | |
1516 | } |