Allow returning something of type void in a function that returns void
[delight/core.git] / d-bi-attrs-40.h
blob8e55dc679e6cac04409b36d56986076028c9d315
1 static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
2 static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
3 static tree handle_common_attribute (tree *, tree, tree, int, bool *);
4 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
5 static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
6 static tree handle_always_inline_attribute (tree *, tree, tree, int,
7 bool *);
8 static tree handle_used_attribute (tree *, tree, tree, int, bool *);
9 static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
10 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
11 static tree handle_transparent_union_attribute (tree *, tree, tree,
12 int, bool *);
13 static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
14 static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
15 static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
16 static tree handle_section_attribute (tree *, tree, tree, int, bool *);
17 static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
18 static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
19 static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
20 static tree handle_visibility_attribute (tree *, tree, tree, int,
21 bool *);
22 static tree handle_tls_model_attribute (tree *, tree, tree, int,
23 bool *);
24 static tree handle_no_instrument_function_attribute (tree *, tree,
25 tree, int, bool *);
26 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
27 static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
28 bool *);
29 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
30 static tree handle_deprecated_attribute (tree *, tree, tree, int,
31 bool *);
32 static tree handle_vector_size_attribute (tree *, tree, tree, int,
33 bool *);
34 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
35 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
36 //static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
37 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
38 bool *);
39 static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
41 //static void check_function_nonnull (tree, tree);
42 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
43 static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
44 static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
45 //static int resort_field_decl_cmp (const void *, const void *);
47 /* extra for gdc copy: */
48 static void check_function_arguments_recurse (void (*)
49 (void *, tree,
50 unsigned HOST_WIDE_INT),
51 void *, tree,
52 unsigned HOST_WIDE_INT);
54 static tree
55 handle_format_arg_attribute (tree *node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED,
56 tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs ATTRIBUTE_UNUSED)
58 return NULL_TREE;
60 static tree
61 handle_format_attribute (tree *node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED, tree args ATTRIBUTE_UNUSED,
62 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs ATTRIBUTE_UNUSED)
64 return NULL_TREE;
66 /* -- end extra */
68 /* Table of machine-independent attributes common to all C-like languages. */
69 const struct attribute_spec d_common_attribute_table[] =
71 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
72 { "packed", 0, 0, false, false, false,
73 handle_packed_attribute },
74 { "nocommon", 0, 0, true, false, false,
75 handle_nocommon_attribute },
76 { "common", 0, 0, true, false, false,
77 handle_common_attribute },
78 /* FIXME: logically, noreturn attributes should be listed as
79 "false, true, true" and apply to function types. But implementing this
80 would require all the places in the compiler that use TREE_THIS_VOLATILE
81 on a decl to identify non-returning functions to be located and fixed
82 to check the function type instead. */
83 { "noreturn", 0, 0, true, false, false,
84 handle_noreturn_attribute },
85 { "volatile", 0, 0, true, false, false,
86 handle_noreturn_attribute },
87 { "noinline", 0, 0, true, false, false,
88 handle_noinline_attribute },
89 { "always_inline", 0, 0, true, false, false,
90 handle_always_inline_attribute },
91 { "used", 0, 0, true, false, false,
92 handle_used_attribute },
93 { "unused", 0, 0, false, false, false,
94 handle_unused_attribute },
95 /* The same comments as for noreturn attributes apply to const ones. */
96 { "const", 0, 0, true, false, false,
97 handle_const_attribute },
98 { "transparent_union", 0, 0, false, false, false,
99 handle_transparent_union_attribute },
100 { "constructor", 0, 0, true, false, false,
101 handle_constructor_attribute },
102 { "destructor", 0, 0, true, false, false,
103 handle_destructor_attribute },
104 { "mode", 1, 1, false, true, false,
105 handle_mode_attribute },
106 { "section", 1, 1, true, false, false,
107 handle_section_attribute },
108 { "aligned", 0, 1, false, false, false,
109 handle_aligned_attribute },
110 { "weak", 0, 0, true, false, false,
111 handle_weak_attribute },
112 { "alias", 1, 1, true, false, false,
113 handle_alias_attribute },
114 { "no_instrument_function", 0, 0, true, false, false,
115 handle_no_instrument_function_attribute },
116 { "malloc", 0, 0, true, false, false,
117 handle_malloc_attribute },
118 { "no_stack_limit", 0, 0, true, false, false,
119 handle_no_limit_stack_attribute },
120 { "pure", 0, 0, true, false, false,
121 handle_pure_attribute },
122 { "deprecated", 0, 0, false, false, false,
123 handle_deprecated_attribute },
124 { "vector_size", 1, 1, false, true, false,
125 handle_vector_size_attribute },
126 { "visibility", 1, 1, false, false, false,
127 handle_visibility_attribute },
128 { "tls_model", 1, 1, true, false, false,
129 handle_tls_model_attribute },
130 { "nonnull", 0, -1, false, true, true,
131 handle_nonnull_attribute },
132 { "nothrow", 0, 0, true, false, false,
133 handle_nothrow_attribute },
134 { "may_alias", 0, 0, false, true, false, NULL },
135 /* not in gdc// { "cleanup", 1, 1, true, false, false,
136 handle_cleanup_attribute },*/
137 { "warn_unused_result", 0, 0, false, true, true,
138 handle_warn_unused_result_attribute },
139 { "sentinel", 0, 1, false, true, true,
140 handle_sentinel_attribute },
141 { NULL, 0, 0, false, false, false, NULL }
144 /* Give the specifications for the format attributes, used by C and all
145 descendants. */
147 const struct attribute_spec d_common_format_attribute_table[] =
149 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
150 { "format", 3, 3, false, true, true,
151 handle_format_attribute },
152 { "format_arg", 1, 1, false, true, true,
153 handle_format_arg_attribute },
154 { NULL, 0, 0, false, false, false, NULL }
157 /* Attribute handlers common to C front ends. */
159 /* Handle a "packed" attribute; arguments as in
160 struct attribute_spec.handler. */
162 static tree
163 handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
164 int flags, bool *no_add_attrs)
166 if (TYPE_P (*node))
168 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
169 *node = build_variant_type_copy (*node);
170 TYPE_PACKED (*node) = 1;
171 if (TYPE_MAIN_VARIANT (*node) == *node)
173 /* If it is the main variant, then pack the other variants
174 too. This happens in,
176 struct Foo {
177 struct Foo const *ptr; // creates a variant w/o packed flag
178 } __ attribute__((packed)); // packs it now.
180 tree probe;
182 for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe))
183 TYPE_PACKED (probe) = 1;
187 else if (TREE_CODE (*node) == FIELD_DECL)
188 DECL_PACKED (*node) = 1;
189 /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
190 used for DECL_REGISTER. It wouldn't mean anything anyway.
191 We can't set DECL_PACKED on the type of a TYPE_DECL, because
192 that changes what the typedef is typing. */
193 else
195 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
196 *no_add_attrs = true;
199 return NULL_TREE;
202 /* Handle a "nocommon" attribute; arguments as in
203 struct attribute_spec.handler. */
205 static tree
206 handle_nocommon_attribute (tree *node, tree name,
207 tree ARG_UNUSED (args),
208 int ARG_UNUSED (flags), bool *no_add_attrs)
210 if (TREE_CODE (*node) == VAR_DECL)
211 DECL_COMMON (*node) = 0;
212 else
214 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
215 *no_add_attrs = true;
218 return NULL_TREE;
221 /* Handle a "common" attribute; arguments as in
222 struct attribute_spec.handler. */
224 static tree
225 handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
226 int ARG_UNUSED (flags), bool *no_add_attrs)
228 if (TREE_CODE (*node) == VAR_DECL)
229 DECL_COMMON (*node) = 1;
230 else
232 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
233 *no_add_attrs = true;
236 return NULL_TREE;
239 /* Handle a "noreturn" attribute; arguments as in
240 struct attribute_spec.handler. */
242 static tree
243 handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
244 int ARG_UNUSED (flags), bool *no_add_attrs)
246 tree type = TREE_TYPE (*node);
248 /* See FIXME comment in c_common_attribute_table. */
249 if (TREE_CODE (*node) == FUNCTION_DECL)
250 TREE_THIS_VOLATILE (*node) = 1;
251 else if (TREE_CODE (type) == POINTER_TYPE
252 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
253 TREE_TYPE (*node)
254 = build_pointer_type
255 (build_type_variant (TREE_TYPE (type),
256 TYPE_READONLY (TREE_TYPE (type)), 1));
257 else
259 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
260 *no_add_attrs = true;
263 return NULL_TREE;
266 /* Handle a "noinline" attribute; arguments as in
267 struct attribute_spec.handler. */
269 static tree
270 handle_noinline_attribute (tree *node, tree name,
271 tree ARG_UNUSED (args),
272 int ARG_UNUSED (flags), bool *no_add_attrs)
274 if (TREE_CODE (*node) == FUNCTION_DECL)
275 DECL_UNINLINABLE (*node) = 1;
276 else
278 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
279 *no_add_attrs = true;
282 return NULL_TREE;
285 /* Handle a "always_inline" attribute; arguments as in
286 struct attribute_spec.handler. */
288 static tree
289 handle_always_inline_attribute (tree *node, tree name,
290 tree ARG_UNUSED (args),
291 int ARG_UNUSED (flags),
292 bool *no_add_attrs)
294 if (TREE_CODE (*node) == FUNCTION_DECL)
296 /* Do nothing else, just set the attribute. We'll get at
297 it later with lookup_attribute. */
299 else
301 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
302 *no_add_attrs = true;
305 return NULL_TREE;
308 /* Handle a "used" attribute; arguments as in
309 struct attribute_spec.handler. */
311 static tree
312 handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
313 int ARG_UNUSED (flags), bool *no_add_attrs)
315 tree node = *pnode;
317 if (TREE_CODE (node) == FUNCTION_DECL
318 || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
320 TREE_USED (node) = 1;
321 DECL_PRESERVE_P (node) = 1;
323 else
325 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
326 *no_add_attrs = true;
329 return NULL_TREE;
332 /* Handle a "unused" attribute; arguments as in
333 struct attribute_spec.handler. */
335 static tree
336 handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
337 int flags, bool *no_add_attrs)
339 if (DECL_P (*node))
341 tree decl = *node;
343 if (TREE_CODE (decl) == PARM_DECL
344 || TREE_CODE (decl) == VAR_DECL
345 || TREE_CODE (decl) == FUNCTION_DECL
346 || TREE_CODE (decl) == LABEL_DECL
347 || TREE_CODE (decl) == TYPE_DECL)
348 TREE_USED (decl) = 1;
349 else
351 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
352 *no_add_attrs = true;
355 else
357 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
358 *node = build_variant_type_copy (*node);
359 TREE_USED (*node) = 1;
362 return NULL_TREE;
365 /* Handle a "const" attribute; arguments as in
366 struct attribute_spec.handler. */
368 static tree
369 handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
370 int ARG_UNUSED (flags), bool *no_add_attrs)
372 tree type = TREE_TYPE (*node);
374 /* See FIXME comment on noreturn in c_common_attribute_table. */
375 if (TREE_CODE (*node) == FUNCTION_DECL)
376 TREE_READONLY (*node) = 1;
377 else if (TREE_CODE (type) == POINTER_TYPE
378 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
379 TREE_TYPE (*node)
380 = build_pointer_type
381 (build_type_variant (TREE_TYPE (type), 1,
382 TREE_THIS_VOLATILE (TREE_TYPE (type))));
383 else
385 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
386 *no_add_attrs = true;
389 return NULL_TREE;
392 /* Handle a "transparent_union" attribute; arguments as in
393 struct attribute_spec.handler. */
395 static tree
396 handle_transparent_union_attribute (tree *node, tree name,
397 tree ARG_UNUSED (args), int flags,
398 bool *no_add_attrs)
400 tree decl = NULL_TREE;
401 tree *type = NULL;
402 int is_type = 0;
404 if (DECL_P (*node))
406 decl = *node;
407 type = &TREE_TYPE (decl);
408 is_type = TREE_CODE (*node) == TYPE_DECL;
410 else if (TYPE_P (*node))
411 type = node, is_type = 1;
413 if (is_type
414 && TREE_CODE (*type) == UNION_TYPE
415 && (decl == 0
416 || (TYPE_FIELDS (*type) != 0
417 && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
419 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
420 *type = build_variant_type_copy (*type);
421 TYPE_TRANSPARENT_UNION (*type) = 1;
423 else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
424 && TREE_CODE (*type) == UNION_TYPE
425 && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
426 DECL_TRANSPARENT_UNION (decl) = 1;
427 else
429 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
430 *no_add_attrs = true;
433 return NULL_TREE;
436 /* Handle a "constructor" attribute; arguments as in
437 struct attribute_spec.handler. */
439 static tree
440 handle_constructor_attribute (tree *node, tree name,
441 tree ARG_UNUSED (args),
442 int ARG_UNUSED (flags),
443 bool *no_add_attrs)
445 tree decl = *node;
446 tree type = TREE_TYPE (decl);
448 if (TREE_CODE (decl) == FUNCTION_DECL
449 && TREE_CODE (type) == FUNCTION_TYPE
450 && decl_function_context (decl) == 0)
452 DECL_STATIC_CONSTRUCTOR (decl) = 1;
453 TREE_USED (decl) = 1;
455 else
457 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
458 *no_add_attrs = true;
461 return NULL_TREE;
464 /* Handle a "destructor" attribute; arguments as in
465 struct attribute_spec.handler. */
467 static tree
468 handle_destructor_attribute (tree *node, tree name,
469 tree ARG_UNUSED (args),
470 int ARG_UNUSED (flags),
471 bool *no_add_attrs)
473 tree decl = *node;
474 tree type = TREE_TYPE (decl);
476 if (TREE_CODE (decl) == FUNCTION_DECL
477 && TREE_CODE (type) == FUNCTION_TYPE
478 && decl_function_context (decl) == 0)
480 DECL_STATIC_DESTRUCTOR (decl) = 1;
481 TREE_USED (decl) = 1;
483 else
485 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
486 *no_add_attrs = true;
489 return NULL_TREE;
492 /* Handle a "mode" attribute; arguments as in
493 struct attribute_spec.handler. */
495 static tree
496 handle_mode_attribute (tree *node, tree name, tree args,
497 int ARG_UNUSED (flags), bool *no_add_attrs)
499 tree type = *node;
501 *no_add_attrs = true;
503 if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
504 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
505 else
507 int j;
508 const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
509 int len = strlen (p);
510 enum machine_mode mode = VOIDmode;
511 tree typefm;
512 bool valid_mode;
514 if (len > 4 && p[0] == '_' && p[1] == '_'
515 && p[len - 1] == '_' && p[len - 2] == '_')
517 char *newp = (char *) alloca (len - 1);
519 strcpy (newp, &p[2]);
520 newp[len - 4] = '\0';
521 p = newp;
524 /* Change this type to have a type with the specified mode.
525 First check for the special modes. */
526 if (!strcmp (p, "byte"))
527 mode = byte_mode;
528 else if (!strcmp (p, "word"))
529 mode = word_mode;
530 else if (!strcmp (p, "pointer"))
531 mode = ptr_mode;
532 else
533 for (j = 0; j < NUM_MACHINE_MODES; j++)
534 if (!strcmp (p, GET_MODE_NAME (j)))
536 mode = (enum machine_mode) j;
537 break;
540 if (mode == VOIDmode)
542 error ("unknown machine mode %qs", p);
543 return NULL_TREE;
546 valid_mode = false;
547 switch (GET_MODE_CLASS (mode))
549 case MODE_INT:
550 case MODE_PARTIAL_INT:
551 case MODE_FLOAT:
552 valid_mode = targetm.scalar_mode_supported_p (mode);
553 break;
555 case MODE_COMPLEX_INT:
556 case MODE_COMPLEX_FLOAT:
557 valid_mode = targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
558 break;
560 case MODE_VECTOR_INT:
561 case MODE_VECTOR_FLOAT:
562 warning ("specifying vector types with __attribute__ ((mode)) "
563 "is deprecated");
564 warning ("use __attribute__ ((vector_size)) instead");
565 valid_mode = vector_mode_valid_p (mode);
566 break;
568 default:
569 break;
571 if (!valid_mode)
573 error ("unable to emulate %qs", p);
574 return NULL_TREE;
577 if (POINTER_TYPE_P (type))
579 tree (*fn)(tree, enum machine_mode, bool);
581 if (!targetm.valid_pointer_mode (mode))
583 error ("invalid pointer mode %qs", p);
584 return NULL_TREE;
587 if (TREE_CODE (type) == POINTER_TYPE)
588 fn = build_pointer_type_for_mode;
589 else
590 fn = build_reference_type_for_mode;
591 typefm = fn (TREE_TYPE (type), mode, false);
593 else
594 typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
596 if (typefm == NULL_TREE)
598 error ("no data type for mode %qs", p);
599 return NULL_TREE;
601 else if (TREE_CODE (type) == ENUMERAL_TYPE)
603 /* For enumeral types, copy the precision from the integer
604 type returned above. If not an INTEGER_TYPE, we can't use
605 this mode for this type. */
606 if (TREE_CODE (typefm) != INTEGER_TYPE)
608 error ("cannot use mode %qs for enumeral types", p);
609 return NULL_TREE;
612 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
613 type = build_variant_type_copy (type);
615 /* We cannot use layout_type here, because that will attempt
616 to re-layout all variants, corrupting our original. */
617 TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
618 TYPE_MIN_VALUE (type) = TYPE_MIN_VALUE (typefm);
619 TYPE_MAX_VALUE (type) = TYPE_MAX_VALUE (typefm);
620 TYPE_SIZE (type) = TYPE_SIZE (typefm);
621 TYPE_SIZE_UNIT (type) = TYPE_SIZE_UNIT (typefm);
622 TYPE_MODE (type) = TYPE_MODE (typefm);
623 if (!TYPE_USER_ALIGN (type))
624 TYPE_ALIGN (type) = TYPE_ALIGN (typefm);
626 typefm = type;
628 else if (VECTOR_MODE_P (mode)
629 ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
630 : TREE_CODE (type) != TREE_CODE (typefm))
632 error ("mode %qs applied to inappropriate type", p);
633 return NULL_TREE;
636 *node = typefm;
639 return NULL_TREE;
642 /* Handle a "section" attribute; arguments as in
643 struct attribute_spec.handler. */
645 static tree
646 handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
647 int ARG_UNUSED (flags), bool *no_add_attrs)
649 tree decl = *node;
651 if (targetm.have_named_sections)
653 user_defined_section_attribute = true;
655 if ((TREE_CODE (decl) == FUNCTION_DECL
656 || TREE_CODE (decl) == VAR_DECL)
657 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
659 if (TREE_CODE (decl) == VAR_DECL
660 && current_function_decl != NULL_TREE
661 && ! (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
663 error ("%Jsection attribute cannot be specified for "
664 "local variables", decl);
665 *no_add_attrs = true;
668 /* The decl may have already been given a section attribute
669 from a previous declaration. Ensure they match. */
670 else if (DECL_SECTION_NAME (decl) != NULL_TREE
671 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
672 TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
674 error ("%Jsection of %qD conflicts with previous declaration",
675 *node, *node);
676 *no_add_attrs = true;
678 else
679 DECL_SECTION_NAME (decl) = TREE_VALUE (args);
681 else
683 error ("%Jsection attribute not allowed for %qD", *node, *node);
684 *no_add_attrs = true;
687 else
689 error ("%Jsection attributes are not supported for this target", *node);
690 *no_add_attrs = true;
693 return NULL_TREE;
696 /* Handle a "aligned" attribute; arguments as in
697 struct attribute_spec.handler. */
699 static tree
700 handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
701 int flags, bool *no_add_attrs)
703 tree decl = NULL_TREE;
704 tree *type = NULL;
705 int is_type = 0;
706 tree align_expr = (args ? TREE_VALUE (args)
707 : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
708 int i;
710 if (DECL_P (*node))
712 decl = *node;
713 type = &TREE_TYPE (decl);
714 is_type = TREE_CODE (*node) == TYPE_DECL;
716 else if (TYPE_P (*node))
717 type = node, is_type = 1;
719 /* Strip any NOPs of any kind. */
720 while (TREE_CODE (align_expr) == NOP_EXPR
721 || TREE_CODE (align_expr) == CONVERT_EXPR
722 || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
723 align_expr = TREE_OPERAND (align_expr, 0);
725 if (TREE_CODE (align_expr) != INTEGER_CST)
727 error ("requested alignment is not a constant");
728 *no_add_attrs = true;
730 else if ((i = tree_log2 (align_expr)) == -1)
732 error ("requested alignment is not a power of 2");
733 *no_add_attrs = true;
735 else if (i > HOST_BITS_PER_INT - 2)
737 error ("requested alignment is too large");
738 *no_add_attrs = true;
740 else if (is_type)
742 /* If we have a TYPE_DECL, then copy the type, so that we
743 don't accidentally modify a builtin type. See pushdecl. */
744 if (decl && TREE_TYPE (decl) != error_mark_node
745 && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
747 tree tt = TREE_TYPE (decl);
748 *type = build_variant_type_copy (*type);
749 DECL_ORIGINAL_TYPE (decl) = tt;
750 TYPE_NAME (*type) = decl;
751 TREE_USED (*type) = TREE_USED (decl);
752 TREE_TYPE (decl) = *type;
754 else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
755 *type = build_variant_type_copy (*type);
757 TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
758 TYPE_USER_ALIGN (*type) = 1;
760 else if (TREE_CODE (decl) != VAR_DECL
761 && TREE_CODE (decl) != FIELD_DECL)
763 error ("%Jalignment may not be specified for %qD", decl, decl);
764 *no_add_attrs = true;
766 else
768 DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
769 DECL_USER_ALIGN (decl) = 1;
772 return NULL_TREE;
775 /* Handle a "weak" attribute; arguments as in
776 struct attribute_spec.handler. */
778 static tree
779 handle_weak_attribute (tree *node, tree ARG_UNUSED (name),
780 tree ARG_UNUSED (args),
781 int ARG_UNUSED (flags),
782 bool * ARG_UNUSED (no_add_attrs))
784 declare_weak (*node);
786 return NULL_TREE;
789 /* Handle an "alias" attribute; arguments as in
790 struct attribute_spec.handler. */
792 static tree
793 handle_alias_attribute (tree *node, tree name, tree args,
794 int ARG_UNUSED (flags), bool *no_add_attrs)
796 tree decl = *node;
798 if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
799 || (TREE_CODE (decl) != FUNCTION_DECL && !DECL_EXTERNAL (decl)))
801 error ("%J%qD defined both normally and as an alias", decl, decl);
802 *no_add_attrs = true;
805 /* Note that the very first time we process a nested declaration,
806 decl_function_context will not be set. Indeed, *would* never
807 be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
808 we do below. After such frobbery, pushdecl would set the context.
809 In any case, this is never what we want. */
810 else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
812 tree id;
814 id = TREE_VALUE (args);
815 if (TREE_CODE (id) != STRING_CST)
817 error ("alias argument not a string");
818 *no_add_attrs = true;
819 return NULL_TREE;
821 id = get_identifier (TREE_STRING_POINTER (id));
822 /* This counts as a use of the object pointed to. */
823 TREE_USED (id) = 1;
825 if (TREE_CODE (decl) == FUNCTION_DECL)
826 DECL_INITIAL (decl) = error_mark_node;
827 else
829 DECL_EXTERNAL (decl) = 0;
830 TREE_STATIC (decl) = 1;
833 else
835 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
836 *no_add_attrs = true;
839 return NULL_TREE;
842 /* Handle an "visibility" attribute; arguments as in
843 struct attribute_spec.handler. */
845 static tree
846 handle_visibility_attribute (tree *node, tree name, tree args,
847 int ARG_UNUSED (flags),
848 bool *no_add_attrs)
850 tree decl = *node;
851 tree id = TREE_VALUE (args);
853 *no_add_attrs = true;
855 if (TYPE_P (*node))
857 if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
859 warning ("%qs attribute ignored on non-class types",
860 IDENTIFIER_POINTER (name));
861 return NULL_TREE;
864 else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
866 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
867 return NULL_TREE;
870 if (TREE_CODE (id) != STRING_CST)
872 error ("visibility argument not a string");
873 return NULL_TREE;
876 /* If this is a type, set the visibility on the type decl. */
877 if (TYPE_P (decl))
879 decl = TYPE_NAME (decl);
880 if (!decl)
881 return NULL_TREE;
882 if (TREE_CODE (decl) == IDENTIFIER_NODE)
884 warning ("%qE attribute ignored on types",
885 name);
886 return NULL_TREE;
890 if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
891 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
892 else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
893 DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL;
894 else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
895 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
896 else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
897 DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
898 else
899 error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
900 DECL_VISIBILITY_SPECIFIED (decl) = 1;
902 /* For decls only, go ahead and attach the attribute to the node as well.
903 This is needed so we can determine whether we have VISIBILITY_DEFAULT
904 because the visibility was not specified, or because it was explicitly
905 overridden from the class visibility. */
906 if (DECL_P (*node))
907 *no_add_attrs = false;
909 return NULL_TREE;
912 /* Handle an "tls_model" attribute; arguments as in
913 struct attribute_spec.handler. */
915 static tree
916 handle_tls_model_attribute (tree *node, tree name, tree args,
917 int ARG_UNUSED (flags), bool *no_add_attrs)
919 tree decl = *node;
921 if (!DECL_THREAD_LOCAL (decl))
923 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
924 *no_add_attrs = true;
926 else
928 tree id;
930 id = TREE_VALUE (args);
931 if (TREE_CODE (id) != STRING_CST)
933 error ("tls_model argument not a string");
934 *no_add_attrs = true;
935 return NULL_TREE;
937 if (strcmp (TREE_STRING_POINTER (id), "local-exec")
938 && strcmp (TREE_STRING_POINTER (id), "initial-exec")
939 && strcmp (TREE_STRING_POINTER (id), "local-dynamic")
940 && strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
942 error ("tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
943 *no_add_attrs = true;
944 return NULL_TREE;
948 return NULL_TREE;
951 /* Handle a "no_instrument_function" attribute; arguments as in
952 struct attribute_spec.handler. */
954 static tree
955 handle_no_instrument_function_attribute (tree *node, tree name,
956 tree ARG_UNUSED (args),
957 int ARG_UNUSED (flags),
958 bool *no_add_attrs)
960 tree decl = *node;
962 if (TREE_CODE (decl) != FUNCTION_DECL)
964 error ("%J%qE attribute applies only to functions", decl, name);
965 *no_add_attrs = true;
967 else if (DECL_INITIAL (decl))
969 error ("%Jcan%'t set %qE attribute after definition", decl, name);
970 *no_add_attrs = true;
972 else
973 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
975 return NULL_TREE;
978 /* Handle a "malloc" attribute; arguments as in
979 struct attribute_spec.handler. */
981 static tree
982 handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
983 int ARG_UNUSED (flags), bool *no_add_attrs)
985 if (TREE_CODE (*node) == FUNCTION_DECL)
986 DECL_IS_MALLOC (*node) = 1;
987 /* ??? TODO: Support types. */
988 else
990 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
991 *no_add_attrs = true;
994 return NULL_TREE;
997 /* Handle a "no_limit_stack" attribute; arguments as in
998 struct attribute_spec.handler. */
1000 static tree
1001 handle_no_limit_stack_attribute (tree *node, tree name,
1002 tree ARG_UNUSED (args),
1003 int ARG_UNUSED (flags),
1004 bool *no_add_attrs)
1006 tree decl = *node;
1008 if (TREE_CODE (decl) != FUNCTION_DECL)
1010 error ("%J%qE attribute applies only to functions", decl, name);
1011 *no_add_attrs = true;
1013 else if (DECL_INITIAL (decl))
1015 error ("%Jcan%'t set %qE attribute after definition", decl, name);
1016 *no_add_attrs = true;
1018 else
1019 DECL_NO_LIMIT_STACK (decl) = 1;
1021 return NULL_TREE;
1024 /* Handle a "pure" attribute; arguments as in
1025 struct attribute_spec.handler. */
1027 static tree
1028 handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1029 int ARG_UNUSED (flags), bool *no_add_attrs)
1031 if (TREE_CODE (*node) == FUNCTION_DECL)
1032 DECL_IS_PURE (*node) = 1;
1033 /* ??? TODO: Support types. */
1034 else
1036 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
1037 *no_add_attrs = true;
1040 return NULL_TREE;
1043 /* Handle a "deprecated" attribute; arguments as in
1044 struct attribute_spec.handler. */
1046 static tree
1047 handle_deprecated_attribute (tree *node, tree name,
1048 tree ARG_UNUSED (args), int flags,
1049 bool *no_add_attrs)
1051 tree type = NULL_TREE;
1052 int warn = 0;
1053 const char *what = NULL;
1055 if (DECL_P (*node))
1057 tree decl = *node;
1058 type = TREE_TYPE (decl);
1060 if (TREE_CODE (decl) == TYPE_DECL
1061 || TREE_CODE (decl) == PARM_DECL
1062 || TREE_CODE (decl) == VAR_DECL
1063 || TREE_CODE (decl) == FUNCTION_DECL
1064 || TREE_CODE (decl) == FIELD_DECL)
1065 TREE_DEPRECATED (decl) = 1;
1066 else
1067 warn = 1;
1069 else if (TYPE_P (*node))
1071 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
1072 *node = build_variant_type_copy (*node);
1073 TREE_DEPRECATED (*node) = 1;
1074 type = *node;
1076 else
1077 warn = 1;
1079 if (warn)
1081 *no_add_attrs = true;
1082 if (type && TYPE_NAME (type))
1084 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
1085 what = IDENTIFIER_POINTER (TYPE_NAME (*node));
1086 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
1087 && DECL_NAME (TYPE_NAME (type)))
1088 what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
1090 if (what)
1091 warning ("%qs attribute ignored for %qs",
1092 IDENTIFIER_POINTER (name), what);
1093 else
1094 warning ("%qs attribute ignored",
1095 IDENTIFIER_POINTER (name));
1098 return NULL_TREE;
1101 /* Handle a "vector_size" attribute; arguments as in
1102 struct attribute_spec.handler. */
1104 static tree
1105 handle_vector_size_attribute (tree *node, tree name, tree args,
1106 int ARG_UNUSED (flags),
1107 bool *no_add_attrs)
1109 unsigned HOST_WIDE_INT vecsize, nunits;
1110 enum machine_mode orig_mode;
1111 tree type = *node, new_type, size;
1113 *no_add_attrs = true;
1115 /* Stripping NON_LVALUE_EXPR allows declarations such as
1116 typedef short v4si __attribute__((vector_size (4 * sizeof(short)))). */
1117 size = TREE_VALUE (args);
1118 if (TREE_CODE (size) == NON_LVALUE_EXPR)
1119 size = TREE_OPERAND (size, 0);
1121 if (!host_integerp (size, 1))
1123 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
1124 return NULL_TREE;
1127 /* Get the vector size (in bytes). */
1128 vecsize = tree_low_cst (size, 1);
1130 /* We need to provide for vector pointers, vector arrays, and
1131 functions returning vectors. For example:
1133 __attribute__((vector_size(16))) short *foo;
1135 In this case, the mode is SI, but the type being modified is
1136 HI, so we need to look further. */
1138 while (POINTER_TYPE_P (type)
1139 || TREE_CODE (type) == FUNCTION_TYPE
1140 || TREE_CODE (type) == METHOD_TYPE
1141 || TREE_CODE (type) == ARRAY_TYPE)
1142 type = TREE_TYPE (type);
1144 /* Get the mode of the type being modified. */
1145 orig_mode = TYPE_MODE (type);
1147 if (TREE_CODE (type) == RECORD_TYPE
1148 || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
1149 && GET_MODE_CLASS (orig_mode) != MODE_INT)
1150 || !host_integerp (TYPE_SIZE_UNIT (type), 1))
1152 error ("invalid vector type for attribute %qs",
1153 IDENTIFIER_POINTER (name));
1154 return NULL_TREE;
1157 /* Calculate how many units fit in the vector. */
1158 nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
1159 if (nunits & (nunits - 1))
1161 error ("number of components of the vector not a power of two");
1162 return NULL_TREE;
1165 new_type = build_vector_type (type, nunits);
1167 /* Build back pointers if needed. */
1168 *node = reconstruct_complex_type (*node, new_type);
1170 return NULL_TREE;
1173 /* Handle the "nonnull" attribute. */
1174 static tree
1175 handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
1176 tree args, int ARG_UNUSED (flags),
1177 bool *no_add_attrs)
1179 tree type = *node;
1180 unsigned HOST_WIDE_INT attr_arg_num;
1182 /* If no arguments are specified, all pointer arguments should be
1183 non-null. Verify a full prototype is given so that the arguments
1184 will have the correct types when we actually check them later. */
1185 if (!args)
1187 if (!TYPE_ARG_TYPES (type))
1189 error ("nonnull attribute without arguments on a non-prototype");
1190 *no_add_attrs = true;
1192 return NULL_TREE;
1195 /* Argument list specified. Verify that each argument number references
1196 a pointer argument. */
1197 for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
1199 tree argument;
1200 unsigned HOST_WIDE_INT arg_num = 0, ck_num;
1202 if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
1204 error ("nonnull argument has invalid operand number (argument %lu)",
1205 (unsigned long) attr_arg_num);
1206 *no_add_attrs = true;
1207 return NULL_TREE;
1210 argument = TYPE_ARG_TYPES (type);
1211 if (argument)
1213 for (ck_num = 1; ; ck_num++)
1215 if (!argument || ck_num == arg_num)
1216 break;
1217 argument = TREE_CHAIN (argument);
1220 if (!argument
1221 || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE)
1223 error ("nonnull argument with out-of-range operand number (argument %lu, operand %lu)",
1224 (unsigned long) attr_arg_num, (unsigned long) arg_num);
1225 *no_add_attrs = true;
1226 return NULL_TREE;
1229 if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
1231 error ("nonnull argument references non-pointer operand (argument %lu, operand %lu)",
1232 (unsigned long) attr_arg_num, (unsigned long) arg_num);
1233 *no_add_attrs = true;
1234 return NULL_TREE;
1239 return NULL_TREE;
1243 /* Check that the Nth argument of a function call (counting backwards
1244 from the end) is a (pointer)0. */
1246 static void
1247 check_function_sentinel (tree attrs, tree params)
1249 tree attr = lookup_attribute ("sentinel", attrs);
1251 if (attr)
1253 if (!params)
1254 warning ("missing sentinel in function call");
1255 else
1257 tree sentinel, end;
1258 unsigned pos = 0;
1260 if (TREE_VALUE (attr))
1262 tree p = TREE_VALUE (TREE_VALUE (attr));
1263 STRIP_NOPS (p);
1264 pos = TREE_INT_CST_LOW (p);
1267 sentinel = end = params;
1269 /* Advance `end' ahead of `sentinel' by `pos' positions. */
1270 while (pos > 0 && TREE_CHAIN (end))
1272 pos--;
1273 end = TREE_CHAIN (end);
1275 if (pos > 0)
1277 warning ("not enough arguments to fit a sentinel");
1278 return;
1281 /* Now advance both until we find the last parameter. */
1282 while (TREE_CHAIN (end))
1284 end = TREE_CHAIN (end);
1285 sentinel = TREE_CHAIN (sentinel);
1288 /* Validate the sentinel. */
1289 if (!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
1290 || !integer_zerop (TREE_VALUE (sentinel)))
1291 warning ("missing sentinel in function call");
1296 /* Helper for check_function_nonnull; given a list of operands which
1297 must be non-null in ARGS, determine if operand PARAM_NUM should be
1298 checked. */
1300 static bool
1301 nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
1303 unsigned HOST_WIDE_INT arg_num = 0;
1305 for (; args; args = TREE_CHAIN (args))
1307 bool found = get_nonnull_operand (TREE_VALUE (args), &arg_num);
1309 gcc_assert (found);
1311 if (arg_num == param_num)
1312 return true;
1314 return false;
1317 /* Check that the function argument PARAM (which is operand number
1318 PARAM_NUM) is non-null. This is called by check_function_nonnull
1319 via check_function_arguments_recurse. */
1321 static void
1322 check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
1323 unsigned HOST_WIDE_INT param_num)
1325 /* Just skip checking the argument if it's not a pointer. This can
1326 happen if the "nonnull" attribute was given without an operand
1327 list (which means to check every pointer argument). */
1329 if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE)
1330 return;
1332 if (integer_zerop (param))
1333 warning ("null argument where non-null required (argument %lu)",
1334 (unsigned long) param_num);
1337 /* Helper for nonnull attribute handling; fetch the operand number
1338 from the attribute argument list. */
1340 static bool
1341 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
1343 /* Strip any conversions from the arg number and verify they
1344 are constants. */
1345 while (TREE_CODE (arg_num_expr) == NOP_EXPR
1346 || TREE_CODE (arg_num_expr) == CONVERT_EXPR
1347 || TREE_CODE (arg_num_expr) == NON_LVALUE_EXPR)
1348 arg_num_expr = TREE_OPERAND (arg_num_expr, 0);
1350 if (TREE_CODE (arg_num_expr) != INTEGER_CST
1351 || TREE_INT_CST_HIGH (arg_num_expr) != 0)
1352 return false;
1354 *valp = TREE_INT_CST_LOW (arg_num_expr);
1355 return true;
1358 /* Handle a "nothrow" attribute; arguments as in
1359 struct attribute_spec.handler. */
1361 static tree
1362 handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
1363 int ARG_UNUSED (flags), bool *no_add_attrs)
1365 if (TREE_CODE (*node) == FUNCTION_DECL)
1366 TREE_NOTHROW (*node) = 1;
1367 /* ??? TODO: Support types. */
1368 else
1370 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
1371 *no_add_attrs = true;
1374 return NULL_TREE;
1377 /* Handle a "warn_unused_result" attribute. No special handling. */
1379 static tree
1380 handle_warn_unused_result_attribute (tree *node, tree name,
1381 tree ARG_UNUSED (args),
1382 int ARG_UNUSED (flags), bool *no_add_attrs)
1384 /* Ignore the attribute for functions not returning any value. */
1385 if (VOID_TYPE_P (TREE_TYPE (*node)))
1387 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
1388 *no_add_attrs = true;
1391 return NULL_TREE;
1394 /* Handle a "sentinel" attribute. */
1396 static tree
1397 handle_sentinel_attribute (tree *node, tree name, tree args,
1398 int ARG_UNUSED (flags), bool *no_add_attrs)
1400 tree params = TYPE_ARG_TYPES (*node);
1402 if (!params)
1404 warning ("%qs attribute requires prototypes with named arguments",
1405 IDENTIFIER_POINTER (name));
1406 *no_add_attrs = true;
1408 else
1410 while (TREE_CHAIN (params))
1411 params = TREE_CHAIN (params);
1413 if (VOID_TYPE_P (TREE_VALUE (params)))
1415 warning ("%qs attribute only applies to variadic functions",
1416 IDENTIFIER_POINTER (name));
1417 *no_add_attrs = true;
1421 if (args)
1423 tree position = TREE_VALUE (args);
1425 STRIP_NOPS (position);
1426 if (TREE_CODE (position) != INTEGER_CST)
1428 warning ("requested position is not an integer constant");
1429 *no_add_attrs = true;
1431 else
1433 if (tree_int_cst_lt (position, integer_zero_node))
1435 warning ("requested position is less than zero");
1436 *no_add_attrs = true;
1441 return NULL_TREE;
1445 /* Generic argument checking recursion routine. PARAM is the argument to
1446 be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked
1447 once the argument is resolved. CTX is context for the callback. */
1448 void
1449 check_function_arguments_recurse (void (*callback)
1450 (void *, tree, unsigned HOST_WIDE_INT),
1451 void *ctx, tree param,
1452 unsigned HOST_WIDE_INT param_num)
1454 if (TREE_CODE (param) == NOP_EXPR)
1456 /* Strip coercion. */
1457 check_function_arguments_recurse (callback, ctx,
1458 TREE_OPERAND (param, 0), param_num);
1459 return;
1462 if (TREE_CODE (param) == CALL_EXPR)
1464 tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0)));
1465 tree attrs;
1466 bool found_format_arg = false;
1468 /* See if this is a call to a known internationalization function
1469 that modifies a format arg. Such a function may have multiple
1470 format_arg attributes (for example, ngettext). */
1472 for (attrs = TYPE_ATTRIBUTES (type);
1473 attrs;
1474 attrs = TREE_CHAIN (attrs))
1475 if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
1477 tree inner_args;
1478 tree format_num_expr;
1479 int format_num;
1480 int i;
1482 /* Extract the argument number, which was previously checked
1483 to be valid. */
1484 format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
1485 while (TREE_CODE (format_num_expr) == NOP_EXPR
1486 || TREE_CODE (format_num_expr) == CONVERT_EXPR
1487 || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
1488 format_num_expr = TREE_OPERAND (format_num_expr, 0);
1490 gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST
1491 && !TREE_INT_CST_HIGH (format_num_expr));
1493 format_num = TREE_INT_CST_LOW (format_num_expr);
1495 for (inner_args = TREE_OPERAND (param, 1), i = 1;
1496 inner_args != 0;
1497 inner_args = TREE_CHAIN (inner_args), i++)
1498 if (i == format_num)
1500 check_function_arguments_recurse (callback, ctx,
1501 TREE_VALUE (inner_args),
1502 param_num);
1503 found_format_arg = true;
1504 break;
1508 /* If we found a format_arg attribute and did a recursive check,
1509 we are done with checking this argument. Otherwise, we continue
1510 and this will be considered a non-literal. */
1511 if (found_format_arg)
1512 return;
1515 if (TREE_CODE (param) == COND_EXPR)
1517 /* Check both halves of the conditional expression. */
1518 check_function_arguments_recurse (callback, ctx,
1519 TREE_OPERAND (param, 1), param_num);
1520 check_function_arguments_recurse (callback, ctx,
1521 TREE_OPERAND (param, 2), param_num);
1522 return;
1525 (*callback) (ctx, param, param_num);