]>
Commit | Line | Data |
---|---|---|
2bbd3819 RS |
1 | /* Generate information regarding function declarations and definitions based |
2 | on information stored in GCC's tree structure. This code implements the | |
872d115f | 3 | -aux-info option. |
517cbe13 JL |
4 | Copyright (C) 1989, 1991, 1994, 1995, 1997, 1998, |
5 | 1999, 2000 Free Software Foundation, Inc. | |
3826a3da | 6 | Contributed by Ron Guilmette (rfg@segfault.us.com). |
2bbd3819 RS |
7 | |
8 | This file is part of GNU CC. | |
9 | ||
10 | GNU CC is free software; you can redistribute it and/or modify | |
11 | it under the terms of the GNU General Public License as published by | |
12 | the Free Software Foundation; either version 2, or (at your option) | |
13 | any later version. | |
14 | ||
15 | GNU CC is distributed in the hope that it will be useful, | |
16 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 | GNU General Public License for more details. | |
19 | ||
20 | You should have received a copy of the GNU General Public License | |
21 | along with GNU CC; see the file COPYING. If not, write to | |
940d9d63 RK |
22 | the Free Software Foundation, 59 Temple Place - Suite 330, |
23 | Boston, MA 02111-1307, USA. */ | |
2bbd3819 | 24 | |
2bbd3819 | 25 | #include "config.h" |
670ee920 | 26 | #include "system.h" |
01198c2f | 27 | #include "toplev.h" |
2bbd3819 RS |
28 | #include "flags.h" |
29 | #include "tree.h" | |
30 | #include "c-tree.h" | |
31 | ||
2bbd3819 RS |
32 | enum formals_style_enum { |
33 | ansi, | |
34 | k_and_r_names, | |
35 | k_and_r_decls | |
36 | }; | |
37 | typedef enum formals_style_enum formals_style; | |
38 | ||
39 | ||
dff01034 | 40 | static const char *data_type; |
2bbd3819 | 41 | |
3d994c6b KG |
42 | static char *affix_data_type PARAMS ((const char *)); |
43 | static const char *gen_formal_list_for_type PARAMS ((tree, formals_style)); | |
44 | static int deserves_ellipsis PARAMS ((tree)); | |
45 | static const char *gen_formal_list_for_func_def PARAMS ((tree, formals_style)); | |
46 | static const char *gen_type PARAMS ((const char *, tree, formals_style)); | |
47 | static const char *gen_decl PARAMS ((tree, int, formals_style)); | |
2bbd3819 | 48 | \f |
2bbd3819 RS |
49 | /* Given a string representing an entire type or an entire declaration |
50 | which only lacks the actual "data-type" specifier (at its left end), | |
51 | affix the data-type specifier to the left end of the given type | |
52 | specification or object declaration. | |
53 | ||
54 | Because of C language weirdness, the data-type specifier (which normally | |
55 | goes in at the very left end) may have to be slipped in just to the | |
56 | right of any leading "const" or "volatile" qualifiers (there may be more | |
57 | than one). Actually this may not be strictly necessary because it seems | |
58 | that GCC (at least) accepts `<data-type> const foo;' and treats it the | |
59 | same as `const <data-type> foo;' but people are accustomed to seeing | |
60 | `const char *foo;' and *not* `char const *foo;' so we try to create types | |
61 | that look as expected. */ | |
62 | ||
0f41302f | 63 | static char * |
dff01034 KG |
64 | affix_data_type (param) |
65 | const char *param; | |
2bbd3819 | 66 | { |
dff01034 | 67 | char *type_or_decl = (char *) alloca (strlen (param) + 1); |
2bbd3819 RS |
68 | char *p = type_or_decl; |
69 | char *qualifiers_then_data_type; | |
70 | char saved; | |
71 | ||
dff01034 KG |
72 | strcpy (type_or_decl, param); |
73 | ||
2bbd3819 RS |
74 | /* Skip as many leading const's or volatile's as there are. */ |
75 | ||
76 | for (;;) | |
77 | { | |
1394aabd | 78 | if (!strncmp (p, "volatile ", 9)) |
2bbd3819 RS |
79 | { |
80 | p += 9; | |
81 | continue; | |
82 | } | |
1394aabd | 83 | if (!strncmp (p, "const ", 6)) |
2bbd3819 RS |
84 | { |
85 | p += 6; | |
86 | continue; | |
87 | } | |
88 | break; | |
89 | } | |
90 | ||
91 | /* p now points to the place where we can insert the data type. We have to | |
92 | add a blank after the data-type of course. */ | |
93 | ||
94 | if (p == type_or_decl) | |
2778b98d | 95 | return concat (data_type, " ", type_or_decl, NULL_PTR); |
2bbd3819 RS |
96 | |
97 | saved = *p; | |
98 | *p = '\0'; | |
2778b98d | 99 | qualifiers_then_data_type = concat (type_or_decl, data_type, NULL_PTR); |
2bbd3819 | 100 | *p = saved; |
2778b98d | 101 | return concat (qualifiers_then_data_type, " ", p, NULL_PTR); |
2bbd3819 RS |
102 | } |
103 | ||
104 | /* Given a tree node which represents some "function type", generate the | |
105 | source code version of a formal parameter list (of some given style) for | |
106 | this function type. Return the whole formal parameter list (including | |
107 | a pair of surrounding parens) as a string. Note that if the style | |
108 | we are currently aiming for is non-ansi, then we just return a pair | |
0f41302f | 109 | of empty parens here. */ |
2bbd3819 | 110 | |
dff01034 | 111 | static const char * |
2bbd3819 RS |
112 | gen_formal_list_for_type (fntype, style) |
113 | tree fntype; | |
114 | formals_style style; | |
115 | { | |
dff01034 | 116 | const char *formal_list = ""; |
2bbd3819 RS |
117 | tree formal_type; |
118 | ||
119 | if (style != ansi) | |
120 | return "()"; | |
121 | ||
122 | formal_type = TYPE_ARG_TYPES (fntype); | |
123 | while (formal_type && TREE_VALUE (formal_type) != void_type_node) | |
124 | { | |
dff01034 | 125 | const char *this_type; |
2bbd3819 RS |
126 | |
127 | if (*formal_list) | |
2778b98d | 128 | formal_list = concat (formal_list, ", ", NULL_PTR); |
2bbd3819 RS |
129 | |
130 | this_type = gen_type ("", TREE_VALUE (formal_type), ansi); | |
e3da301d MS |
131 | formal_list |
132 | = ((strlen (this_type)) | |
2778b98d KG |
133 | ? concat (formal_list, affix_data_type (this_type), NULL_PTR) |
134 | : concat (formal_list, data_type, NULL_PTR)); | |
2bbd3819 RS |
135 | |
136 | formal_type = TREE_CHAIN (formal_type); | |
137 | } | |
138 | ||
139 | /* If we got to here, then we are trying to generate an ANSI style formal | |
140 | parameters list. | |
141 | ||
142 | New style prototyped ANSI formal parameter lists should in theory always | |
143 | contain some stuff between the opening and closing parens, even if it is | |
144 | only "void". | |
145 | ||
146 | The brutal truth though is that there is lots of old K&R code out there | |
147 | which contains declarations of "pointer-to-function" parameters and | |
148 | these almost never have fully specified formal parameter lists associated | |
149 | with them. That is, the pointer-to-function parameters are declared | |
150 | with just empty parameter lists. | |
151 | ||
152 | In cases such as these, protoize should really insert *something* into | |
153 | the vacant parameter lists, but what? It has no basis on which to insert | |
154 | anything in particular. | |
155 | ||
156 | Here, we make life easy for protoize by trying to distinguish between | |
157 | K&R empty parameter lists and new-style prototyped parameter lists | |
158 | that actually contain "void". In the latter case we (obviously) want | |
159 | to output the "void" verbatim, and that what we do. In the former case, | |
160 | we do our best to give protoize something nice to insert. | |
161 | ||
3826a3da | 162 | This "something nice" should be something that is still valid (when |
2bbd3819 RS |
163 | re-compiled) but something that can clearly indicate to the user that |
164 | more typing information (for the parameter list) should be added (by | |
165 | hand) at some convenient moment. | |
166 | ||
d45cf215 | 167 | The string chosen here is a comment with question marks in it. */ |
2bbd3819 RS |
168 | |
169 | if (!*formal_list) | |
170 | { | |
171 | if (TYPE_ARG_TYPES (fntype)) | |
172 | /* assert (TREE_VALUE (TYPE_ARG_TYPES (fntype)) == void_type_node); */ | |
173 | formal_list = "void"; | |
174 | else | |
175 | formal_list = "/* ??? */"; | |
176 | } | |
177 | else | |
178 | { | |
179 | /* If there were at least some parameters, and if the formals-types-list | |
180 | petered out to a NULL (i.e. without being terminated by a | |
181 | void_type_node) then we need to tack on an ellipsis. */ | |
182 | if (!formal_type) | |
2778b98d | 183 | formal_list = concat (formal_list, ", ...", NULL_PTR); |
2bbd3819 RS |
184 | } |
185 | ||
2778b98d | 186 | return concat (" (", formal_list, ")", NULL_PTR); |
2bbd3819 RS |
187 | } |
188 | ||
189 | /* For the generation of an ANSI prototype for a function definition, we have | |
190 | to look at the formal parameter list of the function's own "type" to | |
191 | determine if the function's formal parameter list should end with an | |
192 | ellipsis. Given a tree node, the following function will return non-zero | |
193 | if the "function type" parameter list should end with an ellipsis. */ | |
194 | ||
195 | static int | |
196 | deserves_ellipsis (fntype) | |
197 | tree fntype; | |
198 | { | |
199 | tree formal_type; | |
200 | ||
201 | formal_type = TYPE_ARG_TYPES (fntype); | |
202 | while (formal_type && TREE_VALUE (formal_type) != void_type_node) | |
203 | formal_type = TREE_CHAIN (formal_type); | |
204 | ||
205 | /* If there were at least some parameters, and if the formals-types-list | |
206 | petered out to a NULL (i.e. without being terminated by a void_type_node) | |
207 | then we need to tack on an ellipsis. */ | |
208 | ||
209 | return (!formal_type && TYPE_ARG_TYPES (fntype)); | |
210 | } | |
211 | ||
212 | /* Generate a parameter list for a function definition (in some given style). | |
213 | ||
214 | Note that this routine has to be separate (and different) from the code that | |
215 | generates the prototype parameter lists for function declarations, because | |
216 | in the case of a function declaration, all we have to go on is a tree node | |
217 | representing the function's own "function type". This can tell us the types | |
218 | of all of the formal parameters for the function, but it cannot tell us the | |
219 | actual *names* of each of the formal parameters. We need to output those | |
220 | parameter names for each function definition. | |
221 | ||
222 | This routine gets a pointer to a tree node which represents the actual | |
223 | declaration of the given function, and this DECL node has a list of formal | |
224 | parameter (variable) declarations attached to it. These formal parameter | |
225 | (variable) declaration nodes give us the actual names of the formal | |
226 | parameters for the given function definition. | |
227 | ||
228 | This routine returns a string which is the source form for the entire | |
229 | function formal parameter list. */ | |
230 | ||
dff01034 | 231 | static const char * |
2bbd3819 RS |
232 | gen_formal_list_for_func_def (fndecl, style) |
233 | tree fndecl; | |
234 | formals_style style; | |
235 | { | |
dff01034 | 236 | const char *formal_list = ""; |
2bbd3819 RS |
237 | tree formal_decl; |
238 | ||
239 | formal_decl = DECL_ARGUMENTS (fndecl); | |
240 | while (formal_decl) | |
241 | { | |
dff01034 | 242 | const char *this_formal; |
2bbd3819 RS |
243 | |
244 | if (*formal_list && ((style == ansi) || (style == k_and_r_names))) | |
2778b98d | 245 | formal_list = concat (formal_list, ", ", NULL_PTR); |
2bbd3819 RS |
246 | this_formal = gen_decl (formal_decl, 0, style); |
247 | if (style == k_and_r_decls) | |
2778b98d | 248 | formal_list = concat (formal_list, this_formal, "; ", NULL_PTR); |
2bbd3819 | 249 | else |
2778b98d | 250 | formal_list = concat (formal_list, this_formal, NULL_PTR); |
2bbd3819 RS |
251 | formal_decl = TREE_CHAIN (formal_decl); |
252 | } | |
253 | if (style == ansi) | |
254 | { | |
255 | if (!DECL_ARGUMENTS (fndecl)) | |
2778b98d | 256 | formal_list = concat (formal_list, "void", NULL_PTR); |
2bbd3819 | 257 | if (deserves_ellipsis (TREE_TYPE (fndecl))) |
2778b98d | 258 | formal_list = concat (formal_list, ", ...", NULL_PTR); |
2bbd3819 RS |
259 | } |
260 | if ((style == ansi) || (style == k_and_r_names)) | |
2778b98d | 261 | formal_list = concat (" (", formal_list, ")", NULL_PTR); |
2bbd3819 RS |
262 | return formal_list; |
263 | } | |
264 | ||
265 | /* Generate a string which is the source code form for a given type (t). This | |
266 | routine is ugly and complex because the C syntax for declarations is ugly | |
267 | and complex. This routine is straightforward so long as *no* pointer types, | |
268 | array types, or function types are involved. | |
269 | ||
270 | In the simple cases, this routine will return the (string) value which was | |
271 | passed in as the "ret_val" argument. Usually, this starts out either as an | |
272 | empty string, or as the name of the declared item (i.e. the formal function | |
273 | parameter variable). | |
274 | ||
275 | This routine will also return with the global variable "data_type" set to | |
276 | some string value which is the "basic" data-type of the given complete type. | |
277 | This "data_type" string can be concatenated onto the front of the returned | |
278 | string after this routine returns to its caller. | |
279 | ||
280 | In complicated cases involving pointer types, array types, or function | |
281 | types, the C declaration syntax requires an "inside out" approach, i.e. if | |
282 | you have a type which is a "pointer-to-function" type, you need to handle | |
283 | the "pointer" part first, but it also has to be "innermost" (relative to | |
284 | the declaration stuff for the "function" type). Thus, is this case, you | |
285 | must prepend a "(*" and append a ")" to the name of the item (i.e. formal | |
286 | variable). Then you must append and prepend the other info for the | |
287 | "function type" part of the overall type. | |
288 | ||
289 | To handle the "innermost precedence" rules of complicated C declarators, we | |
290 | do the following (in this routine). The input parameter called "ret_val" | |
291 | is treated as a "seed". Each time gen_type is called (perhaps recursively) | |
292 | some additional strings may be appended or prepended (or both) to the "seed" | |
293 | string. If yet another (lower) level of the GCC tree exists for the given | |
294 | type (as in the case of a pointer type, an array type, or a function type) | |
295 | then the (wrapped) seed is passed to a (recursive) invocation of gen_type() | |
296 | this recursive invocation may again "wrap" the (new) seed with yet more | |
297 | declarator stuff, by appending, prepending (or both). By the time the | |
298 | recursion bottoms out, the "seed value" at that point will have a value | |
299 | which is (almost) the complete source version of the declarator (except | |
300 | for the data_type info). Thus, this deepest "seed" value is simply passed | |
301 | back up through all of the recursive calls until it is given (as the return | |
302 | value) to the initial caller of the gen_type() routine. All that remains | |
303 | to do at this point is for the initial caller to prepend the "data_type" | |
304 | string onto the returned "seed". */ | |
305 | ||
dff01034 | 306 | static const char * |
2bbd3819 | 307 | gen_type (ret_val, t, style) |
dff01034 | 308 | const char *ret_val; |
2bbd3819 RS |
309 | tree t; |
310 | formals_style style; | |
311 | { | |
312 | tree chain_p; | |
313 | ||
f5880dbe JW |
314 | /* If there is a typedef name for this type, use it. */ |
315 | if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) | |
2bbd3819 RS |
316 | data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); |
317 | else | |
318 | { | |
319 | switch (TREE_CODE (t)) | |
320 | { | |
321 | case POINTER_TYPE: | |
322 | if (TYPE_READONLY (t)) | |
2778b98d | 323 | ret_val = concat ("const ", ret_val, NULL_PTR); |
2bbd3819 | 324 | if (TYPE_VOLATILE (t)) |
2778b98d | 325 | ret_val = concat ("volatile ", ret_val, NULL_PTR); |
2bbd3819 | 326 | |
2778b98d | 327 | ret_val = concat ("*", ret_val, NULL_PTR); |
2bbd3819 RS |
328 | |
329 | if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE) | |
2778b98d | 330 | ret_val = concat ("(", ret_val, ")", NULL_PTR); |
2bbd3819 RS |
331 | |
332 | ret_val = gen_type (ret_val, TREE_TYPE (t), style); | |
333 | ||
334 | return ret_val; | |
335 | ||
336 | case ARRAY_TYPE: | |
7e53036d | 337 | if (TYPE_SIZE (t) == 0 || TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST) |
2778b98d KG |
338 | ret_val = gen_type (concat (ret_val, "[]", NULL_PTR), |
339 | TREE_TYPE (t), style); | |
7e53036d | 340 | else if (int_size_in_bytes (t) == 0) |
2778b98d KG |
341 | ret_val = gen_type (concat (ret_val, "[0]", NULL_PTR), |
342 | TREE_TYPE (t), style); | |
7e53036d RS |
343 | else |
344 | { | |
345 | int size = (int_size_in_bytes (t) / int_size_in_bytes (TREE_TYPE (t))); | |
346 | char buff[10]; | |
347 | sprintf (buff, "[%d]", size); | |
2778b98d | 348 | ret_val = gen_type (concat (ret_val, buff, NULL_PTR), |
7e53036d RS |
349 | TREE_TYPE (t), style); |
350 | } | |
2bbd3819 RS |
351 | break; |
352 | ||
353 | case FUNCTION_TYPE: | |
2778b98d KG |
354 | ret_val = gen_type (concat (ret_val, |
355 | gen_formal_list_for_type (t, style), | |
356 | NULL_PTR), | |
357 | TREE_TYPE (t), style); | |
2bbd3819 RS |
358 | break; |
359 | ||
360 | case IDENTIFIER_NODE: | |
361 | data_type = IDENTIFIER_POINTER (t); | |
362 | break; | |
363 | ||
364 | /* The following three cases are complicated by the fact that a | |
365 | user may do something really stupid, like creating a brand new | |
366 | "anonymous" type specification in a formal argument list (or as | |
367 | part of a function return type specification). For example: | |
368 | ||
369 | int f (enum { red, green, blue } color); | |
370 | ||
371 | In such cases, we have no name that we can put into the prototype | |
372 | to represent the (anonymous) type. Thus, we have to generate the | |
373 | whole darn type specification. Yuck! */ | |
374 | ||
375 | case RECORD_TYPE: | |
376 | if (TYPE_NAME (t)) | |
377 | data_type = IDENTIFIER_POINTER (TYPE_NAME (t)); | |
378 | else | |
379 | { | |
380 | data_type = ""; | |
381 | chain_p = TYPE_FIELDS (t); | |
382 | while (chain_p) | |
383 | { | |
2778b98d KG |
384 | data_type = concat (data_type, gen_decl (chain_p, 0, ansi), |
385 | NULL_PTR); | |
2bbd3819 | 386 | chain_p = TREE_CHAIN (chain_p); |
2778b98d | 387 | data_type = concat (data_type, "; ", NULL_PTR); |
2bbd3819 | 388 | } |
2778b98d | 389 | data_type = concat ("{ ", data_type, "}", NULL_PTR); |
2bbd3819 | 390 | } |
2778b98d | 391 | data_type = concat ("struct ", data_type, NULL_PTR); |
2bbd3819 RS |
392 | break; |
393 | ||
394 | case UNION_TYPE: | |
395 | if (TYPE_NAME (t)) | |
396 | data_type = IDENTIFIER_POINTER (TYPE_NAME (t)); | |
397 | else | |
398 | { | |
399 | data_type = ""; | |
400 | chain_p = TYPE_FIELDS (t); | |
401 | while (chain_p) | |
402 | { | |
2778b98d KG |
403 | data_type = concat (data_type, gen_decl (chain_p, 0, ansi), |
404 | NULL_PTR); | |
2bbd3819 | 405 | chain_p = TREE_CHAIN (chain_p); |
2778b98d | 406 | data_type = concat (data_type, "; ", NULL_PTR); |
2bbd3819 | 407 | } |
2778b98d | 408 | data_type = concat ("{ ", data_type, "}", NULL_PTR); |
2bbd3819 | 409 | } |
2778b98d | 410 | data_type = concat ("union ", data_type, NULL_PTR); |
2bbd3819 RS |
411 | break; |
412 | ||
413 | case ENUMERAL_TYPE: | |
414 | if (TYPE_NAME (t)) | |
415 | data_type = IDENTIFIER_POINTER (TYPE_NAME (t)); | |
416 | else | |
417 | { | |
418 | data_type = ""; | |
419 | chain_p = TYPE_VALUES (t); | |
420 | while (chain_p) | |
421 | { | |
422 | data_type = concat (data_type, | |
2778b98d | 423 | IDENTIFIER_POINTER (TREE_PURPOSE (chain_p)), NULL_PTR); |
2bbd3819 RS |
424 | chain_p = TREE_CHAIN (chain_p); |
425 | if (chain_p) | |
2778b98d | 426 | data_type = concat (data_type, ", ", NULL_PTR); |
2bbd3819 | 427 | } |
2778b98d | 428 | data_type = concat ("{ ", data_type, " }", NULL_PTR); |
2bbd3819 | 429 | } |
2778b98d | 430 | data_type = concat ("enum ", data_type, NULL_PTR); |
2bbd3819 RS |
431 | break; |
432 | ||
433 | case TYPE_DECL: | |
434 | data_type = IDENTIFIER_POINTER (DECL_NAME (t)); | |
435 | break; | |
436 | ||
437 | case INTEGER_TYPE: | |
438 | data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); | |
439 | /* Normally, `unsigned' is part of the deal. Not so if it comes | |
3932261a MM |
440 | with a type qualifier. */ |
441 | if (TREE_UNSIGNED (t) && TYPE_QUALS (t)) | |
2778b98d | 442 | data_type = concat ("unsigned ", data_type, NULL_PTR); |
2bbd3819 RS |
443 | break; |
444 | ||
445 | case REAL_TYPE: | |
446 | data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t))); | |
447 | break; | |
448 | ||
449 | case VOID_TYPE: | |
450 | data_type = "void"; | |
451 | break; | |
452 | ||
61d2941a RK |
453 | case ERROR_MARK: |
454 | data_type = "[ERROR]"; | |
455 | break; | |
456 | ||
2bbd3819 RS |
457 | default: |
458 | abort (); | |
459 | } | |
460 | } | |
461 | if (TYPE_READONLY (t)) | |
2778b98d | 462 | ret_val = concat ("const ", ret_val, NULL_PTR); |
2bbd3819 | 463 | if (TYPE_VOLATILE (t)) |
2778b98d | 464 | ret_val = concat ("volatile ", ret_val, NULL_PTR); |
3932261a | 465 | if (TYPE_RESTRICT (t)) |
2778b98d | 466 | ret_val = concat ("restrict ", ret_val, NULL_PTR); |
2bbd3819 RS |
467 | return ret_val; |
468 | } | |
469 | ||
470 | /* Generate a string (source) representation of an entire entity declaration | |
471 | (using some particular style for function types). | |
472 | ||
473 | The given entity may be either a variable or a function. | |
474 | ||
475 | If the "is_func_definition" parameter is non-zero, assume that the thing | |
476 | we are generating a declaration for is a FUNCTION_DECL node which is | |
477 | associated with a function definition. In this case, we can assume that | |
478 | an attached list of DECL nodes for function formal arguments is present. */ | |
479 | ||
dff01034 | 480 | static const char * |
2bbd3819 RS |
481 | gen_decl (decl, is_func_definition, style) |
482 | tree decl; | |
483 | int is_func_definition; | |
484 | formals_style style; | |
485 | { | |
dff01034 | 486 | const char *ret_val; |
2bbd3819 RS |
487 | |
488 | if (DECL_NAME (decl)) | |
489 | ret_val = IDENTIFIER_POINTER (DECL_NAME (decl)); | |
490 | else | |
491 | ret_val = ""; | |
492 | ||
493 | /* If we are just generating a list of names of formal parameters, we can | |
494 | simply return the formal parameter name (with no typing information | |
495 | attached to it) now. */ | |
496 | ||
497 | if (style == k_and_r_names) | |
498 | return ret_val; | |
499 | ||
500 | /* Note that for the declaration of some entity (either a function or a | |
501 | data object, like for instance a parameter) if the entity itself was | |
502 | declared as either const or volatile, then const and volatile properties | |
503 | are associated with just the declaration of the entity, and *not* with | |
504 | the `type' of the entity. Thus, for such declared entities, we have to | |
505 | generate the qualifiers here. */ | |
506 | ||
507 | if (TREE_THIS_VOLATILE (decl)) | |
2778b98d | 508 | ret_val = concat ("volatile ", ret_val, NULL_PTR); |
2bbd3819 | 509 | if (TREE_READONLY (decl)) |
2778b98d | 510 | ret_val = concat ("const ", ret_val, NULL_PTR); |
2bbd3819 RS |
511 | |
512 | data_type = ""; | |
513 | ||
514 | /* For FUNCTION_DECL nodes, there are two possible cases here. First, if | |
515 | this FUNCTION_DECL node was generated from a function "definition", then | |
516 | we will have a list of DECL_NODE's, one for each of the function's formal | |
517 | parameters. In this case, we can print out not only the types of each | |
518 | formal, but also each formal's name. In the second case, this | |
519 | FUNCTION_DECL node came from an actual function declaration (and *not* | |
520 | a definition). In this case, we do nothing here because the formal | |
521 | argument type-list will be output later, when the "type" of the function | |
522 | is added to the string we are building. Note that the ANSI-style formal | |
523 | parameter list is considered to be a (suffix) part of the "type" of the | |
524 | function. */ | |
525 | ||
526 | if (TREE_CODE (decl) == FUNCTION_DECL && is_func_definition) | |
527 | { | |
2778b98d KG |
528 | ret_val = concat (ret_val, gen_formal_list_for_func_def (decl, ansi), |
529 | NULL_PTR); | |
2bbd3819 RS |
530 | |
531 | /* Since we have already added in the formals list stuff, here we don't | |
532 | add the whole "type" of the function we are considering (which | |
533 | would include its parameter-list info), rather, we only add in | |
534 | the "type" of the "type" of the function, which is really just | |
535 | the return-type of the function (and does not include the parameter | |
536 | list info). */ | |
537 | ||
538 | ret_val = gen_type (ret_val, TREE_TYPE (TREE_TYPE (decl)), style); | |
539 | } | |
540 | else | |
541 | ret_val = gen_type (ret_val, TREE_TYPE (decl), style); | |
542 | ||
543 | ret_val = affix_data_type (ret_val); | |
544 | ||
70f75202 | 545 | if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)) |
2778b98d | 546 | ret_val = concat ("register ", ret_val, NULL_PTR); |
2bbd3819 | 547 | if (TREE_PUBLIC (decl)) |
2778b98d | 548 | ret_val = concat ("extern ", ret_val, NULL_PTR); |
2bbd3819 | 549 | if (TREE_CODE (decl) == FUNCTION_DECL && !TREE_PUBLIC (decl)) |
2778b98d | 550 | ret_val = concat ("static ", ret_val, NULL_PTR); |
2bbd3819 RS |
551 | |
552 | return ret_val; | |
553 | } | |
554 | ||
0f41302f | 555 | extern FILE *aux_info_file; |
2bbd3819 RS |
556 | |
557 | /* Generate and write a new line of info to the aux-info (.X) file. This | |
558 | routine is called once for each function declaration, and once for each | |
559 | function definition (even the implicit ones). */ | |
560 | ||
561 | void | |
562 | gen_aux_info_record (fndecl, is_definition, is_implicit, is_prototyped) | |
563 | tree fndecl; | |
564 | int is_definition; | |
565 | int is_implicit; | |
566 | int is_prototyped; | |
567 | { | |
568 | if (flag_gen_aux_info) | |
569 | { | |
570 | static int compiled_from_record = 0; | |
571 | ||
572 | /* Each output .X file must have a header line. Write one now if we | |
573 | have not yet done so. */ | |
574 | ||
575 | if (! compiled_from_record++) | |
576 | { | |
7d57b4ca | 577 | /* The first line tells which directory file names are relative to. |
872d115f | 578 | Currently, -aux-info works only for files in the working |
7d57b4ca RS |
579 | directory, so just use a `.' as a placeholder for now. */ |
580 | fprintf (aux_info_file, "/* compiled from: . */\n"); | |
2bbd3819 RS |
581 | } |
582 | ||
d45cf215 | 583 | /* Write the actual line of auxiliary info. */ |
2bbd3819 RS |
584 | |
585 | fprintf (aux_info_file, "/* %s:%d:%c%c */ %s;", | |
586 | DECL_SOURCE_FILE (fndecl), | |
587 | DECL_SOURCE_LINE (fndecl), | |
588 | (is_implicit) ? 'I' : (is_prototyped) ? 'N' : 'O', | |
589 | (is_definition) ? 'F' : 'C', | |
590 | gen_decl (fndecl, is_definition, ansi)); | |
591 | ||
592 | /* If this is an explicit function declaration, we need to also write | |
593 | out an old-style (i.e. K&R) function header, just in case the user | |
594 | wants to run unprotoize. */ | |
595 | ||
596 | if (is_definition) | |
597 | { | |
598 | fprintf (aux_info_file, " /*%s %s*/", | |
599 | gen_formal_list_for_func_def (fndecl, k_and_r_names), | |
600 | gen_formal_list_for_func_def (fndecl, k_and_r_decls)); | |
601 | } | |
602 | ||
603 | fprintf (aux_info_file, "\n"); | |
604 | } | |
605 | } |