1 /* d-attribs.c -- D attributes handling. 2 Copyright (C) 2015-2022 Free Software Foundation, Inc. 3 4 GCC is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 3, or (at your option) 7 any later version. 8 9 GCC is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with GCC; see the file COPYING3. If not see 16 <http://www.gnu.org/licenses/>. */ 17 18 /* Implementation of attribute handlers for user defined attributes and 19 internal built-in functions. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 25 #include "dmd/attrib.h" 26 #include "dmd/declaration.h" 27 #include "dmd/expression.h" 28 #include "dmd/module.h" 29 #include "dmd/mtype.h" 30 #include "dmd/template.h" 31 32 #include "tree.h" 33 #include "diagnostic.h" 34 #include "tm.h" 35 #include "cgraph.h" 36 #include "toplev.h" 37 #include "target.h" 38 #include "common/common-target.h" 39 #include "stringpool.h" 40 #include "attribs.h" 41 #include "varasm.h" 42 #include "fold-const.h" 43 #include "opts.h" 44 45 #include "d-tree.h" 46 47 48 /* Internal attribute handlers for built-in functions. */ 49 static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); 50 static tree handle_leaf_attribute (tree *, tree, tree, int, bool *); 51 static tree handle_const_attribute (tree *, tree, tree, int, bool *); 52 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); 53 static tree handle_pure_attribute (tree *, tree, tree, int, bool *); 54 static tree handle_novops_attribute (tree *, tree, tree, int, bool *); 55 static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); 56 static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); 57 static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); 58 static tree handle_transaction_pure_attribute (tree *, tree, tree, int, bool *); 59 static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); 60 static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); 61 62 /* D attribute handlers for user defined attributes. */ 63 static tree d_handle_noinline_attribute (tree *, tree, tree, int, bool *); 64 static tree d_handle_always_inline_attribute (tree *, tree, tree, int, bool *); 65 static tree d_handle_flatten_attribute (tree *, tree, tree, int, bool *); 66 static tree d_handle_target_attribute (tree *, tree, tree, int, bool *); 67 static tree d_handle_target_clones_attribute (tree *, tree, tree, int, bool *); 68 static tree d_handle_optimize_attribute (tree *, tree, tree, int, bool *); 69 static tree d_handle_noclone_attribute (tree *, tree, tree, int, bool *); 70 static tree d_handle_noicf_attribute (tree *, tree, tree, int, bool *); 71 static tree d_handle_noipa_attribute (tree *, tree, tree, int, bool *); 72 static tree d_handle_section_attribute (tree *, tree, tree, int, bool *); 73 static tree d_handle_symver_attribute (tree *, tree, tree, int, bool *); 74 static tree d_handle_weak_attribute (tree *, tree, tree, int, bool *) ; 75 static tree d_handle_noplt_attribute (tree *, tree, tree, int, bool *) ; 76 static tree d_handle_alloc_size_attribute (tree *, tree, tree, int, bool *); 77 static tree d_handle_cold_attribute (tree *, tree, tree, int, bool *); 78 static tree d_handle_restrict_attribute (tree *, tree, tree, int, bool *); 79 static tree d_handle_used_attribute (tree *, tree, tree, int, bool *); 80 81 /* Helper to define attribute exclusions. */ 82 #define ATTR_EXCL(name, function, type, variable) \ 83 { name, function, type, variable } 84 85 /* Define attributes that are mutually exclusive with one another. */ 86 static const struct attribute_spec::exclusions attr_noreturn_exclusions[] = 87 { 88 ATTR_EXCL ("alloc_size", true, true, true), 89 ATTR_EXCL ("const", true, true, true), 90 ATTR_EXCL ("malloc", true, true, true), 91 ATTR_EXCL ("pure", true, true, true), 92 ATTR_EXCL ("returns_twice", true, true, true), 93 ATTR_EXCL (NULL, false, false, false), 94 }; 95 96 static const struct attribute_spec::exclusions attr_returns_twice_exclusions[] = 97 { 98 ATTR_EXCL ("noreturn", true, true, true), 99 ATTR_EXCL (NULL, false, false, false), 100 }; 101 102 static const struct attribute_spec::exclusions attr_const_pure_exclusions[] = 103 { 104 ATTR_EXCL ("alloc_size", true, true, true), 105 ATTR_EXCL ("const", true, true, true), 106 ATTR_EXCL ("noreturn", true, true, true), 107 ATTR_EXCL ("pure", true, true, true), 108 ATTR_EXCL (NULL, false, false, false) 109 }; 110 111 static const struct attribute_spec::exclusions attr_inline_exclusions[] = 112 { 113 ATTR_EXCL ("noinline", true, true, true), 114 ATTR_EXCL ("target_clones", true, true, true), 115 ATTR_EXCL (NULL, false, false, false), 116 }; 117 118 static const struct attribute_spec::exclusions attr_noinline_exclusions[] = 119 { 120 ATTR_EXCL ("always_inline", true, true, true), 121 ATTR_EXCL (NULL, false, false, false), 122 }; 123 124 static const struct attribute_spec::exclusions attr_target_exclusions[] = 125 { 126 ATTR_EXCL ("target_clones", true, true, true), 127 ATTR_EXCL (NULL, false, false, false), 128 }; 129 130 static const struct attribute_spec::exclusions attr_target_clones_exclusions[] = 131 { 132 ATTR_EXCL ("always_inline", true, true, true), 133 ATTR_EXCL ("target", true, true, true), 134 ATTR_EXCL (NULL, false, false, false), 135 }; 136 137 static const struct attribute_spec::exclusions attr_alloc_exclusions[] = 138 { 139 ATTR_EXCL ("const", true, true, true), 140 ATTR_EXCL ("noreturn", true, true, true), 141 ATTR_EXCL ("pure", true, true, true), 142 ATTR_EXCL (NULL, false, false, false), 143 }; 144 145 extern const struct attribute_spec::exclusions attr_cold_hot_exclusions[] = 146 { 147 ATTR_EXCL ("cold", true, true, true), 148 ATTR_EXCL ("hot", true, true, true), 149 ATTR_EXCL (NULL, false, false, false) 150 }; 151 152 /* Helper to define an attribute. */ 153 #define ATTR_SPEC(name, min_len, max_len, decl_req, type_req, fn_type_req, \ 154 affects_type_identity, handler, exclude) \ 155 { name, min_len, max_len, decl_req, type_req, fn_type_req, \ 156 affects_type_identity, handler, exclude } 157 158 /* Table of machine-independent attributes. 159 For internal use (marking of built-ins) only. */ 160 const attribute_spec d_langhook_common_attribute_table[] = 161 { 162 ATTR_SPEC ("noreturn", 0, 0, true, false, false, false, 163 handle_noreturn_attribute, attr_noreturn_exclusions), 164 ATTR_SPEC ("leaf", 0, 0, true, false, false, false, 165 handle_leaf_attribute, NULL), 166 ATTR_SPEC ("const", 0, 0, true, false, false, false, 167 handle_const_attribute, attr_const_pure_exclusions), 168 ATTR_SPEC ("malloc", 0, 0, true, false, false, false, 169 handle_malloc_attribute, NULL), 170 ATTR_SPEC ("returns_twice", 0, 0, true, false, false, false, 171 handle_returns_twice_attribute, attr_returns_twice_exclusions), 172 ATTR_SPEC ("pure", 0, 0, true, false, false, false, 173 handle_pure_attribute, attr_const_pure_exclusions), 174 ATTR_SPEC ("nonnull", 0, -1, false, true, true, false, 175 handle_nonnull_attribute, NULL), 176 ATTR_SPEC ("nothrow", 0, 0, true, false, false, false, 177 handle_nothrow_attribute, NULL), 178 ATTR_SPEC ("transaction_pure", 0, 0, false, true, true, false, 179 handle_transaction_pure_attribute, NULL), 180 ATTR_SPEC ("no vops", 0, 0, true, false, false, false, 181 handle_novops_attribute, NULL), 182 ATTR_SPEC ("type generic", 0, 0, false, true, true, false, 183 handle_type_generic_attribute, NULL), 184 ATTR_SPEC ("fn spec", 1, 1, false, true, true, false, 185 handle_fnspec_attribute, NULL), 186 ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL), 187 }; 188 189 /* Table of D language attributes exposed by `gcc.attribute' UDAs. */ 190 const attribute_spec d_langhook_attribute_table[] = 191 { 192 ATTR_SPEC ("noinline", 0, 0, true, false, false, false, 193 d_handle_noinline_attribute, attr_noinline_exclusions), 194 ATTR_SPEC ("always_inline", 0, 0, true, false, false, false, 195 d_handle_always_inline_attribute, attr_inline_exclusions), 196 ATTR_SPEC ("flatten", 0, 0, true, false, false, false, 197 d_handle_flatten_attribute, NULL), 198 ATTR_SPEC ("target", 1, -1, true, false, false, false, 199 d_handle_target_attribute, attr_target_exclusions), 200 ATTR_SPEC ("target_clones", 1, -1, true, false, false, false, 201 d_handle_target_clones_attribute, attr_target_clones_exclusions), 202 ATTR_SPEC ("optimize", 1, -1, true, false, false, false, 203 d_handle_optimize_attribute, NULL), 204 ATTR_SPEC ("noclone", 0, 0, true, false, false, false, 205 d_handle_noclone_attribute, NULL), 206 ATTR_SPEC ("no_icf", 0, 0, true, false, false, false, 207 d_handle_noicf_attribute, NULL), 208 ATTR_SPEC ("noipa", 0, 0, true, false, false, false, 209 d_handle_noipa_attribute, NULL), 210 ATTR_SPEC ("section", 1, 1, true, false, false, false, 211 d_handle_section_attribute, NULL), 212 ATTR_SPEC ("symver", 1, -1, true, false, false, false, 213 d_handle_symver_attribute, NULL), 214 ATTR_SPEC ("weak", 0, 0, true, false, false, false, 215 d_handle_weak_attribute, NULL), 216 ATTR_SPEC ("noplt", 0, 0, true, false, false, false, 217 d_handle_noplt_attribute, NULL), 218 ATTR_SPEC ("alloc_size", 1, 3, false, true, true, false, 219 d_handle_alloc_size_attribute, attr_alloc_exclusions), 220 ATTR_SPEC ("cold", 0, 0, true, false, false, false, 221 d_handle_cold_attribute, attr_cold_hot_exclusions), 222 ATTR_SPEC ("restrict", 0, 0, true, false, false, false, 223 d_handle_restrict_attribute, NULL), 224 ATTR_SPEC ("used", 0, 0, true, false, false, false, 225 d_handle_used_attribute, NULL), 226 ATTR_SPEC (NULL, 0, 0, false, false, false, false, NULL, NULL), 227 }; 228 229 230 /* Insert the type attribute ATTRNAME with value VALUE into TYPE. 231 Returns a new variant of the original type declaration. */ 232 233 tree 234 insert_type_attribute (tree type, const char *attrname, tree value) 235 { 236 tree ident = get_identifier (attrname); 237 238 if (value) 239 value = tree_cons (NULL_TREE, value, NULL_TREE); 240 241 tree attribs = merge_attributes (TYPE_ATTRIBUTES (type), 242 tree_cons (ident, value, NULL_TREE)); 243 244 return build_type_attribute_variant (type, attribs); 245 } 246 247 /* Insert the decl attribute ATTRNAME with value VALUE into DECL. */ 248 249 tree 250 insert_decl_attribute (tree decl, const char *attrname, tree value) 251 { 252 tree ident = get_identifier (attrname); 253 254 if (value) 255 value = tree_cons (NULL_TREE, value, NULL_TREE); 256 257 tree attribs = merge_attributes (DECL_ATTRIBUTES (decl), 258 tree_cons (ident, value, NULL_TREE)); 259 260 return build_decl_attribute_variant (decl, attribs); 261 } 262 263 /* Returns TRUE if NAME is an attribute recognized as being handled by 264 the `gcc.attribute' module. */ 265 266 static bool 267 uda_attribute_p (const char *name) 268 { 269 tree ident = get_identifier (name); 270 271 /* Search both our language, and target attribute tables. 272 Common and format attributes are kept internal. */ 273 for (const attribute_spec *p = d_langhook_attribute_table; p->name; p++) 274 { 275 if (get_identifier (p->name) == ident) 276 return true; 277 } 278 279 if (targetm.attribute_table) 280 { 281 for (const attribute_spec *p = targetm.attribute_table; p->name; p++) 282 { 283 if (get_identifier (p->name) == ident) 284 return true; 285 } 286 } 287 288 return false; 289 } 290 291 /* [attribute/uda] 292 293 User Defined Attributes (UDA) are compile time expressions that can be 294 attached to a declaration. These attributes can then be queried, extracted, 295 and manipulated at compile-time. There is no run-time component to them. 296 297 Expand and merge all UDAs found in the EATTRS list that are of type 298 `gcc.attribute.Attribute'. This symbol is internally recognized by the 299 compiler and maps them to their equivalent GCC attribute. */ 300 301 static tree 302 build_attributes (Expressions *eattrs) 303 { 304 if (!eattrs) 305 return NULL_TREE; 306 307 expandTuples (eattrs); 308 309 tree attribs = NULL_TREE; 310 311 for (size_t i = 0; i < eattrs->length; i++) 312 { 313 Expression *attr = (*eattrs)[i]; 314 Dsymbol *sym = attr->type->toDsymbol (0); 315 316 if (!sym) 317 { 318 /* If attribute is a template symbol, perhaps arguments were not 319 supplied, so warn about attribute having no effect. */ 320 if (TemplateExp *te = attr->isTemplateExp ()) 321 { 322 if (!te->td || !te->td->onemember) 323 continue; 324 325 sym = te->td->onemember; 326 } 327 else 328 continue; 329 } 330 331 /* Attribute symbol must come from the `gcc.attribute' module. */ 332 Dsymbol *mod = sym->getModule (); 333 if (!(strcmp (mod->toChars (), "attributes") == 0 334 && mod->parent != NULL 335 && strcmp (mod->parent->toChars (), "gcc") == 0 336 && !mod->parent->parent)) 337 continue; 338 339 /* Get the result of the attribute if it hasn't already been folded. */ 340 if (attr->op == EXP::call) 341 attr = attr->ctfeInterpret (); 342 343 if (attr->op != EXP::structLiteral) 344 { 345 warning_at (make_location_t (attr->loc), OPT_Wattributes, 346 "%qE attribute has no effect", 347 get_identifier (sym->toChars ())); 348 continue; 349 } 350 351 /* Should now have a struct `Attribute("attrib", "value", ...)' 352 initializer list. */ 353 Expressions *elems = attr->isStructLiteralExp ()->elements; 354 Expression *e0 = (*elems)[0]; 355 356 if (e0->op != EXP::string_) 357 { 358 warning_at (make_location_t (attr->loc), OPT_Wattributes, 359 "unknown attribute %qs", e0->toChars()); 360 continue; 361 } 362 363 StringExp *se = e0->toStringExp (); 364 gcc_assert (se->sz == 1); 365 366 /* Empty string attribute, just ignore it. */ 367 if (se->len == 0) 368 continue; 369 370 /* Check if the attribute is recognized and handled. 371 Done here to report the diagnostic at the right location. */ 372 const char *name = (const char *)(se->len ? se->string : ""); 373 if (!uda_attribute_p (name)) 374 { 375 warning_at (make_location_t (attr->loc), OPT_Wattributes, 376 "unknown attribute %qs", name); 377 continue; 378 } 379 380 /* Chain all attribute arguments together. */ 381 tree args = NULL_TREE; 382 383 for (size_t j = 1; j < elems->length; j++) 384 { 385 Expression *e = (*elems)[j]; 386 /* Stop after the first `void' argument. */ 387 if (e == NULL) 388 break; 389 390 StringExp *s = e->isStringExp (); 391 tree t; 392 if (s != NULL && s->sz == 1) 393 { 394 const char *string = (const char *)(s->len ? s->string : ""); 395 t = build_string (s->len, string); 396 } 397 else 398 t = build_expr (e); 399 400 args = chainon (args, build_tree_list (0, t)); 401 } 402 403 tree list = build_tree_list (get_identifier (name), args); 404 attribs = chainon (attribs, list); 405 } 406 407 return attribs; 408 } 409 410 /* If any GCC attributes are found in the declaration SYM, apply them to the 411 type or decl NODE. */ 412 413 void 414 apply_user_attributes (Dsymbol *sym, tree node) 415 { 416 if (!sym->userAttribDecl) 417 { 418 if (DECL_P (node) && DECL_ATTRIBUTES (node) != NULL) 419 decl_attributes (&node, DECL_ATTRIBUTES (node), 0); 420 421 return; 422 } 423 424 location_t saved_location = input_location; 425 input_location = make_location_t (sym->loc); 426 427 Expressions *attrs = sym->userAttribDecl->getAttributes (); 428 decl_attributes (&node, build_attributes (attrs), 429 TYPE_P (node) ? ATTR_FLAG_TYPE_IN_PLACE : 0); 430 431 input_location = saved_location; 432 } 433 434 /* Built-in attribute handlers. 435 These functions take the arguments: 436 (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ 437 438 /* Handle a "noreturn" attribute; arguments as in 439 struct attribute_spec.handler. */ 440 441 static tree 442 handle_noreturn_attribute (tree *node, tree, tree, int, bool *) 443 { 444 tree type = TREE_TYPE (*node); 445 446 if (TREE_CODE (*node) == FUNCTION_DECL) 447 TREE_THIS_VOLATILE (*node) = 1; 448 else if (TREE_CODE (type) == POINTER_TYPE 449 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) 450 TREE_TYPE (*node) 451 = build_pointer_type 452 (build_type_variant (TREE_TYPE (type), 453 TYPE_READONLY (TREE_TYPE (type)), 1)); 454 else 455 gcc_unreachable (); 456 457 return NULL_TREE; 458 } 459 460 /* Handle a "leaf" attribute; arguments as in 461 struct attribute_spec.handler. */ 462 463 static tree 464 handle_leaf_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) 465 { 466 if (TREE_CODE (*node) != FUNCTION_DECL) 467 { 468 warning (OPT_Wattributes, "%qE attribute ignored", name); 469 *no_add_attrs = true; 470 } 471 if (!TREE_PUBLIC (*node)) 472 { 473 warning (OPT_Wattributes, "%qE attribute has no effect", name); 474 *no_add_attrs = true; 475 } 476 477 return NULL_TREE; 478 } 479 480 /* Handle a "const" attribute; arguments as in 481 struct attribute_spec.handler. */ 482 483 static tree 484 handle_const_attribute (tree *node, tree, tree, int, bool *) 485 { 486 tree type = TREE_TYPE (*node); 487 488 if (TREE_CODE (*node) == FUNCTION_DECL) 489 TREE_READONLY (*node) = 1; 490 else if (TREE_CODE (type) == POINTER_TYPE 491 && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) 492 TREE_TYPE (*node) 493 = build_pointer_type 494 (build_type_variant (TREE_TYPE (type), 1, 495 TREE_THIS_VOLATILE (TREE_TYPE (type)))); 496 else 497 gcc_unreachable (); 498 499 return NULL_TREE; 500 } 501 502 /* Handle a "malloc" attribute; arguments as in 503 struct attribute_spec.handler. */ 504 505 tree 506 handle_malloc_attribute (tree *node, tree, tree, int, bool *) 507 { 508 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL 509 && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node)))); 510 DECL_IS_MALLOC (*node) = 1; 511 return NULL_TREE; 512 } 513 514 /* Handle a "pure" attribute; arguments as in 515 struct attribute_spec.handler. */ 516 517 static tree 518 handle_pure_attribute (tree *node, tree, tree, int, bool *) 519 { 520 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); 521 DECL_PURE_P (*node) = 1; 522 return NULL_TREE; 523 } 524 525 /* Handle a "no vops" attribute; arguments as in 526 struct attribute_spec.handler. */ 527 528 static tree 529 handle_novops_attribute (tree *node, tree, tree, int, bool *) 530 { 531 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); 532 DECL_IS_NOVOPS (*node) = 1; 533 return NULL_TREE; 534 } 535 536 /* Helper for nonnull attribute handling; fetch the operand number 537 from the attribute argument list. */ 538 539 static bool 540 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp) 541 { 542 /* Verify the arg number is a constant. */ 543 if (!tree_fits_uhwi_p (arg_num_expr)) 544 return false; 545 546 *valp = TREE_INT_CST_LOW (arg_num_expr); 547 return true; 548 } 549 550 /* Handle the "nonnull" attribute. */ 551 552 static tree 553 handle_nonnull_attribute (tree *node, tree, tree args, int, bool *) 554 { 555 tree type = *node; 556 557 /* If no arguments are specified, all pointer arguments should be 558 non-null. Verify a full prototype is given so that the arguments 559 will have the correct types when we actually check them later. 560 Avoid diagnosing type-generic built-ins since those have no 561 prototype. */ 562 if (!args) 563 { 564 gcc_assert (prototype_p (type) 565 || !TYPE_ATTRIBUTES (type) 566 || lookup_attribute ("type generic", TYPE_ATTRIBUTES (type))); 567 568 return NULL_TREE; 569 } 570 571 /* Argument list specified. Verify that each argument number references 572 a pointer argument. */ 573 for (; args; args = TREE_CHAIN (args)) 574 { 575 tree argument; 576 unsigned HOST_WIDE_INT arg_num = 0, ck_num; 577 578 if (!get_nonnull_operand (TREE_VALUE (args), &arg_num)) 579 gcc_unreachable (); 580 581 argument = TYPE_ARG_TYPES (type); 582 if (argument) 583 { 584 for (ck_num = 1; ; ck_num++) 585 { 586 if (!argument || ck_num == arg_num) 587 break; 588 argument = TREE_CHAIN (argument); 589 } 590 591 gcc_assert (argument 592 && TREE_CODE (TREE_VALUE (argument)) == POINTER_TYPE); 593 } 594 } 595 596 return NULL_TREE; 597 } 598 599 /* Handle a "nothrow" attribute; arguments as in 600 struct attribute_spec.handler. */ 601 602 static tree 603 handle_nothrow_attribute (tree *node, tree, tree, int, bool *) 604 { 605 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); 606 TREE_NOTHROW (*node) = 1; 607 return NULL_TREE; 608 } 609 610 /* Handle a "type generic" attribute; arguments as in 611 struct attribute_spec.handler. */ 612 613 static tree 614 handle_type_generic_attribute (tree *node, tree, tree, int, bool *) 615 { 616 /* Ensure we have a function type. */ 617 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE); 618 619 /* Ensure we have a variadic function. */ 620 gcc_assert (!prototype_p (*node) || stdarg_p (*node)); 621 622 return NULL_TREE; 623 } 624 625 /* Handle a "transaction_pure" attribute; arguments as in 626 struct attribute_spec.handler. */ 627 628 static tree 629 handle_transaction_pure_attribute (tree *node, tree, tree, int, bool *) 630 { 631 /* Ensure we have a function type. */ 632 gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE); 633 634 return NULL_TREE; 635 } 636 637 /* Handle a "returns_twice" attribute; arguments as in 638 struct attribute_spec.handler. */ 639 640 static tree 641 handle_returns_twice_attribute (tree *node, tree, tree, int, bool *) 642 { 643 gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); 644 645 DECL_IS_RETURNS_TWICE (*node) = 1; 646 647 return NULL_TREE; 648 } 649 650 /* Handle a "fn spec" attribute; arguments as in 651 struct attribute_spec.handler. */ 652 653 tree 654 handle_fnspec_attribute (tree *, tree, tree args, int, bool *) 655 { 656 gcc_assert (args 657 && TREE_CODE (TREE_VALUE (args)) == STRING_CST 658 && !TREE_CHAIN (args)); 659 return NULL_TREE; 660 } 661 662 /* Language specific attribute handlers. 663 These functions take the arguments: 664 (tree *node, tree name, tree args, int flags, bool *no_add_attrs) */ 665 666 /* Handle a "noinline" attribute; arguments as in 667 struct attribute_spec.handler. */ 668 669 static tree 670 d_handle_noinline_attribute (tree *node, tree name, tree, int, 671 bool *no_add_attrs) 672 { 673 if (TREE_CODE (*node) == FUNCTION_DECL) 674 DECL_UNINLINABLE (*node) = 1; 675 else 676 { 677 warning (OPT_Wattributes, "%qE attribute ignored", name); 678 *no_add_attrs = true; 679 } 680 681 return NULL_TREE; 682 } 683 684 /* Handle a "always_inline" attribute; arguments as in 685 struct attribute_spec.handler. */ 686 687 static tree 688 d_handle_always_inline_attribute (tree *node, tree name, tree, int, 689 bool *no_add_attrs) 690 { 691 if (TREE_CODE (*node) == FUNCTION_DECL) 692 { 693 DECL_DECLARED_INLINE_P (*node) = 1; 694 DECL_DISREGARD_INLINE_LIMITS (*node) = 1; 695 } 696 else 697 { 698 warning (OPT_Wattributes, "%qE attribute ignored", name); 699 *no_add_attrs = true; 700 } 701 702 return NULL_TREE; 703 } 704 705 /* Handle a "flatten" attribute; arguments as in 706 struct attribute_spec.handler. */ 707 708 static tree 709 d_handle_flatten_attribute (tree *node, tree name, tree, int, 710 bool *no_add_attrs) 711 { 712 if (TREE_CODE (*node) != FUNCTION_DECL) 713 { 714 warning (OPT_Wattributes, "%qE attribute ignored", name); 715 *no_add_attrs = true; 716 } 717 718 return NULL_TREE; 719 } 720 721 /* Handle a "target" attribute; arguments as in 722 struct attribute_spec.handler. */ 723 724 static tree 725 d_handle_target_attribute (tree *node, tree name, tree args, int flags, 726 bool *no_add_attrs) 727 { 728 /* Ensure we have a function type. */ 729 if (TREE_CODE (*node) != FUNCTION_DECL) 730 { 731 warning (OPT_Wattributes, "%qE attribute ignored", name); 732 *no_add_attrs = true; 733 } 734 else if (!targetm.target_option.valid_attribute_p (*node, name, args, flags)) 735 *no_add_attrs = true; 736 737 /* Check that there's no empty string in values of the attribute. */ 738 for (tree t = args; t != NULL_TREE; t = TREE_CHAIN (t)) 739 { 740 tree value = TREE_VALUE (t); 741 if (TREE_CODE (value) != STRING_CST 742 || (TREE_STRING_LENGTH (value) != 0 743 && TREE_STRING_POINTER (value)[0] != '\0')) 744 continue; 745 746 warning (OPT_Wattributes, "empty string in attribute %<target%>"); 747 *no_add_attrs = true; 748 } 749 750 return NULL_TREE; 751 } 752 753 /* Handle a "target_clones" attribute; arguments as in 754 struct attribute_spec.handler. */ 755 756 static tree 757 d_handle_target_clones_attribute (tree *node, tree name, tree, int, 758 bool *no_add_attrs) 759 { 760 /* Ensure we have a function type. */ 761 if (TREE_CODE (*node) != FUNCTION_DECL) 762 { 763 warning (OPT_Wattributes, "%qE attribute ignored", name); 764 *no_add_attrs = true; 765 } 766 else 767 { 768 /* Do not inline functions with multiple clone targets. */ 769 DECL_UNINLINABLE (*node) = 1; 770 } 771 772 return NULL_TREE; 773 } 774 775 /* Arguments being collected for optimization. */ 776 static GTY(()) vec <const char *, va_gc> *optimize_args; 777 778 /* Inner function to convert a TREE_LIST to argv string to parse the optimize 779 options in ARGS. */ 780 781 static bool 782 parse_optimize_options (tree args) 783 { 784 bool ret = true; 785 786 /* Build up argv vector. Just in case the string is stored away, use garbage 787 collected strings. */ 788 vec_safe_truncate (optimize_args, 0); 789 vec_safe_push (optimize_args, (const char *) NULL); 790 791 for (tree ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap)) 792 { 793 tree value = TREE_VALUE (ap); 794 795 if (TREE_CODE (value) == INTEGER_CST) 796 { 797 char buffer[20]; 798 sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value)); 799 vec_safe_push (optimize_args, ggc_strdup (buffer)); 800 } 801 else if (TREE_CODE (value) == STRING_CST) 802 { 803 size_t len = TREE_STRING_LENGTH (value); 804 const char *p = TREE_STRING_POINTER (value); 805 806 /* If the user supplied -Oxxx or -fxxx, only allow -Oxxx or -fxxx 807 options. */ 808 if (*p == '-' && p[1] != 'O' && p[1] != 'f') 809 { 810 ret = false; 811 warning (OPT_Wattributes, 812 "bad option %qs to attribute %<optimize%>", p); 813 continue; 814 } 815 816 /* Can't use GC memory here. */ 817 char *q = XOBNEWVEC (&opts_obstack, char, len + 3); 818 char *r = q; 819 820 if (*p != '-') 821 { 822 *r++ = '-'; 823 824 /* Assume that Ox is -Ox, a numeric value is -Ox, a s by 825 itself is -Os, and any other switch begins with a -f. */ 826 if ((*p >= '0' && *p <= '9') || (p[0] == 's' && p[1] == '\0')) 827 *r++ = 'O'; 828 else if (*p != 'O') 829 *r++ = 'f'; 830 } 831 832 memcpy (r, p, len); 833 r[len] = '\0'; 834 vec_safe_push (optimize_args, (const char *) q); 835 } 836 } 837 838 unsigned opt_argc = optimize_args->length (); 839 const char **opt_argv 840 = (const char **) alloca (sizeof (char *) * (opt_argc + 1)); 841 842 for (unsigned i = 1; i < opt_argc; i++) 843 opt_argv[i] = (*optimize_args)[i]; 844 845 /* Now parse the options. */ 846 struct cl_decoded_option *decoded_options; 847 unsigned int decoded_options_count; 848 849 decode_cmdline_options_to_array_default_mask (opt_argc, opt_argv, 850 &decoded_options, 851 &decoded_options_count); 852 /* Drop non-Optimization options. */ 853 unsigned j = 1; 854 for (unsigned i = 1; i < decoded_options_count; ++i) 855 { 856 unsigned opt_index = decoded_options[i].opt_index; 857 if (opt_index >= cl_options_count 858 || ! (cl_options[opt_index].flags & CL_OPTIMIZATION)) 859 { 860 ret = false; 861 warning (OPT_Wattributes, 862 "bad option %qs to attribute %<optimize%>", 863 decoded_options[i].orig_option_with_args_text); 864 continue; 865 } 866 if (i != j) 867 decoded_options[j] = decoded_options[i]; 868 j++; 869 } 870 decoded_options_count = j; 871 /* And apply them. */ 872 decode_options (&global_options, &global_options_set, 873 decoded_options, decoded_options_count, 874 input_location, global_dc, NULL); 875 876 targetm.override_options_after_change(); 877 878 optimize_args->truncate (0); 879 return ret; 880 } 881 882 /* Handle a "optimize" attribute; arguments as in 883 struct attribute_spec.handler. */ 884 885 static tree 886 d_handle_optimize_attribute (tree *node, tree name, tree args, int, 887 bool *no_add_attrs) 888 { 889 /* Ensure we have a function type. */ 890 if (TREE_CODE (*node) != FUNCTION_DECL) 891 { 892 warning (OPT_Wattributes, "%qE attribute ignored", name); 893 *no_add_attrs = true; 894 } 895 else 896 { 897 struct cl_optimization cur_opts; 898 tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node); 899 900 /* Save current options. */ 901 cl_optimization_save (&cur_opts, &global_options, &global_options_set); 902 tree prev_target_node = build_target_option_node (&global_options, 903 &global_options_set); 904 905 /* If we previously had some optimization options, use them as the 906 default. */ 907 gcc_options *saved_global_options = NULL; 908 if (flag_checking) 909 { 910 saved_global_options = XNEW (gcc_options); 911 *saved_global_options = global_options; 912 } 913 914 if (old_opts) 915 cl_optimization_restore (&global_options, &global_options_set, 916 TREE_OPTIMIZATION (old_opts)); 917 918 /* Parse options, and update the vector. */ 919 parse_optimize_options (args); 920 DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) 921 = build_optimization_node (&global_options, &global_options_set); 922 tree target_node = build_target_option_node (&global_options, 923 &global_options_set); 924 if (prev_target_node != target_node) 925 DECL_FUNCTION_SPECIFIC_TARGET (*node) = target_node; 926 927 /* Restore current options. */ 928 cl_optimization_restore (&global_options, &global_options_set, 929 &cur_opts); 930 cl_target_option_restore (&global_options, &global_options_set, 931 TREE_TARGET_OPTION (prev_target_node)); 932 if (saved_global_options != NULL) 933 { 934 cl_optimization_compare (saved_global_options, &global_options); 935 free (saved_global_options); 936 } 937 } 938 939 return NULL_TREE; 940 } 941 942 /* Handle a "noclone" attribute; arguments as in 943 struct attribute_spec.handler. */ 944 945 static tree 946 d_handle_noclone_attribute (tree *node, tree name, tree, int, 947 bool *no_add_attrs) 948 { 949 if (TREE_CODE (*node) != FUNCTION_DECL) 950 { 951 warning (OPT_Wattributes, "%qE attribute ignored", name); 952 *no_add_attrs = true; 953 } 954 955 return NULL_TREE; 956 } 957 958 /* Handle a "no_icf" attribute; arguments as in 959 struct attribute_spec.handler. */ 960 961 static tree 962 d_handle_noicf_attribute (tree *node, tree name, tree, int, 963 bool *no_add_attrs) 964 { 965 if (TREE_CODE (*node) != FUNCTION_DECL) 966 { 967 warning (OPT_Wattributes, "%qE attribute ignored", name); 968 *no_add_attrs = true; 969 } 970 971 return NULL_TREE; 972 } 973 974 /* Handle a "noipa" attribute; arguments as in 975 struct attribute_spec.handler. */ 976 977 static tree 978 d_handle_noipa_attribute (tree *node, tree name, tree, int, 979 bool *no_add_attrs) 980 { 981 if (TREE_CODE (*node) != FUNCTION_DECL) 982 { 983 warning (OPT_Wattributes, "%qE attribute ignored", name); 984 *no_add_attrs = true; 985 } 986 987 return NULL_TREE; 988 } 989 990 /* Handle a "section" attribute; arguments as in 991 struct attribute_spec.handler. */ 992 993 static tree 994 d_handle_section_attribute (tree *node, tree name, tree args, int flags, 995 bool *no_add_attrs) 996 { 997 if (!targetm_common.have_named_sections) 998 { 999 error ("section attributes are not supported for this target"); 1000 *no_add_attrs = true; 1001 return NULL_TREE; 1002 } 1003 1004 if (!VAR_OR_FUNCTION_DECL_P (*node)) 1005 { 1006 error ("section attribute not allowed for %q+D", *node); 1007 *no_add_attrs = true; 1008 return NULL_TREE; 1009 } 1010 1011 if (TREE_CODE (TREE_VALUE (args)) != STRING_CST) 1012 { 1013 error ("section attribute argument not a string constant"); 1014 *no_add_attrs = true; 1015 return NULL_TREE; 1016 } 1017 1018 if (VAR_P (*node) 1019 && current_function_decl != NULL_TREE 1020 && !TREE_STATIC (*node)) 1021 { 1022 error ("section attribute cannot be specified for local variables"); 1023 *no_add_attrs = true; 1024 return NULL_TREE; 1025 } 1026 1027 /* The decl may have already been given a section attribute 1028 from a previous declaration. Ensure they match. */ 1029 if (DECL_SECTION_NAME (*node) != NULL 1030 && strcmp (DECL_SECTION_NAME (*node), 1031 TREE_STRING_POINTER (TREE_VALUE (args))) != 0) 1032 { 1033 error ("section of %q+D conflicts with previous declaration", *node); 1034 *no_add_attrs = true; 1035 return NULL_TREE; 1036 } 1037 1038 if (VAR_P (*node) 1039 && !targetm.have_tls && targetm.emutls.tmpl_section 1040 && DECL_THREAD_LOCAL_P (*node)) 1041 { 1042 error ("section of %q+D cannot be overridden", *node); 1043 *no_add_attrs = true; 1044 return NULL_TREE; 1045 } 1046 1047 tree res = targetm.handle_generic_attribute (node, name, args, flags, 1048 no_add_attrs); 1049 1050 /* If the back end confirms the attribute can be added then continue onto 1051 final processing. */ 1052 if (*no_add_attrs) 1053 return NULL_TREE; 1054 1055 set_decl_section_name (*node, TREE_STRING_POINTER (TREE_VALUE (args))); 1056 return res; 1057 } 1058 1059 /* Handle a "symver" and attribute; arguments as in 1060 struct attribute_spec.handler. */ 1061 1062 static tree 1063 d_handle_symver_attribute (tree *node, tree, tree args, int, bool *no_add_attrs) 1064 { 1065 if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL) 1066 { 1067 warning (OPT_Wattributes, 1068 "%<symver%> attribute only applies to functions and variables"); 1069 *no_add_attrs = true; 1070 return NULL_TREE; 1071 } 1072 1073 if (!decl_in_symtab_p (*node)) 1074 { 1075 warning (OPT_Wattributes, 1076 "%<symver%> attribute is only applicable to symbols"); 1077 *no_add_attrs = true; 1078 return NULL_TREE; 1079 } 1080 1081 for (; args; args = TREE_CHAIN (args)) 1082 { 1083 tree symver = TREE_VALUE (args); 1084 if (TREE_CODE (symver) != STRING_CST) 1085 { 1086 error ("%<symver%> attribute argument not a string constant"); 1087 *no_add_attrs = true; 1088 return NULL_TREE; 1089 } 1090 1091 const char *symver_str = TREE_STRING_POINTER (symver); 1092 1093 int ats = 0; 1094 for (int n = 0; (int)n < TREE_STRING_LENGTH (symver); n++) 1095 if (symver_str[n] == '@') 1096 ats++; 1097 1098 if (ats != 1 && ats != 2) 1099 { 1100 error ("symver attribute argument must have format %<name@nodename%>"); 1101 error ("%<symver%> attribute argument %qs must contain one or two " 1102 "%<@%>", symver_str); 1103 *no_add_attrs = true; 1104 return NULL_TREE; 1105 } 1106 } 1107 1108 return NULL_TREE; 1109 } 1110 1111 /* Handle a "weak" attribute; arguments as in 1112 struct attribute_spec.handler. */ 1113 1114 static tree 1115 d_handle_weak_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) 1116 { 1117 if (TREE_CODE (*node) == FUNCTION_DECL 1118 && DECL_DECLARED_INLINE_P (*node)) 1119 { 1120 warning (OPT_Wattributes, "inline function %q+D declared weak", *node); 1121 *no_add_attrs = true; 1122 } 1123 else if (VAR_OR_FUNCTION_DECL_P (*node)) 1124 { 1125 struct symtab_node *n = symtab_node::get (*node); 1126 if (n && n->refuse_visibility_changes) 1127 error ("%q+D declared weak after being used", *node); 1128 declare_weak (*node); 1129 } 1130 else 1131 warning (OPT_Wattributes, "%qE attribute ignored", name); 1132 1133 return NULL_TREE; 1134 } 1135 1136 /* Handle a "noplt" attribute; arguments as in 1137 struct attribute_spec.handler. */ 1138 1139 static tree 1140 d_handle_noplt_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) 1141 { 1142 if (TREE_CODE (*node) != FUNCTION_DECL) 1143 { 1144 warning (OPT_Wattributes, "%qE attribute ignored", name); 1145 *no_add_attrs = true; 1146 } 1147 1148 return NULL_TREE; 1149 } 1150 1151 /* Verify that argument value POS at position ARGNO to attribute ATNAME applied 1152 to function FNTYPE refers to a function parameter at position POS and is a 1153 valid integer type. When ZERO_BASED is true, POS is adjusted to be 1-based. 1154 If successful, POS is returned. Otherwise, issue appropriate warnings and 1155 return null. A non-zero 1-based ARGNO should be passed in by callers only 1156 for attributes with more than one argument. */ 1157 1158 static tree 1159 positional_argument (const_tree fntype, const_tree atname, tree pos, 1160 int argno, bool zero_based) 1161 { 1162 tree postype = TREE_TYPE (pos); 1163 1164 if (pos == error_mark_node || !postype) 1165 { 1166 /* Only mention the positional argument number when it's non-zero. */ 1167 if (argno < 1) 1168 warning (OPT_Wattributes, 1169 "%qE attribute argument is invalid", atname); 1170 else 1171 warning (OPT_Wattributes, 1172 "%qE attribute argument %i is invalid", atname, argno); 1173 1174 return NULL_TREE; 1175 } 1176 1177 if (!INTEGRAL_TYPE_P (postype)) 1178 { 1179 /* Handle this case specially to avoid mentioning the value 1180 of pointer constants in diagnostics. Only mention 1181 the positional argument number when it's non-zero. */ 1182 if (argno < 1) 1183 warning (OPT_Wattributes, 1184 "%qE attribute argument has type %qT", 1185 atname, postype); 1186 else 1187 warning (OPT_Wattributes, 1188 "%qE attribute argument %i has type %qT", 1189 atname, argno, postype); 1190 1191 return NULL_TREE; 1192 } 1193 1194 if (TREE_CODE (pos) != INTEGER_CST) 1195 { 1196 /* Only mention the argument number when it's non-zero. */ 1197 if (argno < 1) 1198 warning (OPT_Wattributes, 1199 "%qE attribute argument value %qE is not an integer " 1200 "constant", 1201 atname, pos); 1202 else 1203 warning (OPT_Wattributes, 1204 "%qE attribute argument %i value %qE is not an integer " 1205 "constant", 1206 atname, argno, pos); 1207 1208 return NULL_TREE; 1209 } 1210 1211 /* Validate the value of the position argument. If 0-based, then it should 1212 not be negative. If 1-based, it should be greater than zero. */ 1213 if ((zero_based && tree_int_cst_sgn (pos) < 0) 1214 || (!zero_based && tree_int_cst_sgn (pos) < 1)) 1215 { 1216 if (argno < 1) 1217 warning (OPT_Wattributes, 1218 "%qE attribute argument value %qE does not refer to " 1219 "a function parameter", 1220 atname, pos); 1221 else 1222 warning (OPT_Wattributes, 1223 "%qE attribute argument %i value %qE does not refer to " 1224 "a function parameter", 1225 atname, argno, pos); 1226 1227 return NULL_TREE; 1228 } 1229 1230 /* Adjust the value of pos to be 1-based. */ 1231 tree adjusted_pos = (zero_based) 1232 ? int_const_binop (PLUS_EXPR, pos, integer_one_node) : pos; 1233 1234 if (!prototype_p (fntype)) 1235 return adjusted_pos; 1236 1237 /* Verify that the argument position does not exceed the number 1238 of formal arguments to the function. */ 1239 unsigned nargs = type_num_arguments (fntype); 1240 if (!nargs 1241 || !tree_fits_uhwi_p (adjusted_pos) 1242 || !IN_RANGE (tree_to_uhwi (adjusted_pos), 1, nargs)) 1243 { 1244 if (argno < 1) 1245 warning (OPT_Wattributes, 1246 "%qE attribute argument value %qE exceeds the number " 1247 "of function parameters %u", 1248 atname, pos, nargs); 1249 else 1250 warning (OPT_Wattributes, 1251 "%qE attribute argument %i value %qE exceeds the number " 1252 "of function parameters %u", 1253 atname, argno, pos, nargs); 1254 1255 return NULL_TREE; 1256 } 1257 1258 /* Verify that the type of the referenced formal argument matches 1259 the expected type. */ 1260 unsigned HOST_WIDE_INT ipos = tree_to_uhwi (adjusted_pos); 1261 1262 /* Zero was handled above. */ 1263 gcc_assert (ipos != 0); 1264 1265 if (tree argtype = type_argument_type (fntype, ipos)) 1266 { 1267 /* Accept types that match INTEGRAL_TYPE_P except for bool. */ 1268 if (!INTEGRAL_TYPE_P (argtype) || TREE_CODE (argtype) == BOOLEAN_TYPE) 1269 { 1270 if (argno < 1) 1271 warning (OPT_Wattributes, 1272 "%qE attribute argument value %qE refers to " 1273 "parameter type %qT", 1274 atname, pos, argtype); 1275 else 1276 warning (OPT_Wattributes, 1277 "%qE attribute argument %i value %qE refers to " 1278 "parameter type %qT", 1279 atname, argno, pos, argtype); 1280 1281 return NULL_TREE; 1282 } 1283 1284 return adjusted_pos; 1285 } 1286 1287 /* Argument position exceeding number of parameters was handled above. */ 1288 gcc_unreachable (); 1289 } 1290 1291 /* Handle a "alloc_size" attribute; arguments as in 1292 struct attribute_spec.handler. */ 1293 1294 static tree 1295 d_handle_alloc_size_attribute (tree *node, tree name, tree args, int, 1296 bool *no_add_attrs) 1297 { 1298 tree fntype = *node; 1299 tree rettype = TREE_TYPE (fntype); 1300 if (!POINTER_TYPE_P (rettype)) 1301 { 1302 warning (OPT_Wattributes, 1303 "%qE attribute ignored on a function returning %qT", 1304 name, rettype); 1305 *no_add_attrs = true; 1306 return NULL_TREE; 1307 } 1308 1309 /* The first argument SIZE_ARG is never null. */ 1310 tree size_arg = TREE_VALUE (args); 1311 tree next = TREE_CHAIN (args); 1312 1313 /* NUM_ARG is null when the attribute includes just one argument, or is 1314 explictly set to null if it has been left uninitialized by the caller. */ 1315 tree num_arg = NULL_TREE; 1316 if (next != NULL_TREE) 1317 { 1318 if (TREE_VALUE (next) != TYPE_MIN_VALUE (d_int_type)) 1319 num_arg = TREE_VALUE (next); 1320 1321 next = TREE_CHAIN (next); 1322 } 1323 1324 /* If ZERO_ARG is set and true, arguments positions are treated as 0-based. 1325 Otherwise the default is 1-based. */ 1326 bool zero_based = false; 1327 if (next != NULL_TREE) 1328 zero_based = integer_truep (TREE_VALUE (next)); 1329 1330 /* Update the argument values with the real argument position. */ 1331 if (tree val = positional_argument (fntype, name, size_arg, num_arg ? 1 : 0, 1332 zero_based)) 1333 TREE_VALUE (args) = val; 1334 else 1335 *no_add_attrs = true; 1336 1337 if (num_arg != NULL_TREE) 1338 { 1339 args = TREE_CHAIN (args); 1340 if (tree val = positional_argument (fntype, name, num_arg, 2, zero_based)) 1341 TREE_VALUE (args) = val; 1342 else 1343 *no_add_attrs = true; 1344 } 1345 1346 /* Terminate the original TREE_CHAIN in `args' to remove any remaining 1347 D-specific `alloc_size` arguments. */ 1348 TREE_CHAIN (args) = NULL_TREE; 1349 1350 return NULL_TREE; 1351 } 1352 1353 /* Handle a "cold" and attribute; arguments as in 1354 struct attribute_spec.handler. */ 1355 1356 static tree 1357 d_handle_cold_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) 1358 { 1359 if (TREE_CODE (*node) != FUNCTION_DECL) 1360 { 1361 warning (OPT_Wattributes, "%qE attribute ignored", name); 1362 *no_add_attrs = true; 1363 } 1364 1365 return NULL_TREE; 1366 } 1367 1368 /* Handle a "restrict" attribute; arguments as in 1369 struct attribute_spec.handler. */ 1370 1371 static tree 1372 d_handle_restrict_attribute (tree *node, tree name, tree, int, 1373 bool *no_add_attrs) 1374 { 1375 if (TREE_CODE (*node) == PARM_DECL && POINTER_TYPE_P (TREE_TYPE (*node))) 1376 { 1377 TREE_TYPE (*node) = build_qualified_type (TREE_TYPE (*node), 1378 TYPE_QUAL_RESTRICT); 1379 } 1380 else 1381 { 1382 warning (OPT_Wattributes, "%qE attribute ignored", name); 1383 *no_add_attrs = true; 1384 } 1385 1386 return NULL_TREE; 1387 } 1388 1389 /* Handle a "used" attribute; arguments as in 1390 struct attribute_spec.handler. */ 1391 1392 static tree 1393 d_handle_used_attribute (tree *node, tree name, tree, int, bool *no_add_attrs) 1394 { 1395 if (TREE_CODE (*node) == FUNCTION_DECL 1396 || (VAR_P (*node) && TREE_STATIC (*node)) 1397 || (TREE_CODE (*node) == TYPE_DECL)) 1398 { 1399 TREE_USED (*node) = 1; 1400 DECL_PRESERVE_P (*node) = 1; 1401 if (VAR_P (*node)) 1402 DECL_READ_P (*node) = 1; 1403 } 1404 else 1405 { 1406 warning (OPT_Wattributes, "%qE attribute ignored", name); 1407 *no_add_attrs = true; 1408 } 1409 1410 return NULL_TREE; 1411 } 1412