Don't allow "a~b" if either could be null
[delight/core.git] / d-bi-attrs-34.h
blob626a72e69eb275575d52c23845ef5211bfda2f57
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 /*not in gdc//static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);*/
37 static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
38 bool *);
40 /*not in gdc//static void check_function_nonnull (tree, tree);*/
41 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
42 static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
43 static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
45 /* extra for gdc copy: */
46 static void check_function_arguments_recurse (void (*)
47 (void *, tree,
48 unsigned HOST_WIDE_INT),
49 void *, tree,
50 unsigned HOST_WIDE_INT);
51 static tree
52 handle_format_arg_attribute (tree *node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED,
53 tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs ATTRIBUTE_UNUSED)
55 return NULL_TREE;
57 static tree
58 handle_format_attribute (tree *node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED, tree args ATTRIBUTE_UNUSED,
59 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs ATTRIBUTE_UNUSED)
61 return NULL_TREE;
64 /* -- end extra */
66 /* Table of machine-independent attributes common to all C-like languages. */
67 const struct attribute_spec d_common_attribute_table[] =
69 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
70 { "packed", 0, 0, false, false, false,
71 handle_packed_attribute },
72 { "nocommon", 0, 0, true, false, false,
73 handle_nocommon_attribute },
74 { "common", 0, 0, true, false, false,
75 handle_common_attribute },
76 /* FIXME: logically, noreturn attributes should be listed as
77 "false, true, true" and apply to function types. But implementing this
78 would require all the places in the compiler that use TREE_THIS_VOLATILE
79 on a decl to identify non-returning functions to be located and fixed
80 to check the function type instead. */
81 { "noreturn", 0, 0, true, false, false,
82 handle_noreturn_attribute },
83 { "volatile", 0, 0, true, false, false,
84 handle_noreturn_attribute },
85 { "noinline", 0, 0, true, false, false,
86 handle_noinline_attribute },
87 { "always_inline", 0, 0, true, false, false,
88 handle_always_inline_attribute },
89 { "used", 0, 0, true, false, false,
90 handle_used_attribute },
91 { "unused", 0, 0, false, false, false,
92 handle_unused_attribute },
93 /* The same comments as for noreturn attributes apply to const ones. */
94 { "const", 0, 0, true, false, false,
95 handle_const_attribute },
96 { "transparent_union", 0, 0, false, false, false,
97 handle_transparent_union_attribute },
98 { "constructor", 0, 0, true, false, false,
99 handle_constructor_attribute },
100 { "destructor", 0, 0, true, false, false,
101 handle_destructor_attribute },
102 { "mode", 1, 1, false, true, false,
103 handle_mode_attribute },
104 { "section", 1, 1, true, false, false,
105 handle_section_attribute },
106 { "aligned", 0, 1, false, false, false,
107 handle_aligned_attribute },
108 { "weak", 0, 0, true, false, false,
109 handle_weak_attribute },
110 { "alias", 1, 1, true, false, false,
111 handle_alias_attribute },
112 { "no_instrument_function", 0, 0, true, false, false,
113 handle_no_instrument_function_attribute },
114 { "malloc", 0, 0, true, false, false,
115 handle_malloc_attribute },
116 { "no_stack_limit", 0, 0, true, false, false,
117 handle_no_limit_stack_attribute },
118 { "pure", 0, 0, true, false, false,
119 handle_pure_attribute },
120 { "deprecated", 0, 0, false, false, false,
121 handle_deprecated_attribute },
122 { "vector_size", 1, 1, false, true, false,
123 handle_vector_size_attribute },
124 { "visibility", 1, 1, true, false, false,
125 handle_visibility_attribute },
126 { "tls_model", 1, 1, true, false, false,
127 handle_tls_model_attribute },
128 { "nonnull", 0, -1, false, true, true,
129 handle_nonnull_attribute },
130 { "nothrow", 0, 0, true, false, false,
131 handle_nothrow_attribute },
132 { "may_alias", 0, 0, false, true, false, NULL },
133 /* not in gdc// { "cleanup", 1, 1, true, false, false,
134 handle_cleanup_attribute },*/
135 { "warn_unused_result", 0, 0, false, true, true,
136 handle_warn_unused_result_attribute },
137 { NULL, 0, 0, false, false, false, NULL }
140 /* Give the specifications for the format attributes, used by C and all
141 descendants. */
143 const struct attribute_spec d_common_format_attribute_table[] =
145 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
146 { "format", 3, 3, false, true, true,
147 handle_format_attribute },
148 { "format_arg", 1, 1, false, true, true,
149 handle_format_arg_attribute },
150 { NULL, 0, 0, false, false, false, NULL }
153 /* Attribute handlers common to C front ends. */
155 /* Handle a "packed" attribute; arguments as in
156 struct attribute_spec.handler. */
158 static tree
159 handle_packed_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
160 int flags, bool *no_add_attrs)
162 if (TYPE_P (*node))
164 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
165 *node = build_type_copy (*node);
166 TYPE_PACKED (*node) = 1;
167 if (TYPE_MAIN_VARIANT (*node) == *node)
169 /* If it is the main variant, then pack the other variants
170 too. This happens in,
172 struct Foo {
173 struct Foo const *ptr; // creates a variant w/o packed flag
174 } __ attribute__((packed)); // packs it now.
176 tree probe;
178 for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe))
179 TYPE_PACKED (probe) = 1;
183 else if (TREE_CODE (*node) == FIELD_DECL)
184 DECL_PACKED (*node) = 1;
185 /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
186 used for DECL_REGISTER. It wouldn't mean anything anyway.
187 We can't set DECL_PACKED on the type of a TYPE_DECL, because
188 that changes what the typedef is typing. */
189 else
191 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
192 *no_add_attrs = true;
195 return NULL_TREE;
198 /* Handle a "nocommon" attribute; arguments as in
199 struct attribute_spec.handler. */
201 static tree
202 handle_nocommon_attribute (tree *node, tree name,
203 tree args ATTRIBUTE_UNUSED,
204 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
206 if (TREE_CODE (*node) == VAR_DECL)
207 DECL_COMMON (*node) = 0;
208 else
210 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
211 *no_add_attrs = true;
214 return NULL_TREE;
217 /* Handle a "common" attribute; arguments as in
218 struct attribute_spec.handler. */
220 static tree
221 handle_common_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
222 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
224 if (TREE_CODE (*node) == VAR_DECL)
225 DECL_COMMON (*node) = 1;
226 else
228 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
229 *no_add_attrs = true;
232 return NULL_TREE;
235 /* Handle a "noreturn" attribute; arguments as in
236 struct attribute_spec.handler. */
238 static tree
239 handle_noreturn_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
240 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
242 tree type = TREE_TYPE (*node);
244 /* See FIXME comment in c_common_attribute_table. */
245 if (TREE_CODE (*node) == FUNCTION_DECL)
246 TREE_THIS_VOLATILE (*node) = 1;
247 else if (TREE_CODE (type) == POINTER_TYPE
248 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
249 TREE_TYPE (*node)
250 = build_pointer_type
251 (build_type_variant (TREE_TYPE (type),
252 TREE_READONLY (TREE_TYPE (type)), 1));
253 else
255 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
256 *no_add_attrs = true;
259 return NULL_TREE;
262 /* Handle a "noinline" attribute; arguments as in
263 struct attribute_spec.handler. */
265 static tree
266 handle_noinline_attribute (tree *node, tree name,
267 tree args ATTRIBUTE_UNUSED,
268 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
270 if (TREE_CODE (*node) == FUNCTION_DECL)
271 DECL_UNINLINABLE (*node) = 1;
272 else
274 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
275 *no_add_attrs = true;
278 return NULL_TREE;
281 /* Handle a "always_inline" attribute; arguments as in
282 struct attribute_spec.handler. */
284 static tree
285 handle_always_inline_attribute (tree *node, tree name,
286 tree args ATTRIBUTE_UNUSED,
287 int flags ATTRIBUTE_UNUSED,
288 bool *no_add_attrs)
290 if (TREE_CODE (*node) == FUNCTION_DECL)
292 /* Do nothing else, just set the attribute. We'll get at
293 it later with lookup_attribute. */
295 else
297 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
298 *no_add_attrs = true;
301 return NULL_TREE;
304 /* Handle a "used" attribute; arguments as in
305 struct attribute_spec.handler. */
307 static tree
308 handle_used_attribute (tree *pnode, tree name, tree args ATTRIBUTE_UNUSED,
309 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
311 tree node = *pnode;
313 if (TREE_CODE (node) == FUNCTION_DECL
314 || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node)))
316 TREE_USED (node) = 1;
318 else
320 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
321 *no_add_attrs = true;
324 return NULL_TREE;
327 /* Handle a "unused" attribute; arguments as in
328 struct attribute_spec.handler. */
330 static tree
331 handle_unused_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
332 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
334 if (DECL_P (*node))
336 tree decl = *node;
338 if (TREE_CODE (decl) == PARM_DECL
339 || TREE_CODE (decl) == VAR_DECL
340 || TREE_CODE (decl) == FUNCTION_DECL
341 || TREE_CODE (decl) == LABEL_DECL
342 || TREE_CODE (decl) == TYPE_DECL)
343 TREE_USED (decl) = 1;
344 else
346 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
347 *no_add_attrs = true;
350 else
352 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
353 *node = build_type_copy (*node);
354 TREE_USED (*node) = 1;
357 return NULL_TREE;
360 /* Handle a "const" attribute; arguments as in
361 struct attribute_spec.handler. */
363 static tree
364 handle_const_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
365 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
367 tree type = TREE_TYPE (*node);
369 /* See FIXME comment on noreturn in c_common_attribute_table. */
370 if (TREE_CODE (*node) == FUNCTION_DECL)
371 TREE_READONLY (*node) = 1;
372 else if (TREE_CODE (type) == POINTER_TYPE
373 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
374 TREE_TYPE (*node)
375 = build_pointer_type
376 (build_type_variant (TREE_TYPE (type), 1,
377 TREE_THIS_VOLATILE (TREE_TYPE (type))));
378 else
380 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
381 *no_add_attrs = true;
384 return NULL_TREE;
387 /* Handle a "transparent_union" attribute; arguments as in
388 struct attribute_spec.handler. */
390 static tree
391 handle_transparent_union_attribute (tree *node, tree name,
392 tree args ATTRIBUTE_UNUSED, int flags,
393 bool *no_add_attrs)
395 tree decl = NULL_TREE;
396 tree *type = NULL;
397 int is_type = 0;
399 if (DECL_P (*node))
401 decl = *node;
402 type = &TREE_TYPE (decl);
403 is_type = TREE_CODE (*node) == TYPE_DECL;
405 else if (TYPE_P (*node))
406 type = node, is_type = 1;
408 if (is_type
409 && TREE_CODE (*type) == UNION_TYPE
410 && (decl == 0
411 || (TYPE_FIELDS (*type) != 0
412 && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
414 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
415 *type = build_type_copy (*type);
416 TYPE_TRANSPARENT_UNION (*type) = 1;
418 else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
419 && TREE_CODE (*type) == UNION_TYPE
420 && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
421 DECL_TRANSPARENT_UNION (decl) = 1;
422 else
424 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
425 *no_add_attrs = true;
428 return NULL_TREE;
431 /* Handle a "constructor" attribute; arguments as in
432 struct attribute_spec.handler. */
434 static tree
435 handle_constructor_attribute (tree *node, tree name,
436 tree args ATTRIBUTE_UNUSED,
437 int flags ATTRIBUTE_UNUSED,
438 bool *no_add_attrs)
440 tree decl = *node;
441 tree type = TREE_TYPE (decl);
443 if (TREE_CODE (decl) == FUNCTION_DECL
444 && TREE_CODE (type) == FUNCTION_TYPE
445 && decl_function_context (decl) == 0)
447 DECL_STATIC_CONSTRUCTOR (decl) = 1;
448 TREE_USED (decl) = 1;
450 else
452 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
453 *no_add_attrs = true;
456 return NULL_TREE;
459 /* Handle a "destructor" attribute; arguments as in
460 struct attribute_spec.handler. */
462 static tree
463 handle_destructor_attribute (tree *node, tree name,
464 tree args ATTRIBUTE_UNUSED,
465 int flags ATTRIBUTE_UNUSED,
466 bool *no_add_attrs)
468 tree decl = *node;
469 tree type = TREE_TYPE (decl);
471 if (TREE_CODE (decl) == FUNCTION_DECL
472 && TREE_CODE (type) == FUNCTION_TYPE
473 && decl_function_context (decl) == 0)
475 DECL_STATIC_DESTRUCTOR (decl) = 1;
476 TREE_USED (decl) = 1;
478 else
480 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
481 *no_add_attrs = true;
484 return NULL_TREE;
487 /* Handle a "mode" attribute; arguments as in
488 struct attribute_spec.handler. */
490 static tree
491 handle_mode_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
492 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
494 tree type = *node;
496 *no_add_attrs = true;
498 if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
499 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
500 else
502 int j;
503 const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
504 int len = strlen (p);
505 enum machine_mode mode = VOIDmode;
506 tree typefm;
507 tree ptr_type;
509 if (len > 4 && p[0] == '_' && p[1] == '_'
510 && p[len - 1] == '_' && p[len - 2] == '_')
512 char *newp = alloca (len - 1);
514 strcpy (newp, &p[2]);
515 newp[len - 4] = '\0';
516 p = newp;
519 /* Change this type to have a type with the specified mode.
520 First check for the special modes. */
521 if (! strcmp (p, "byte"))
522 mode = byte_mode;
523 else if (!strcmp (p, "word"))
524 mode = word_mode;
525 else if (! strcmp (p, "pointer"))
526 mode = ptr_mode;
527 else
528 for (j = 0; j < NUM_MACHINE_MODES; j++)
529 if (!strcmp (p, GET_MODE_NAME (j)))
531 mode = (enum machine_mode) j;
532 break;
535 if (mode == VOIDmode)
536 error ("unknown machine mode `%s'", p);
537 else if (0 == (typefm = (*lang_hooks.types.type_for_mode)
538 (mode, TREE_UNSIGNED (type))))
539 error ("no data type for mode `%s'", p);
540 else if ((TREE_CODE (type) == POINTER_TYPE
541 || TREE_CODE (type) == REFERENCE_TYPE)
542 && !(*targetm.valid_pointer_mode) (mode))
543 error ("invalid pointer mode `%s'", p);
544 else
546 /* If this is a vector, make sure we either have hardware
547 support, or we can emulate it. */
548 if (VECTOR_MODE_P (mode) && !vector_mode_valid_p (mode))
550 error ("unable to emulate '%s'", GET_MODE_NAME (mode));
551 return NULL_TREE;
554 if (TREE_CODE (type) == POINTER_TYPE)
556 ptr_type = build_pointer_type_for_mode (TREE_TYPE (type),
557 mode);
558 *node = ptr_type;
560 else if (TREE_CODE (type) == REFERENCE_TYPE)
562 ptr_type = build_reference_type_for_mode (TREE_TYPE (type),
563 mode);
564 *node = ptr_type;
566 else if (VECTOR_MODE_P (mode)
567 ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
568 : TREE_CODE (type) != TREE_CODE (typefm))
571 error ("mode `%s' applied to inappropriate type", p);
572 return NULL_TREE;
574 else
575 *node = typefm;
577 /* No need to layout the type here. The caller should do this. */
581 return NULL_TREE;
584 /* Handle a "section" attribute; arguments as in
585 struct attribute_spec.handler. */
587 static tree
588 handle_section_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
589 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
591 tree decl = *node;
593 if (targetm.have_named_sections)
595 if ((TREE_CODE (decl) == FUNCTION_DECL
596 || TREE_CODE (decl) == VAR_DECL)
597 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
599 if (TREE_CODE (decl) == VAR_DECL
600 && current_function_decl != NULL_TREE
601 && ! (TREE_STATIC (decl) || DECL_EXTERNAL (decl)))
603 error ("%Jsection attribute cannot be specified for "
604 "local variables", decl);
605 *no_add_attrs = true;
608 /* The decl may have already been given a section attribute
609 from a previous declaration. Ensure they match. */
610 else if (DECL_SECTION_NAME (decl) != NULL_TREE
611 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
612 TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
614 error ("%Jsection of '%D' conflicts with previous declaration",
615 *node, *node);
616 *no_add_attrs = true;
618 else
619 DECL_SECTION_NAME (decl) = TREE_VALUE (args);
621 else
623 error ("%Jsection attribute not allowed for '%D'", *node, *node);
624 *no_add_attrs = true;
627 else
629 error ("%Jsection attributes are not supported for this target", *node);
630 *no_add_attrs = true;
633 return NULL_TREE;
636 /* Handle a "aligned" attribute; arguments as in
637 struct attribute_spec.handler. */
639 static tree
640 handle_aligned_attribute (tree *node, tree name ATTRIBUTE_UNUSED, tree args,
641 int flags, bool *no_add_attrs)
643 tree decl = NULL_TREE;
644 tree *type = NULL;
645 int is_type = 0;
646 tree align_expr = (args ? TREE_VALUE (args)
647 : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
648 int i;
650 if (DECL_P (*node))
652 decl = *node;
653 type = &TREE_TYPE (decl);
654 is_type = TREE_CODE (*node) == TYPE_DECL;
656 else if (TYPE_P (*node))
657 type = node, is_type = 1;
659 /* Strip any NOPs of any kind. */
660 while (TREE_CODE (align_expr) == NOP_EXPR
661 || TREE_CODE (align_expr) == CONVERT_EXPR
662 || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
663 align_expr = TREE_OPERAND (align_expr, 0);
665 if (TREE_CODE (align_expr) != INTEGER_CST)
667 error ("requested alignment is not a constant");
668 *no_add_attrs = true;
670 else if ((i = tree_log2 (align_expr)) == -1)
672 error ("requested alignment is not a power of 2");
673 *no_add_attrs = true;
675 else if (i > HOST_BITS_PER_INT - 2)
677 error ("requested alignment is too large");
678 *no_add_attrs = true;
680 else if (is_type)
682 /* If we have a TYPE_DECL, then copy the type, so that we
683 don't accidentally modify a builtin type. See pushdecl. */
684 if (decl && TREE_TYPE (decl) != error_mark_node
685 && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
687 tree tt = TREE_TYPE (decl);
688 *type = build_type_copy (*type);
689 DECL_ORIGINAL_TYPE (decl) = tt;
690 TYPE_NAME (*type) = decl;
691 TREE_USED (*type) = TREE_USED (decl);
692 TREE_TYPE (decl) = *type;
694 else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
695 *type = build_type_copy (*type);
697 TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
698 TYPE_USER_ALIGN (*type) = 1;
700 else if (TREE_CODE (decl) != VAR_DECL
701 && TREE_CODE (decl) != FIELD_DECL)
703 error ("%Jalignment may not be specified for '%D'", decl, decl);
704 *no_add_attrs = true;
706 else
708 DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
709 DECL_USER_ALIGN (decl) = 1;
712 return NULL_TREE;
715 /* Handle a "weak" attribute; arguments as in
716 struct attribute_spec.handler. */
718 static tree
719 handle_weak_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
720 tree args ATTRIBUTE_UNUSED,
721 int flags ATTRIBUTE_UNUSED,
722 bool *no_add_attrs ATTRIBUTE_UNUSED)
724 declare_weak (*node);
726 return NULL_TREE;
729 /* Handle an "alias" attribute; arguments as in
730 struct attribute_spec.handler. */
732 static tree
733 handle_alias_attribute (tree *node, tree name, tree args,
734 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
736 tree decl = *node;
738 if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
739 || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
741 error ("%J'%D' defined both normally and as an alias", decl, decl);
742 *no_add_attrs = true;
744 else if (decl_function_context (decl) == 0)
746 tree id;
748 id = TREE_VALUE (args);
749 if (TREE_CODE (id) != STRING_CST)
751 error ("alias arg not a string");
752 *no_add_attrs = true;
753 return NULL_TREE;
755 id = get_identifier (TREE_STRING_POINTER (id));
756 /* This counts as a use of the object pointed to. */
757 TREE_USED (id) = 1;
759 if (TREE_CODE (decl) == FUNCTION_DECL)
760 DECL_INITIAL (decl) = error_mark_node;
761 else
762 DECL_EXTERNAL (decl) = 0;
764 else
766 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
767 *no_add_attrs = true;
770 return NULL_TREE;
773 /* Handle an "visibility" attribute; arguments as in
774 struct attribute_spec.handler. */
776 static tree
777 handle_visibility_attribute (tree *node, tree name, tree args,
778 int flags ATTRIBUTE_UNUSED,
779 bool *no_add_attrs)
781 tree decl = *node;
782 tree id = TREE_VALUE (args);
784 *no_add_attrs = true;
786 if (decl_function_context (decl) != 0 || ! TREE_PUBLIC (decl))
788 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
789 return NULL_TREE;
792 if (TREE_CODE (id) != STRING_CST)
794 error ("visibility arg not a string");
795 return NULL_TREE;
798 if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
799 DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
800 else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
801 DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL;
802 else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
803 DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
804 else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
805 DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
806 else
807 error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
809 return NULL_TREE;
812 /* Handle an "tls_model" attribute; arguments as in
813 struct attribute_spec.handler. */
815 static tree
816 handle_tls_model_attribute (tree *node, tree name, tree args,
817 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
819 tree decl = *node;
821 if (! DECL_THREAD_LOCAL (decl))
823 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
824 *no_add_attrs = true;
826 else
828 tree id;
830 id = TREE_VALUE (args);
831 if (TREE_CODE (id) != STRING_CST)
833 error ("tls_model arg not a string");
834 *no_add_attrs = true;
835 return NULL_TREE;
837 if (strcmp (TREE_STRING_POINTER (id), "local-exec")
838 && strcmp (TREE_STRING_POINTER (id), "initial-exec")
839 && strcmp (TREE_STRING_POINTER (id), "local-dynamic")
840 && strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
842 error ("tls_model arg must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
843 *no_add_attrs = true;
844 return NULL_TREE;
848 return NULL_TREE;
851 /* Handle a "no_instrument_function" attribute; arguments as in
852 struct attribute_spec.handler. */
854 static tree
855 handle_no_instrument_function_attribute (tree *node, tree name,
856 tree args ATTRIBUTE_UNUSED,
857 int flags ATTRIBUTE_UNUSED,
858 bool *no_add_attrs)
860 tree decl = *node;
862 if (TREE_CODE (decl) != FUNCTION_DECL)
864 error ("%J'%E' attribute applies only to functions", decl, name);
865 *no_add_attrs = true;
867 else if (DECL_INITIAL (decl))
869 error ("%Jcan't set '%E' attribute after definition", decl, name);
870 *no_add_attrs = true;
872 else
873 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
875 return NULL_TREE;
878 /* Handle a "malloc" attribute; arguments as in
879 struct attribute_spec.handler. */
881 static tree
882 handle_malloc_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
883 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
885 if (TREE_CODE (*node) == FUNCTION_DECL)
886 DECL_IS_MALLOC (*node) = 1;
887 /* ??? TODO: Support types. */
888 else
890 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
891 *no_add_attrs = true;
894 return NULL_TREE;
897 /* Handle a "no_limit_stack" attribute; arguments as in
898 struct attribute_spec.handler. */
900 static tree
901 handle_no_limit_stack_attribute (tree *node, tree name,
902 tree args ATTRIBUTE_UNUSED,
903 int flags ATTRIBUTE_UNUSED,
904 bool *no_add_attrs)
906 tree decl = *node;
908 if (TREE_CODE (decl) != FUNCTION_DECL)
910 error ("%J'%E' attribute applies only to functions", decl, name);
911 *no_add_attrs = true;
913 else if (DECL_INITIAL (decl))
915 error ("%Jcan't set '%E' attribute after definition", decl, name);
916 *no_add_attrs = true;
918 else
919 DECL_NO_LIMIT_STACK (decl) = 1;
921 return NULL_TREE;
924 /* Handle a "pure" attribute; arguments as in
925 struct attribute_spec.handler. */
927 static tree
928 handle_pure_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
929 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
931 if (TREE_CODE (*node) == FUNCTION_DECL)
932 DECL_IS_PURE (*node) = 1;
933 /* ??? TODO: Support types. */
934 else
936 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
937 *no_add_attrs = true;
940 return NULL_TREE;
943 /* Handle a "deprecated" attribute; arguments as in
944 struct attribute_spec.handler. */
946 static tree
947 handle_deprecated_attribute (tree *node, tree name,
948 tree args ATTRIBUTE_UNUSED, int flags,
949 bool *no_add_attrs)
951 tree type = NULL_TREE;
952 int warn = 0;
953 const char *what = NULL;
955 if (DECL_P (*node))
957 tree decl = *node;
958 type = TREE_TYPE (decl);
960 if (TREE_CODE (decl) == TYPE_DECL
961 || TREE_CODE (decl) == PARM_DECL
962 || TREE_CODE (decl) == VAR_DECL
963 || TREE_CODE (decl) == FUNCTION_DECL
964 || TREE_CODE (decl) == FIELD_DECL)
965 TREE_DEPRECATED (decl) = 1;
966 else
967 warn = 1;
969 else if (TYPE_P (*node))
971 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
972 *node = build_type_copy (*node);
973 TREE_DEPRECATED (*node) = 1;
974 type = *node;
976 else
977 warn = 1;
979 if (warn)
981 *no_add_attrs = true;
982 if (type && TYPE_NAME (type))
984 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
985 what = IDENTIFIER_POINTER (TYPE_NAME (*node));
986 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
987 && DECL_NAME (TYPE_NAME (type)))
988 what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
990 if (what)
991 warning ("`%s' attribute ignored for `%s'",
992 IDENTIFIER_POINTER (name), what);
993 else
994 warning ("`%s' attribute ignored",
995 IDENTIFIER_POINTER (name));
998 return NULL_TREE;
1001 /* Keep a list of vector type nodes we created in handle_vector_size_attribute,
1002 to prevent us from duplicating type nodes unnecessarily.
1003 The normal mechanism to prevent duplicates is to use type_hash_canon, but
1004 since we want to distinguish types that are essentially identical (except
1005 for their debug representation), we use a local list here. */
1006 static GTY(()) tree vector_type_node_list = 0;
1008 /* Handle a "vector_size" attribute; arguments as in
1009 struct attribute_spec.handler. */
1011 static tree
1012 handle_vector_size_attribute (tree *node, tree name, tree args,
1013 int flags ATTRIBUTE_UNUSED,
1014 bool *no_add_attrs)
1016 unsigned HOST_WIDE_INT vecsize, nunits;
1017 enum machine_mode mode, orig_mode, new_mode;
1018 tree type = *node, new_type = NULL_TREE;
1019 tree type_list_node;
1021 *no_add_attrs = true;
1023 if (! host_integerp (TREE_VALUE (args), 1))
1025 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1026 return NULL_TREE;
1029 /* Get the vector size (in bytes). */
1030 vecsize = tree_low_cst (TREE_VALUE (args), 1);
1032 /* We need to provide for vector pointers, vector arrays, and
1033 functions returning vectors. For example:
1035 __attribute__((vector_size(16))) short *foo;
1037 In this case, the mode is SI, but the type being modified is
1038 HI, so we need to look further. */
1040 while (POINTER_TYPE_P (type)
1041 || TREE_CODE (type) == FUNCTION_TYPE
1042 || TREE_CODE (type) == METHOD_TYPE
1043 || TREE_CODE (type) == ARRAY_TYPE)
1044 type = TREE_TYPE (type);
1046 /* Get the mode of the type being modified. */
1047 orig_mode = TYPE_MODE (type);
1049 if (TREE_CODE (type) == RECORD_TYPE
1050 || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
1051 && GET_MODE_CLASS (orig_mode) != MODE_INT)
1052 || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
1054 error ("invalid vector type for attribute `%s'",
1055 IDENTIFIER_POINTER (name));
1056 return NULL_TREE;
1059 /* Calculate how many units fit in the vector. */
1060 nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
1062 /* Find a suitably sized vector. */
1063 new_mode = VOIDmode;
1064 for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
1065 ? MODE_VECTOR_INT
1066 : MODE_VECTOR_FLOAT);
1067 mode != VOIDmode;
1068 mode = GET_MODE_WIDER_MODE (mode))
1069 if (vecsize == GET_MODE_SIZE (mode)
1070 && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode))
1072 new_mode = mode;
1073 break;
1076 if (new_mode == VOIDmode)
1078 error ("no vector mode with the size and type specified could be found");
1079 return NULL_TREE;
1082 for (type_list_node = vector_type_node_list; type_list_node;
1083 type_list_node = TREE_CHAIN (type_list_node))
1085 tree other_type = TREE_VALUE (type_list_node);
1086 tree record = TYPE_DEBUG_REPRESENTATION_TYPE (other_type);
1087 tree fields = TYPE_FIELDS (record);
1088 tree field_type = TREE_TYPE (fields);
1089 tree array_type = TREE_TYPE (field_type);
1090 if (TREE_CODE (fields) != FIELD_DECL
1091 || TREE_CODE (field_type) != ARRAY_TYPE)
1092 abort ();
1094 if (TYPE_MODE (other_type) == mode && type == array_type)
1096 new_type = other_type;
1097 break;
1101 if (new_type == NULL_TREE)
1103 tree index, array, rt, list_node;
1105 new_type = (*lang_hooks.types.type_for_mode) (new_mode,
1106 TREE_UNSIGNED (type));
1108 if (!new_type)
1110 error ("no vector mode with the size and type specified could be found");
1111 return NULL_TREE;
1114 new_type = build_type_copy (new_type);
1116 /* If this is a vector, make sure we either have hardware
1117 support, or we can emulate it. */
1118 if ((GET_MODE_CLASS (mode) == MODE_VECTOR_INT
1119 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
1120 && !vector_mode_valid_p (mode))
1122 error ("unable to emulate '%s'", GET_MODE_NAME (mode));
1123 return NULL_TREE;
1126 /* Set the debug information here, because this is the only
1127 place where we know the underlying type for a vector made
1128 with vector_size. For debugging purposes we pretend a vector
1129 is an array within a structure. */
1130 index = build_int_2 (TYPE_VECTOR_SUBPARTS (new_type) - 1, 0);
1131 array = build_array_type (type, build_index_type (index));
1132 rt = make_node (RECORD_TYPE);
1134 TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
1135 DECL_CONTEXT (TYPE_FIELDS (rt)) = rt;
1136 layout_type (rt);
1137 TYPE_DEBUG_REPRESENTATION_TYPE (new_type) = rt;
1139 list_node = build_tree_list (NULL, new_type);
1140 TREE_CHAIN (list_node) = vector_type_node_list;
1141 vector_type_node_list = list_node;
1144 /* Build back pointers if needed. */
1145 *node = reconstruct_complex_type (*node, new_type);
1147 return NULL_TREE;
1150 /* Handle the "nonnull" attribute. */
1151 static tree
1152 handle_nonnull_attribute (tree *node, tree name ATTRIBUTE_UNUSED,
1153 tree args, int flags ATTRIBUTE_UNUSED,
1154 bool *no_add_attrs)
1156 tree type = *node;
1157 unsigned HOST_WIDE_INT attr_arg_num;
1159 /* If no arguments are specified, all pointer arguments should be
1160 non-null. Verify a full prototype is given so that the arguments
1161 will have the correct types when we actually check them later. */
1162 if (! args)
1164 if (! TYPE_ARG_TYPES (type))
1166 error ("nonnull attribute without arguments on a non-prototype");
1167 *no_add_attrs = true;
1169 return NULL_TREE;
1172 /* Argument list specified. Verify that each argument number references
1173 a pointer argument. */
1174 for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
1176 tree argument;
1177 unsigned HOST_WIDE_INT arg_num, ck_num;
1179 if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
1181 error ("nonnull argument has invalid operand number (arg %lu)",
1182 (unsigned long) attr_arg_num);
1183 *no_add_attrs = true;
1184 return NULL_TREE;
1187 argument = TYPE_ARG_TYPES (type);
1188 if (argument)
1190 for (ck_num = 1; ; ck_num++)
1192 if (! argument || ck_num == arg_num)
1193 break;
1194 argument = TREE_CHAIN (argument);
1197 if (! argument
1198 || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE)
1200 error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)",
1201 (unsigned long) attr_arg_num, (unsigned long) arg_num);
1202 *no_add_attrs = true;
1203 return NULL_TREE;
1206 if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
1208 error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)",
1209 (unsigned long) attr_arg_num, (unsigned long) arg_num);
1210 *no_add_attrs = true;
1211 return NULL_TREE;
1216 return NULL_TREE;
1219 #if 0
1220 /* not in gdc */
1221 /* Check the argument list of a function call for null in argument slots
1222 that are marked as requiring a non-null pointer argument. */
1224 static void
1225 check_function_nonnull (tree attrs, tree params)
1227 tree a, args, param;
1228 int param_num;
1230 for (a = attrs; a; a = TREE_CHAIN (a))
1232 if (is_attribute_p ("nonnull", TREE_PURPOSE (a)))
1234 args = TREE_VALUE (a);
1236 /* Walk the argument list. If we encounter an argument number we
1237 should check for non-null, do it. If the attribute has no args,
1238 then every pointer argument is checked (in which case the check
1239 for pointer type is done in check_nonnull_arg). */
1240 for (param = params, param_num = 1; ;
1241 param_num++, param = TREE_CHAIN (param))
1243 if (! param)
1244 break;
1245 if (! args || nonnull_check_p (args, param_num))
1246 check_function_arguments_recurse (check_nonnull_arg, NULL,
1247 TREE_VALUE (param),
1248 param_num);
1253 #endif
1255 /* Helper for check_function_nonnull; given a list of operands which
1256 must be non-null in ARGS, determine if operand PARAM_NUM should be
1257 checked. */
1259 static bool
1260 nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
1262 unsigned HOST_WIDE_INT arg_num;
1264 for (; args; args = TREE_CHAIN (args))
1266 if (! get_nonnull_operand (TREE_VALUE (args), &arg_num))
1267 abort ();
1269 if (arg_num == param_num)
1270 return true;
1272 return false;
1275 /* Check that the function argument PARAM (which is operand number
1276 PARAM_NUM) is non-null. This is called by check_function_nonnull
1277 via check_function_arguments_recurse. */
1279 static void
1280 check_nonnull_arg (void *ctx ATTRIBUTE_UNUSED, tree param,
1281 unsigned HOST_WIDE_INT param_num)
1283 /* Just skip checking the argument if it's not a pointer. This can
1284 happen if the "nonnull" attribute was given without an operand
1285 list (which means to check every pointer argument). */
1287 if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE)
1288 return;
1290 if (integer_zerop (param))
1291 warning ("null argument where non-null required (arg %lu)",
1292 (unsigned long) param_num);
1295 /* Helper for nonnull attribute handling; fetch the operand number
1296 from the attribute argument list. */
1298 static bool
1299 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
1301 /* Strip any conversions from the arg number and verify they
1302 are constants. */
1303 while (TREE_CODE (arg_num_expr) == NOP_EXPR
1304 || TREE_CODE (arg_num_expr) == CONVERT_EXPR
1305 || TREE_CODE (arg_num_expr) == NON_LVALUE_EXPR)
1306 arg_num_expr = TREE_OPERAND (arg_num_expr, 0);
1308 if (TREE_CODE (arg_num_expr) != INTEGER_CST
1309 || TREE_INT_CST_HIGH (arg_num_expr) != 0)
1310 return false;
1312 *valp = TREE_INT_CST_LOW (arg_num_expr);
1313 return true;
1316 /* Handle a "nothrow" attribute; arguments as in
1317 struct attribute_spec.handler. */
1319 static tree
1320 handle_nothrow_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
1321 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
1323 if (TREE_CODE (*node) == FUNCTION_DECL)
1324 TREE_NOTHROW (*node) = 1;
1325 /* ??? TODO: Support types. */
1326 else
1328 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1329 *no_add_attrs = true;
1332 return NULL_TREE;
1335 #if 0
1336 /* not in gdc */
1337 /* Handle a "cleanup" attribute; arguments as in
1338 struct attribute_spec.handler. */
1340 static tree
1341 handle_cleanup_attribute (tree *node, tree name, tree args,
1342 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
1344 tree decl = *node;
1345 tree cleanup_id, cleanup_decl;
1347 /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do
1348 for global destructors in C++. This requires infrastructure that
1349 we don't have generically at the moment. It's also not a feature
1350 we'd be missing too much, since we do have attribute constructor. */
1351 if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
1353 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1354 *no_add_attrs = true;
1355 return NULL_TREE;
1358 /* Verify that the argument is a function in scope. */
1359 /* ??? We could support pointers to functions here as well, if
1360 that was considered desirable. */
1361 cleanup_id = TREE_VALUE (args);
1362 if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
1364 error ("cleanup arg not an identifier");
1365 *no_add_attrs = true;
1366 return NULL_TREE;
1368 cleanup_decl = lookup_name (cleanup_id);
1369 if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
1371 error ("cleanup arg not a function");
1372 *no_add_attrs = true;
1373 return NULL_TREE;
1376 /* That the function has proper type is checked with the
1377 eventual call to build_function_call. */
1379 return NULL_TREE;
1381 #endif
1383 /* Handle a "warn_unused_result" attribute. No special handling. */
1385 static tree
1386 handle_warn_unused_result_attribute (tree *node, tree name,
1387 tree args ATTRIBUTE_UNUSED,
1388 int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
1390 /* Ignore the attribute for functions not returning any value. */
1391 if (VOID_TYPE_P (TREE_TYPE (*node)))
1393 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
1394 *no_add_attrs = true;
1397 return NULL_TREE;
1400 #if 0
1401 /* not in gdc */
1402 /* Check for valid arguments being passed to a function. */
1403 static void
1404 check_function_arguments (tree attrs, tree params)
1406 /* Check for null being passed in a pointer argument that must be
1407 non-null. We also need to do this if format checking is enabled. */
1409 if (warn_nonnull)
1410 check_function_nonnull (attrs, params);
1412 /* Check for errors in format strings. */
1414 if (warn_format)
1415 check_function_format (NULL, attrs, params);
1417 #endif
1419 /* Generic argument checking recursion routine. PARAM is the argument to
1420 be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked
1421 once the argument is resolved. CTX is context for the callback. */
1422 void
1423 check_function_arguments_recurse (void (*callback)
1424 (void *, tree, unsigned HOST_WIDE_INT),
1425 void *ctx, tree param,
1426 unsigned HOST_WIDE_INT param_num)
1428 if (TREE_CODE (param) == NOP_EXPR)
1430 /* Strip coercion. */
1431 check_function_arguments_recurse (callback, ctx,
1432 TREE_OPERAND (param, 0), param_num);
1433 return;
1436 if (TREE_CODE (param) == CALL_EXPR)
1438 tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0)));
1439 tree attrs;
1440 bool found_format_arg = false;
1442 /* See if this is a call to a known internationalization function
1443 that modifies a format arg. Such a function may have multiple
1444 format_arg attributes (for example, ngettext). */
1446 for (attrs = TYPE_ATTRIBUTES (type);
1447 attrs;
1448 attrs = TREE_CHAIN (attrs))
1449 if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
1451 tree inner_args;
1452 tree format_num_expr;
1453 int format_num;
1454 int i;
1456 /* Extract the argument number, which was previously checked
1457 to be valid. */
1458 format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
1459 while (TREE_CODE (format_num_expr) == NOP_EXPR
1460 || TREE_CODE (format_num_expr) == CONVERT_EXPR
1461 || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
1462 format_num_expr = TREE_OPERAND (format_num_expr, 0);
1464 if (TREE_CODE (format_num_expr) != INTEGER_CST
1465 || TREE_INT_CST_HIGH (format_num_expr) != 0)
1466 abort ();
1468 format_num = TREE_INT_CST_LOW (format_num_expr);
1470 for (inner_args = TREE_OPERAND (param, 1), i = 1;
1471 inner_args != 0;
1472 inner_args = TREE_CHAIN (inner_args), i++)
1473 if (i == format_num)
1475 check_function_arguments_recurse (callback, ctx,
1476 TREE_VALUE (inner_args),
1477 param_num);
1478 found_format_arg = true;
1479 break;
1483 /* If we found a format_arg attribute and did a recursive check,
1484 we are done with checking this argument. Otherwise, we continue
1485 and this will be considered a non-literal. */
1486 if (found_format_arg)
1487 return;
1490 if (TREE_CODE (param) == COND_EXPR)
1492 /* Check both halves of the conditional expression. */
1493 check_function_arguments_recurse (callback, ctx,
1494 TREE_OPERAND (param, 1), param_num);
1495 check_function_arguments_recurse (callback, ctx,
1496 TREE_OPERAND (param, 2), param_num);
1497 return;
1500 (*callback) (ctx, param, param_num);