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