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