attribs.c revision 90075
1114402Sru/* Functions dealing with attribute handling, used by most front ends. 2114402Sru Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 3114402Sru 2002 Free Software Foundation, Inc. 4114402Sru 5114402SruThis file is part of GCC. 6114402Sru 7114402SruGCC is free software; you can redistribute it and/or modify it under 8114402Sruthe terms of the GNU General Public License as published by the Free 9114402SruSoftware Foundation; either version 2, or (at your option) any later 10114402Sruversion. 11114402Sru 12114402SruGCC is distributed in the hope that it will be useful, but WITHOUT ANY 13114402SruWARRANTY; without even the implied warranty of MERCHANTABILITY or 14114402SruFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15114402Srufor more details. 16114402Sru 17114402SruYou should have received a copy of the GNU General Public License 18114402Srualong with GCC; see the file COPYING. If not, write to the Free 19151497SruSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 20114402Sru02111-1307, USA. */ 21114402Sru 22114402Sru#include "config.h" 23114402Sru#include "system.h" 24114402Sru#include "tree.h" 25114402Sru#include "flags.h" 26114402Sru#include "toplev.h" 27114402Sru#include "output.h" 28114402Sru#include "rtl.h" 29114402Sru#include "ggc.h" 30114402Sru#include "expr.h" 31114402Sru#include "tm_p.h" 32114402Sru#include "obstack.h" 33114402Sru#include "cpplib.h" 34114402Sru#include "target.h" 35114402Sru 36114402Srustatic void init_attributes PARAMS ((void)); 37114402Sru 38114402Sru/* Table of the tables of attributes (common, format, language, machine) 39114402Sru searched. */ 40114402Srustatic const struct attribute_spec *attribute_tables[4]; 41114402Sru 42114402Srustatic bool attributes_initialized = false; 43114402Sru 44114402Srustatic tree handle_packed_attribute PARAMS ((tree *, tree, tree, int, 45114402Sru bool *)); 46114402Srustatic tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int, 47114402Sru bool *)); 48114402Srustatic tree handle_common_attribute PARAMS ((tree *, tree, tree, int, 49114402Sru bool *)); 50114402Srustatic tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int, 51114402Sru bool *)); 52114402Srustatic tree handle_noinline_attribute PARAMS ((tree *, tree, tree, int, 53114402Sru bool *)); 54114402Srustatic tree handle_used_attribute PARAMS ((tree *, tree, tree, int, 55114402Sru bool *)); 56114402Srustatic tree handle_unused_attribute PARAMS ((tree *, tree, tree, int, 57114402Sru bool *)); 58114402Srustatic tree handle_const_attribute PARAMS ((tree *, tree, tree, int, 59114402Sru bool *)); 60114402Srustatic tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree, 61114402Sru int, bool *)); 62114402Srustatic tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int, 63114402Sru bool *)); 64114402Srustatic tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int, 65114402Sru bool *)); 66114402Srustatic tree handle_mode_attribute PARAMS ((tree *, tree, tree, int, 67114402Sru bool *)); 68114402Srustatic tree handle_section_attribute PARAMS ((tree *, tree, tree, int, 69114402Sru bool *)); 70114402Srustatic tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int, 71114402Sru bool *)); 72114402Srustatic tree handle_weak_attribute PARAMS ((tree *, tree, tree, int, 73114402Sru bool *)); 74114402Srustatic tree handle_alias_attribute PARAMS ((tree *, tree, tree, int, 75114402Sru bool *)); 76114402Srustatic tree handle_no_instrument_function_attribute PARAMS ((tree *, tree, 77114402Sru tree, int, 78114402Sru bool *)); 79114402Srustatic tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int, 80114402Sru bool *)); 81114402Srustatic tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int, 82114402Sru bool *)); 83114402Srustatic tree handle_pure_attribute PARAMS ((tree *, tree, tree, int, 84114402Sru bool *)); 85114402Srustatic tree handle_deprecated_attribute PARAMS ((tree *, tree, tree, int, 86114402Sru bool *)); 87114402Srustatic tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int, 88114402Sru bool *)); 89114402Srustatic tree vector_size_helper PARAMS ((tree, tree)); 90114402Sru 91114402Sru/* Table of machine-independent attributes common to all C-like languages. */ 92114402Srustatic const struct attribute_spec c_common_attribute_table[] = 93114402Sru{ 94114402Sru /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ 95114402Sru { "packed", 0, 0, false, false, false, 96114402Sru handle_packed_attribute }, 97114402Sru { "nocommon", 0, 0, true, false, false, 98114402Sru handle_nocommon_attribute }, 99114402Sru { "common", 0, 0, true, false, false, 100114402Sru handle_common_attribute }, 101114402Sru /* FIXME: logically, noreturn attributes should be listed as 102114402Sru "false, true, true" and apply to function types. But implementing this 103114402Sru would require all the places in the compiler that use TREE_THIS_VOLATILE 104114402Sru on a decl to identify non-returning functions to be located and fixed 105114402Sru to check the function type instead. */ 106114402Sru { "noreturn", 0, 0, true, false, false, 107114402Sru handle_noreturn_attribute }, 108114402Sru { "volatile", 0, 0, true, false, false, 109114402Sru handle_noreturn_attribute }, 110114402Sru { "noinline", 0, 0, true, false, false, 111114402Sru handle_noinline_attribute }, 112114402Sru { "used", 0, 0, true, false, false, 113114402Sru handle_used_attribute }, 114114402Sru { "unused", 0, 0, false, false, false, 115114402Sru handle_unused_attribute }, 116114402Sru /* The same comments as for noreturn attributes apply to const ones. */ 117114402Sru { "const", 0, 0, true, false, false, 118114402Sru handle_const_attribute }, 119114402Sru { "transparent_union", 0, 0, false, false, false, 120114402Sru handle_transparent_union_attribute }, 121114402Sru { "constructor", 0, 0, true, false, false, 122114402Sru handle_constructor_attribute }, 123114402Sru { "destructor", 0, 0, true, false, false, 124114402Sru handle_destructor_attribute }, 125114402Sru { "mode", 1, 1, false, true, false, 126114402Sru handle_mode_attribute }, 127114402Sru { "section", 1, 1, true, false, false, 128114402Sru handle_section_attribute }, 129114402Sru { "aligned", 0, 1, false, false, false, 130114402Sru handle_aligned_attribute }, 131114402Sru { "weak", 0, 0, true, false, false, 132114402Sru handle_weak_attribute }, 133114402Sru { "alias", 1, 1, true, false, false, 134114402Sru handle_alias_attribute }, 135114402Sru { "no_instrument_function", 0, 0, true, false, false, 136114402Sru handle_no_instrument_function_attribute }, 137114402Sru { "malloc", 0, 0, true, false, false, 138114402Sru handle_malloc_attribute }, 139114402Sru { "no_stack_limit", 0, 0, true, false, false, 140114402Sru handle_no_limit_stack_attribute }, 141114402Sru { "pure", 0, 0, true, false, false, 142114402Sru handle_pure_attribute }, 143114402Sru { "deprecated", 0, 0, false, false, false, 144114402Sru handle_deprecated_attribute }, 145114402Sru { "vector_size", 1, 1, false, true, false, 146114402Sru handle_vector_size_attribute }, 147114402Sru { NULL, 0, 0, false, false, false, NULL } 148114402Sru}; 149114402Sru 150114402Sru/* Default empty table of attributes. */ 151114402Srustatic const struct attribute_spec empty_attribute_table[] = 152114402Sru{ 153114402Sru { NULL, 0, 0, false, false, false, NULL } 154114402Sru}; 155114402Sru 156114402Sru/* Table of machine-independent attributes for checking formats, if used. */ 157114402Sruconst struct attribute_spec *format_attribute_table = empty_attribute_table; 158114402Sru 159114402Sru/* Table of machine-independent attributes for a particular language. */ 160114402Sruconst struct attribute_spec *lang_attribute_table = empty_attribute_table; 161114402Sru 162114402Sru/* Flag saying whether common language attributes are to be supported. */ 163114402Sruint lang_attribute_common = 1; 164114402Sru 165114402Sru/* Initialize attribute tables, and make some sanity checks 166114402Sru if --enable-checking. */ 167114402Sru 168114402Srustatic void 169114402Sruinit_attributes () 170114402Sru{ 171114402Sru#ifdef ENABLE_CHECKING 172114402Sru int i; 173114402Sru#endif 174114402Sru 175114402Sru attribute_tables[0] 176114402Sru = lang_attribute_common ? c_common_attribute_table : empty_attribute_table; 177114402Sru attribute_tables[1] = lang_attribute_table; 178114402Sru attribute_tables[2] = format_attribute_table; 179114402Sru attribute_tables[3] = targetm.attribute_table; 180114402Sru 181114402Sru#ifdef ENABLE_CHECKING 182114402Sru /* Make some sanity checks on the attribute tables. */ 183114402Sru for (i = 0; 184114402Sru i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0])); 185114402Sru i++) 186114402Sru { 187114402Sru int j; 188114402Sru 189114402Sru for (j = 0; attribute_tables[i][j].name != NULL; j++) 190114402Sru { 191114402Sru /* The name must not begin and end with __. */ 192114402Sru const char *name = attribute_tables[i][j].name; 193114402Sru int len = strlen (name); 194114402Sru if (name[0] == '_' && name[1] == '_' 195114402Sru && name[len - 1] == '_' && name[len - 2] == '_') 196114402Sru abort (); 197114402Sru /* The minimum and maximum lengths must be consistent. */ 198114402Sru if (attribute_tables[i][j].min_length < 0) 199114402Sru abort (); 200114402Sru if (attribute_tables[i][j].max_length != -1 201114402Sru && (attribute_tables[i][j].max_length 202114402Sru < attribute_tables[i][j].min_length)) 203114402Sru abort (); 204114402Sru /* An attribute cannot require both a DECL and a TYPE. */ 205114402Sru if (attribute_tables[i][j].decl_required 206114402Sru && attribute_tables[i][j].type_required) 207114402Sru abort (); 208114402Sru /* If an attribute requires a function type, in particular 209114402Sru it requires a type. */ 210114402Sru if (attribute_tables[i][j].function_type_required 211114402Sru && !attribute_tables[i][j].type_required) 212114402Sru abort (); 213114402Sru } 214114402Sru } 215114402Sru 216114402Sru /* Check that each name occurs just once in each table. */ 217114402Sru for (i = 0; 218114402Sru i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0])); 219114402Sru i++) 220114402Sru { 221114402Sru int j, k; 222114402Sru for (j = 0; attribute_tables[i][j].name != NULL; j++) 223114402Sru for (k = j + 1; attribute_tables[i][k].name != NULL; k++) 224114402Sru if (!strcmp (attribute_tables[i][j].name, 225114402Sru attribute_tables[i][k].name)) 226114402Sru abort (); 227114402Sru } 228114402Sru /* Check that no name occurs in more than one table. */ 229114402Sru for (i = 0; 230114402Sru i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0])); 231114402Sru i++) 232114402Sru { 233114402Sru int j, k, l; 234114402Sru 235114402Sru for (j = i + 1; 236114402Sru j < ((int) (sizeof (attribute_tables) 237114402Sru / sizeof (attribute_tables[0]))); 238114402Sru j++) 239114402Sru for (k = 0; attribute_tables[i][k].name != NULL; k++) 240114402Sru for (l = 0; attribute_tables[j][l].name != NULL; l++) 241114402Sru if (!strcmp (attribute_tables[i][k].name, 242114402Sru attribute_tables[j][l].name)) 243114402Sru abort (); 244114402Sru } 245114402Sru#endif 246114402Sru 247114402Sru attributes_initialized = true; 248114402Sru} 249114402Sru 250114402Sru/* Process the attributes listed in ATTRIBUTES and install them in *NODE, 251114402Sru which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL, 252114402Sru it should be modified in place; if a TYPE, a copy should be created 253114402Sru unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS. FLAGS gives further 254114402Sru information, in the form of a bitwise OR of flags in enum attribute_flags 255114402Sru from tree.h. Depending on these flags, some attributes may be 256114402Sru returned to be applied at a later stage (for example, to apply 257114402Sru a decl attribute to the declaration rather than to its type). If 258114402Sru ATTR_FLAG_BUILT_IN is not set and *NODE is a DECL, then also consider 259114402Sru whether there might be some default attributes to apply to this DECL; 260114402Sru if so, decl_attributes will be called recursively with those attributes 261114402Sru and ATTR_FLAG_BUILT_IN set. */ 262114402Sru 263114402Srutree 264114402Srudecl_attributes (node, attributes, flags) 265114402Sru tree *node, attributes; 266114402Sru int flags; 267114402Sru{ 268114402Sru tree a; 269114402Sru tree returned_attrs = NULL_TREE; 270114402Sru 271114402Sru if (!attributes_initialized) 272114402Sru init_attributes (); 273114402Sru 274114402Sru (*targetm.insert_attributes) (*node, &attributes); 275114402Sru 276114402Sru if (DECL_P (*node) && TREE_CODE (*node) == FUNCTION_DECL 277114402Sru && !(flags & (int) ATTR_FLAG_BUILT_IN)) 278114402Sru insert_default_attributes (*node); 279114402Sru 280114402Sru for (a = attributes; a; a = TREE_CHAIN (a)) 281114402Sru { 282114402Sru tree name = TREE_PURPOSE (a); 283114402Sru tree args = TREE_VALUE (a); 284114402Sru tree *anode = node; 285114402Sru const struct attribute_spec *spec = NULL; 286114402Sru bool no_add_attrs = 0; 287114402Sru int i; 288114402Sru 289114402Sru for (i = 0; 290114402Sru i < ((int) (sizeof (attribute_tables) 291114402Sru / sizeof (attribute_tables[0]))); 292114402Sru i++) 293114402Sru { 294114402Sru int j; 295114402Sru 296114402Sru for (j = 0; attribute_tables[i][j].name != NULL; j++) 297114402Sru { 298114402Sru if (is_attribute_p (attribute_tables[i][j].name, name)) 299114402Sru { 300114402Sru spec = &attribute_tables[i][j]; 301114402Sru break; 302114402Sru } 303114402Sru } 304114402Sru if (spec != NULL) 305114402Sru break; 306114402Sru } 307114402Sru 308114402Sru if (spec == NULL) 309114402Sru { 310114402Sru warning ("`%s' attribute directive ignored", 311114402Sru IDENTIFIER_POINTER (name)); 312114402Sru continue; 313114402Sru } 314114402Sru else if (list_length (args) < spec->min_length 315114402Sru || (spec->max_length >= 0 316114402Sru && list_length (args) > spec->max_length)) 317114402Sru { 318114402Sru error ("wrong number of arguments specified for `%s' attribute", 319114402Sru IDENTIFIER_POINTER (name)); 320114402Sru continue; 321114402Sru } 322114402Sru 323114402Sru if (spec->decl_required && !DECL_P (*anode)) 324114402Sru { 325114402Sru if (flags & ((int) ATTR_FLAG_DECL_NEXT 326114402Sru | (int) ATTR_FLAG_FUNCTION_NEXT 327114402Sru | (int) ATTR_FLAG_ARRAY_NEXT)) 328114402Sru { 329114402Sru /* Pass on this attribute to be tried again. */ 330114402Sru returned_attrs = tree_cons (name, args, returned_attrs); 331114402Sru continue; 332114402Sru } 333114402Sru else 334114402Sru { 335114402Sru warning ("`%s' attribute does not apply to types", 336114402Sru IDENTIFIER_POINTER (name)); 337114402Sru continue; 338114402Sru } 339114402Sru } 340114402Sru 341114402Sru /* If we require a type, but were passed a decl, set up to make a 342114402Sru new type and update the one in the decl. ATTR_FLAG_TYPE_IN_PLACE 343114402Sru would have applied if we'd been passed a type, but we cannot modify 344114402Sru the decl's type in place here. */ 345114402Sru if (spec->type_required && DECL_P (*anode)) 346114402Sru { 347114402Sru anode = &TREE_TYPE (*anode); 348114402Sru flags &= ~(int) ATTR_FLAG_TYPE_IN_PLACE; 349114402Sru } 350114402Sru 351114402Sru if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE 352114402Sru && TREE_CODE (*anode) != METHOD_TYPE) 353114402Sru { 354114402Sru if (TREE_CODE (*anode) == POINTER_TYPE 355114402Sru && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE 356114402Sru || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE)) 357114402Sru { 358114402Sru if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) 359114402Sru *anode = build_type_copy (*anode); 360114402Sru anode = &TREE_TYPE (*anode); 361114402Sru } 362114402Sru else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT) 363114402Sru { 364114402Sru /* Pass on this attribute to be tried again. */ 365114402Sru returned_attrs = tree_cons (name, args, returned_attrs); 366114402Sru continue; 367114402Sru } 368114402Sru 369114402Sru if (TREE_CODE (*anode) != FUNCTION_TYPE 370114402Sru && TREE_CODE (*anode) != METHOD_TYPE) 371114402Sru { 372114402Sru warning ("`%s' attribute only applies to function types", 373114402Sru IDENTIFIER_POINTER (name)); 374114402Sru continue; 375114402Sru } 376114402Sru } 377114402Sru 378114402Sru if (spec->handler != NULL) 379114402Sru returned_attrs = chainon ((*spec->handler) (anode, name, args, 380114402Sru flags, &no_add_attrs), 381114402Sru returned_attrs); 382114402Sru 383114402Sru /* Layout the decl in case anything changed. */ 384114402Sru if (spec->type_required && DECL_P (*node) 385114402Sru && TREE_CODE (*node) == VAR_DECL) 386114402Sru { 387114402Sru /* Force a recalculation of mode and size. */ 388114402Sru DECL_MODE (*node) = VOIDmode; 389114402Sru DECL_SIZE (*node) = 0; 390114402Sru 391114402Sru layout_decl (*node, 0); 392114402Sru } 393114402Sru 394114402Sru if (!no_add_attrs) 395114402Sru { 396114402Sru tree old_attrs; 397114402Sru tree a; 398114402Sru 399114402Sru if (DECL_P (*anode)) 400114402Sru old_attrs = DECL_ATTRIBUTES (*anode); 401114402Sru else 402114402Sru old_attrs = TYPE_ATTRIBUTES (*anode); 403114402Sru 404114402Sru for (a = lookup_attribute (spec->name, old_attrs); 405114402Sru a != NULL_TREE; 406114402Sru a = lookup_attribute (spec->name, TREE_CHAIN (a))) 407114402Sru { 408114402Sru if (simple_cst_equal (TREE_VALUE (a), args) == 1) 409114402Sru break; 410114402Sru } 411114402Sru 412114402Sru if (a == NULL_TREE) 413114402Sru { 414114402Sru /* This attribute isn't already in the list. */ 415114402Sru if (DECL_P (*anode)) 416114402Sru DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs); 417114402Sru else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE) 418114402Sru TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs); 419114402Sru else 420114402Sru *anode = build_type_attribute_variant (*anode, 421114402Sru tree_cons (name, args, 422114402Sru old_attrs)); 423114402Sru } 424114402Sru } 425114402Sru } 426114402Sru 427114402Sru return returned_attrs; 428114402Sru} 429114402Sru 430114402Sru/* Handle a "packed" attribute; arguments as in 431114402Sru struct attribute_spec.handler. */ 432114402Sru 433114402Srustatic tree 434114402Sruhandle_packed_attribute (node, name, args, flags, no_add_attrs) 435114402Sru tree *node; 436114402Sru tree name; 437114402Sru tree args ATTRIBUTE_UNUSED; 438114402Sru int flags; 439114402Sru bool *no_add_attrs; 440114402Sru{ 441114402Sru tree *type = NULL; 442114402Sru if (DECL_P (*node)) 443114402Sru { 444114402Sru if (TREE_CODE (*node) == TYPE_DECL) 445114402Sru type = &TREE_TYPE (*node); 446114402Sru } 447114402Sru else 448114402Sru type = node; 449114402Sru 450114402Sru if (type) 451114402Sru { 452114402Sru if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) 453114402Sru *type = build_type_copy (*type); 454114402Sru TYPE_PACKED (*type) = 1; 455114402Sru } 456114402Sru else if (TREE_CODE (*node) == FIELD_DECL) 457114402Sru DECL_PACKED (*node) = 1; 458114402Sru /* We can't set DECL_PACKED for a VAR_DECL, because the bit is 459114402Sru used for DECL_REGISTER. It wouldn't mean anything anyway. */ 460114402Sru else 461114402Sru { 462114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 463114402Sru *no_add_attrs = true; 464114402Sru } 465114402Sru 466114402Sru return NULL_TREE; 467114402Sru} 468114402Sru 469114402Sru/* Handle a "nocommon" attribute; arguments as in 470114402Sru struct attribute_spec.handler. */ 471114402Sru 472114402Srustatic tree 473114402Sruhandle_nocommon_attribute (node, name, args, flags, no_add_attrs) 474114402Sru tree *node; 475114402Sru tree name; 476114402Sru tree args ATTRIBUTE_UNUSED; 477114402Sru int flags ATTRIBUTE_UNUSED; 478114402Sru bool *no_add_attrs; 479114402Sru{ 480114402Sru if (TREE_CODE (*node) == VAR_DECL) 481114402Sru DECL_COMMON (*node) = 0; 482114402Sru else 483114402Sru { 484114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 485114402Sru *no_add_attrs = true; 486114402Sru } 487114402Sru 488114402Sru return NULL_TREE; 489114402Sru} 490114402Sru 491114402Sru/* Handle a "common" attribute; arguments as in 492114402Sru struct attribute_spec.handler. */ 493114402Sru 494114402Srustatic tree 495114402Sruhandle_common_attribute (node, name, args, flags, no_add_attrs) 496114402Sru tree *node; 497114402Sru tree name; 498114402Sru tree args ATTRIBUTE_UNUSED; 499114402Sru int flags ATTRIBUTE_UNUSED; 500114402Sru bool *no_add_attrs; 501114402Sru{ 502114402Sru if (TREE_CODE (*node) == VAR_DECL) 503114402Sru DECL_COMMON (*node) = 1; 504114402Sru else 505114402Sru { 506114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 507114402Sru *no_add_attrs = true; 508114402Sru } 509114402Sru 510114402Sru return NULL_TREE; 511114402Sru} 512114402Sru 513114402Sru/* Handle a "noreturn" attribute; arguments as in 514114402Sru struct attribute_spec.handler. */ 515114402Sru 516114402Srustatic tree 517114402Sruhandle_noreturn_attribute (node, name, args, flags, no_add_attrs) 518114402Sru tree *node; 519114402Sru tree name; 520114402Sru tree args ATTRIBUTE_UNUSED; 521114402Sru int flags ATTRIBUTE_UNUSED; 522114402Sru bool *no_add_attrs; 523114402Sru{ 524114402Sru tree type = TREE_TYPE (*node); 525114402Sru 526114402Sru /* See FIXME comment in c_common_attribute_table. */ 527114402Sru if (TREE_CODE (*node) == FUNCTION_DECL) 528114402Sru TREE_THIS_VOLATILE (*node) = 1; 529114402Sru else if (TREE_CODE (type) == POINTER_TYPE 530114402Sru && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) 531114402Sru TREE_TYPE (*node) 532114402Sru = build_pointer_type 533114402Sru (build_type_variant (TREE_TYPE (type), 534114402Sru TREE_READONLY (TREE_TYPE (type)), 1)); 535114402Sru else 536114402Sru { 537114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 538114402Sru *no_add_attrs = true; 539114402Sru } 540114402Sru 541114402Sru return NULL_TREE; 542114402Sru} 543114402Sru 544114402Sru/* Handle a "noinline" attribute; arguments as in 545114402Sru struct attribute_spec.handler. */ 546114402Sru 547114402Srustatic tree 548114402Sruhandle_noinline_attribute (node, name, args, flags, no_add_attrs) 549114402Sru tree *node; 550114402Sru tree name; 551114402Sru tree args ATTRIBUTE_UNUSED; 552114402Sru int flags ATTRIBUTE_UNUSED; 553114402Sru bool *no_add_attrs; 554114402Sru{ 555114402Sru if (TREE_CODE (*node) == FUNCTION_DECL) 556114402Sru DECL_UNINLINABLE (*node) = 1; 557114402Sru else 558114402Sru { 559114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 560114402Sru *no_add_attrs = true; 561114402Sru } 562114402Sru 563114402Sru return NULL_TREE; 564114402Sru} 565114402Sru 566114402Sru/* Handle a "used" attribute; arguments as in 567114402Sru struct attribute_spec.handler. */ 568114402Sru 569114402Srustatic tree 570114402Sruhandle_used_attribute (node, name, args, flags, no_add_attrs) 571114402Sru tree *node; 572114402Sru tree name; 573114402Sru tree args ATTRIBUTE_UNUSED; 574114402Sru int flags ATTRIBUTE_UNUSED; 575114402Sru bool *no_add_attrs; 576114402Sru{ 577114402Sru if (TREE_CODE (*node) == FUNCTION_DECL) 578114402Sru TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (*node)) 579114402Sru = TREE_USED (*node) = 1; 580114402Sru else 581114402Sru { 582114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 583114402Sru *no_add_attrs = true; 584114402Sru } 585114402Sru 586114402Sru return NULL_TREE; 587114402Sru} 588114402Sru 589114402Sru/* Handle a "unused" attribute; arguments as in 590114402Sru struct attribute_spec.handler. */ 591114402Sru 592114402Srustatic tree 593114402Sruhandle_unused_attribute (node, name, args, flags, no_add_attrs) 594114402Sru tree *node; 595114402Sru tree name; 596114402Sru tree args ATTRIBUTE_UNUSED; 597114402Sru int flags; 598114402Sru bool *no_add_attrs; 599114402Sru{ 600114402Sru if (DECL_P (*node)) 601114402Sru { 602114402Sru tree decl = *node; 603114402Sru 604114402Sru if (TREE_CODE (decl) == PARM_DECL 605114402Sru || TREE_CODE (decl) == VAR_DECL 606114402Sru || TREE_CODE (decl) == FUNCTION_DECL 607114402Sru || TREE_CODE (decl) == LABEL_DECL 608114402Sru || TREE_CODE (decl) == TYPE_DECL) 609114402Sru TREE_USED (decl) = 1; 610114402Sru else 611114402Sru { 612114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 613114402Sru *no_add_attrs = true; 614114402Sru } 615114402Sru } 616114402Sru else 617114402Sru { 618114402Sru if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) 619114402Sru *node = build_type_copy (*node); 620114402Sru TREE_USED (*node) = 1; 621114402Sru } 622114402Sru 623114402Sru return NULL_TREE; 624114402Sru} 625114402Sru 626114402Sru/* Handle a "const" attribute; arguments as in 627114402Sru struct attribute_spec.handler. */ 628114402Sru 629114402Srustatic tree 630114402Sruhandle_const_attribute (node, name, args, flags, no_add_attrs) 631114402Sru tree *node; 632114402Sru tree name; 633114402Sru tree args ATTRIBUTE_UNUSED; 634114402Sru int flags ATTRIBUTE_UNUSED; 635114402Sru bool *no_add_attrs; 636114402Sru{ 637114402Sru tree type = TREE_TYPE (*node); 638114402Sru 639114402Sru /* See FIXME comment on noreturn in c_common_attribute_table. */ 640114402Sru if (TREE_CODE (*node) == FUNCTION_DECL) 641114402Sru TREE_READONLY (*node) = 1; 642114402Sru else if (TREE_CODE (type) == POINTER_TYPE 643114402Sru && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) 644114402Sru TREE_TYPE (*node) 645114402Sru = build_pointer_type 646114402Sru (build_type_variant (TREE_TYPE (type), 1, 647114402Sru TREE_THIS_VOLATILE (TREE_TYPE (type)))); 648114402Sru else 649114402Sru { 650114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 651114402Sru *no_add_attrs = true; 652114402Sru } 653114402Sru 654114402Sru return NULL_TREE; 655114402Sru} 656114402Sru 657114402Sru/* Handle a "transparent_union" attribute; arguments as in 658114402Sru struct attribute_spec.handler. */ 659114402Sru 660114402Srustatic tree 661114402Sruhandle_transparent_union_attribute (node, name, args, flags, no_add_attrs) 662114402Sru tree *node; 663114402Sru tree name; 664114402Sru tree args ATTRIBUTE_UNUSED; 665114402Sru int flags; 666114402Sru bool *no_add_attrs; 667114402Sru{ 668114402Sru tree decl = NULL_TREE; 669151497Sru tree *type = NULL; 670114402Sru int is_type = 0; 671114402Sru 672114402Sru if (DECL_P (*node)) 673114402Sru { 674114402Sru decl = *node; 675114402Sru type = &TREE_TYPE (decl); 676114402Sru is_type = TREE_CODE (*node) == TYPE_DECL; 677114402Sru } 678114402Sru else if (TYPE_P (*node)) 679114402Sru type = node, is_type = 1; 680114402Sru 681114402Sru if (is_type 682114402Sru && TREE_CODE (*type) == UNION_TYPE 683114402Sru && (decl == 0 684114402Sru || (TYPE_FIELDS (*type) != 0 685114402Sru && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))))) 686114402Sru { 687114402Sru if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) 688114402Sru *type = build_type_copy (*type); 689114402Sru TYPE_TRANSPARENT_UNION (*type) = 1; 690114402Sru } 691114402Sru else if (decl != 0 && TREE_CODE (decl) == PARM_DECL 692114402Sru && TREE_CODE (*type) == UNION_TYPE 693114402Sru && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type))) 694114402Sru DECL_TRANSPARENT_UNION (decl) = 1; 695114402Sru else 696114402Sru { 697114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 698114402Sru *no_add_attrs = true; 699114402Sru } 700114402Sru 701114402Sru return NULL_TREE; 702114402Sru} 703114402Sru 704114402Sru/* Handle a "constructor" attribute; arguments as in 705114402Sru struct attribute_spec.handler. */ 706114402Sru 707114402Srustatic tree 708114402Sruhandle_constructor_attribute (node, name, args, flags, no_add_attrs) 709114402Sru tree *node; 710114402Sru tree name; 711114402Sru tree args ATTRIBUTE_UNUSED; 712114402Sru int flags ATTRIBUTE_UNUSED; 713114402Sru bool *no_add_attrs; 714114402Sru{ 715114402Sru tree decl = *node; 716114402Sru tree type = TREE_TYPE (decl); 717114402Sru 718114402Sru if (TREE_CODE (decl) == FUNCTION_DECL 719114402Sru && TREE_CODE (type) == FUNCTION_TYPE 720114402Sru && decl_function_context (decl) == 0) 721114402Sru { 722114402Sru DECL_STATIC_CONSTRUCTOR (decl) = 1; 723114402Sru TREE_USED (decl) = 1; 724114402Sru } 725114402Sru else 726114402Sru { 727114402Sru warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 728114402Sru *no_add_attrs = true; 729114402Sru } 730114402Sru 731114402Sru return NULL_TREE; 732114402Sru} 733 734/* Handle a "destructor" attribute; arguments as in 735 struct attribute_spec.handler. */ 736 737static tree 738handle_destructor_attribute (node, name, args, flags, no_add_attrs) 739 tree *node; 740 tree name; 741 tree args ATTRIBUTE_UNUSED; 742 int flags ATTRIBUTE_UNUSED; 743 bool *no_add_attrs; 744{ 745 tree decl = *node; 746 tree type = TREE_TYPE (decl); 747 748 if (TREE_CODE (decl) == FUNCTION_DECL 749 && TREE_CODE (type) == FUNCTION_TYPE 750 && decl_function_context (decl) == 0) 751 { 752 DECL_STATIC_DESTRUCTOR (decl) = 1; 753 TREE_USED (decl) = 1; 754 } 755 else 756 { 757 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 758 *no_add_attrs = true; 759 } 760 761 return NULL_TREE; 762} 763 764/* Handle a "mode" attribute; arguments as in 765 struct attribute_spec.handler. */ 766 767static tree 768handle_mode_attribute (node, name, args, flags, no_add_attrs) 769 tree *node; 770 tree name; 771 tree args; 772 int flags ATTRIBUTE_UNUSED; 773 bool *no_add_attrs; 774{ 775 tree type = *node; 776 777 *no_add_attrs = true; 778 779 if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE) 780 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 781 else 782 { 783 int j; 784 const char *p = IDENTIFIER_POINTER (TREE_VALUE (args)); 785 int len = strlen (p); 786 enum machine_mode mode = VOIDmode; 787 tree typefm; 788 789 if (len > 4 && p[0] == '_' && p[1] == '_' 790 && p[len - 1] == '_' && p[len - 2] == '_') 791 { 792 char *newp = (char *) alloca (len - 1); 793 794 strcpy (newp, &p[2]); 795 newp[len - 4] = '\0'; 796 p = newp; 797 } 798 799 /* Change this type to have a type with the specified mode. 800 First check for the special modes. */ 801 if (! strcmp (p, "byte")) 802 mode = byte_mode; 803 else if (!strcmp (p, "word")) 804 mode = word_mode; 805 else if (! strcmp (p, "pointer")) 806 mode = ptr_mode; 807 else 808 for (j = 0; j < NUM_MACHINE_MODES; j++) 809 if (!strcmp (p, GET_MODE_NAME (j))) 810 mode = (enum machine_mode) j; 811 812 if (mode == VOIDmode) 813 error ("unknown machine mode `%s'", p); 814 else if (0 == (typefm = type_for_mode (mode, 815 TREE_UNSIGNED (type)))) 816 error ("no data type for mode `%s'", p); 817 else 818 *node = typefm; 819 /* No need to layout the type here. The caller should do this. */ 820 } 821 822 return NULL_TREE; 823} 824 825/* Handle a "section" attribute; arguments as in 826 struct attribute_spec.handler. */ 827 828static tree 829handle_section_attribute (node, name, args, flags, no_add_attrs) 830 tree *node; 831 tree name ATTRIBUTE_UNUSED; 832 tree args; 833 int flags ATTRIBUTE_UNUSED; 834 bool *no_add_attrs; 835{ 836 tree decl = *node; 837 838 if (targetm.have_named_sections) 839 { 840 if ((TREE_CODE (decl) == FUNCTION_DECL 841 || TREE_CODE (decl) == VAR_DECL) 842 && TREE_CODE (TREE_VALUE (args)) == STRING_CST) 843 { 844 if (TREE_CODE (decl) == VAR_DECL 845 && current_function_decl != NULL_TREE 846 && ! TREE_STATIC (decl)) 847 { 848 error_with_decl (decl, 849 "section attribute cannot be specified for local variables"); 850 *no_add_attrs = true; 851 } 852 853 /* The decl may have already been given a section attribute 854 from a previous declaration. Ensure they match. */ 855 else if (DECL_SECTION_NAME (decl) != NULL_TREE 856 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), 857 TREE_STRING_POINTER (TREE_VALUE (args))) != 0) 858 { 859 error_with_decl (*node, 860 "section of `%s' conflicts with previous declaration"); 861 *no_add_attrs = true; 862 } 863 else 864 DECL_SECTION_NAME (decl) = TREE_VALUE (args); 865 } 866 else 867 { 868 error_with_decl (*node, 869 "section attribute not allowed for `%s'"); 870 *no_add_attrs = true; 871 } 872 } 873 else 874 { 875 error_with_decl (*node, 876 "section attributes are not supported for this target"); 877 *no_add_attrs = true; 878 } 879 880 return NULL_TREE; 881} 882 883/* Handle a "aligned" attribute; arguments as in 884 struct attribute_spec.handler. */ 885 886static tree 887handle_aligned_attribute (node, name, args, flags, no_add_attrs) 888 tree *node; 889 tree name ATTRIBUTE_UNUSED; 890 tree args; 891 int flags; 892 bool *no_add_attrs; 893{ 894 tree decl = NULL_TREE; 895 tree *type = NULL; 896 int is_type = 0; 897 tree align_expr = (args ? TREE_VALUE (args) 898 : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); 899 int i; 900 901 if (DECL_P (*node)) 902 { 903 decl = *node; 904 type = &TREE_TYPE (decl); 905 is_type = TREE_CODE (*node) == TYPE_DECL; 906 } 907 else if (TYPE_P (*node)) 908 type = node, is_type = 1; 909 910 /* Strip any NOPs of any kind. */ 911 while (TREE_CODE (align_expr) == NOP_EXPR 912 || TREE_CODE (align_expr) == CONVERT_EXPR 913 || TREE_CODE (align_expr) == NON_LVALUE_EXPR) 914 align_expr = TREE_OPERAND (align_expr, 0); 915 916 if (TREE_CODE (align_expr) != INTEGER_CST) 917 { 918 error ("requested alignment is not a constant"); 919 *no_add_attrs = true; 920 } 921 else if ((i = tree_log2 (align_expr)) == -1) 922 { 923 error ("requested alignment is not a power of 2"); 924 *no_add_attrs = true; 925 } 926 else if (i > HOST_BITS_PER_INT - 2) 927 { 928 error ("requested alignment is too large"); 929 *no_add_attrs = true; 930 } 931 else if (is_type) 932 { 933 /* If we have a TYPE_DECL, then copy the type, so that we 934 don't accidentally modify a builtin type. See pushdecl. */ 935 if (decl && TREE_TYPE (decl) != error_mark_node 936 && DECL_ORIGINAL_TYPE (decl) == NULL_TREE) 937 { 938 tree tt = TREE_TYPE (decl); 939 *type = build_type_copy (*type); 940 DECL_ORIGINAL_TYPE (decl) = tt; 941 TYPE_NAME (*type) = decl; 942 TREE_USED (*type) = TREE_USED (decl); 943 TREE_TYPE (decl) = *type; 944 } 945 else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) 946 *type = build_type_copy (*type); 947 948 TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT; 949 TYPE_USER_ALIGN (*type) = 1; 950 } 951 else if (TREE_CODE (decl) != VAR_DECL 952 && TREE_CODE (decl) != FIELD_DECL) 953 { 954 error_with_decl (decl, 955 "alignment may not be specified for `%s'"); 956 *no_add_attrs = true; 957 } 958 else 959 { 960 DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT; 961 DECL_USER_ALIGN (decl) = 1; 962 } 963 964 return NULL_TREE; 965} 966 967/* Handle a "weak" attribute; arguments as in 968 struct attribute_spec.handler. */ 969 970static tree 971handle_weak_attribute (node, name, args, flags, no_add_attrs) 972 tree *node; 973 tree name ATTRIBUTE_UNUSED; 974 tree args ATTRIBUTE_UNUSED; 975 int flags ATTRIBUTE_UNUSED; 976 bool *no_add_attrs ATTRIBUTE_UNUSED; 977{ 978 declare_weak (*node); 979 980 return NULL_TREE; 981} 982 983/* Handle an "alias" attribute; arguments as in 984 struct attribute_spec.handler. */ 985 986static tree 987handle_alias_attribute (node, name, args, flags, no_add_attrs) 988 tree *node; 989 tree name; 990 tree args; 991 int flags ATTRIBUTE_UNUSED; 992 bool *no_add_attrs; 993{ 994 tree decl = *node; 995 996 if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) 997 || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl))) 998 { 999 error_with_decl (decl, 1000 "`%s' defined both normally and as an alias"); 1001 *no_add_attrs = true; 1002 } 1003 else if (decl_function_context (decl) == 0) 1004 { 1005 tree id; 1006 1007 id = TREE_VALUE (args); 1008 if (TREE_CODE (id) != STRING_CST) 1009 { 1010 error ("alias arg not a string"); 1011 *no_add_attrs = true; 1012 return NULL_TREE; 1013 } 1014 id = get_identifier (TREE_STRING_POINTER (id)); 1015 /* This counts as a use of the object pointed to. */ 1016 TREE_USED (id) = 1; 1017 1018 if (TREE_CODE (decl) == FUNCTION_DECL) 1019 DECL_INITIAL (decl) = error_mark_node; 1020 else 1021 DECL_EXTERNAL (decl) = 0; 1022 assemble_alias (decl, id); 1023 } 1024 else 1025 { 1026 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 1027 *no_add_attrs = true; 1028 } 1029 1030 return NULL_TREE; 1031} 1032 1033/* Handle a "no_instrument_function" attribute; arguments as in 1034 struct attribute_spec.handler. */ 1035 1036static tree 1037handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs) 1038 tree *node; 1039 tree name; 1040 tree args ATTRIBUTE_UNUSED; 1041 int flags ATTRIBUTE_UNUSED; 1042 bool *no_add_attrs; 1043{ 1044 tree decl = *node; 1045 1046 if (TREE_CODE (decl) != FUNCTION_DECL) 1047 { 1048 error_with_decl (decl, 1049 "`%s' attribute applies only to functions", 1050 IDENTIFIER_POINTER (name)); 1051 *no_add_attrs = true; 1052 } 1053 else if (DECL_INITIAL (decl)) 1054 { 1055 error_with_decl (decl, 1056 "can't set `%s' attribute after definition", 1057 IDENTIFIER_POINTER (name)); 1058 *no_add_attrs = true; 1059 } 1060 else 1061 DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1; 1062 1063 return NULL_TREE; 1064} 1065 1066/* Handle a "malloc" attribute; arguments as in 1067 struct attribute_spec.handler. */ 1068 1069static tree 1070handle_malloc_attribute (node, name, args, flags, no_add_attrs) 1071 tree *node; 1072 tree name; 1073 tree args ATTRIBUTE_UNUSED; 1074 int flags ATTRIBUTE_UNUSED; 1075 bool *no_add_attrs; 1076{ 1077 if (TREE_CODE (*node) == FUNCTION_DECL) 1078 DECL_IS_MALLOC (*node) = 1; 1079 /* ??? TODO: Support types. */ 1080 else 1081 { 1082 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 1083 *no_add_attrs = true; 1084 } 1085 1086 return NULL_TREE; 1087} 1088 1089/* Handle a "no_limit_stack" attribute; arguments as in 1090 struct attribute_spec.handler. */ 1091 1092static tree 1093handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs) 1094 tree *node; 1095 tree name; 1096 tree args ATTRIBUTE_UNUSED; 1097 int flags ATTRIBUTE_UNUSED; 1098 bool *no_add_attrs; 1099{ 1100 tree decl = *node; 1101 1102 if (TREE_CODE (decl) != FUNCTION_DECL) 1103 { 1104 error_with_decl (decl, 1105 "`%s' attribute applies only to functions", 1106 IDENTIFIER_POINTER (name)); 1107 *no_add_attrs = true; 1108 } 1109 else if (DECL_INITIAL (decl)) 1110 { 1111 error_with_decl (decl, 1112 "can't set `%s' attribute after definition", 1113 IDENTIFIER_POINTER (name)); 1114 *no_add_attrs = true; 1115 } 1116 else 1117 DECL_NO_LIMIT_STACK (decl) = 1; 1118 1119 return NULL_TREE; 1120} 1121 1122/* Handle a "pure" attribute; arguments as in 1123 struct attribute_spec.handler. */ 1124 1125static tree 1126handle_pure_attribute (node, name, args, flags, no_add_attrs) 1127 tree *node; 1128 tree name; 1129 tree args ATTRIBUTE_UNUSED; 1130 int flags ATTRIBUTE_UNUSED; 1131 bool *no_add_attrs; 1132{ 1133 if (TREE_CODE (*node) == FUNCTION_DECL) 1134 DECL_IS_PURE (*node) = 1; 1135 /* ??? TODO: Support types. */ 1136 else 1137 { 1138 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 1139 *no_add_attrs = true; 1140 } 1141 1142 return NULL_TREE; 1143} 1144 1145/* Handle a "deprecated" attribute; arguments as in 1146 struct attribute_spec.handler. */ 1147 1148static tree 1149handle_deprecated_attribute (node, name, args, flags, no_add_attrs) 1150 tree *node; 1151 tree name; 1152 tree args ATTRIBUTE_UNUSED; 1153 int flags; 1154 bool *no_add_attrs; 1155{ 1156 tree type = NULL_TREE; 1157 int warn = 0; 1158 const char *what = NULL; 1159 1160 if (DECL_P (*node)) 1161 { 1162 tree decl = *node; 1163 type = TREE_TYPE (decl); 1164 1165 if (TREE_CODE (decl) == TYPE_DECL 1166 || TREE_CODE (decl) == PARM_DECL 1167 || TREE_CODE (decl) == VAR_DECL 1168 || TREE_CODE (decl) == FUNCTION_DECL 1169 || TREE_CODE (decl) == FIELD_DECL) 1170 TREE_DEPRECATED (decl) = 1; 1171 else 1172 warn = 1; 1173 } 1174 else if (TYPE_P (*node)) 1175 { 1176 if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) 1177 *node = build_type_copy (*node); 1178 TREE_DEPRECATED (*node) = 1; 1179 type = *node; 1180 } 1181 else 1182 warn = 1; 1183 1184 if (warn) 1185 { 1186 *no_add_attrs = true; 1187 if (type && TYPE_NAME (type)) 1188 { 1189 if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) 1190 what = IDENTIFIER_POINTER (TYPE_NAME (*node)); 1191 else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 1192 && DECL_NAME (TYPE_NAME (type))) 1193 what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); 1194 } 1195 if (what) 1196 warning ("`%s' attribute ignored for `%s'", 1197 IDENTIFIER_POINTER (name), what); 1198 else 1199 warning ("`%s' attribute ignored", 1200 IDENTIFIER_POINTER (name)); 1201 } 1202 1203 return NULL_TREE; 1204} 1205 1206/* Handle a "vector_size" attribute; arguments as in 1207 struct attribute_spec.handler. */ 1208 1209static tree 1210handle_vector_size_attribute (node, name, args, flags, no_add_attrs) 1211 tree *node; 1212 tree name; 1213 tree args; 1214 int flags ATTRIBUTE_UNUSED; 1215 bool *no_add_attrs; 1216{ 1217 unsigned HOST_WIDE_INT vecsize, nunits; 1218 enum machine_mode mode, orig_mode, new_mode; 1219 tree type = *node, new_type; 1220 1221 *no_add_attrs = true; 1222 1223 if (! host_integerp (TREE_VALUE (args), 1)) 1224 { 1225 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name)); 1226 return NULL_TREE; 1227 } 1228 1229 /* Get the vector size (in bytes). */ 1230 vecsize = tree_low_cst (TREE_VALUE (args), 1); 1231 1232 /* We need to provide for vector pointers, vector arrays, and 1233 functions returning vectors. For example: 1234 1235 __attribute__((vector_size(16))) short *foo; 1236 1237 In this case, the mode is SI, but the type being modified is 1238 HI, so we need to look further. */ 1239 1240 while (POINTER_TYPE_P (type) 1241 || TREE_CODE (type) == FUNCTION_TYPE 1242 || TREE_CODE (type) == ARRAY_TYPE) 1243 type = TREE_TYPE (type); 1244 1245 /* Get the mode of the type being modified. */ 1246 orig_mode = TYPE_MODE (type); 1247 1248 if (TREE_CODE (type) == RECORD_TYPE 1249 || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT 1250 && GET_MODE_CLASS (orig_mode) != MODE_INT) 1251 || ! host_integerp (TYPE_SIZE_UNIT (type), 1)) 1252 { 1253 error ("invalid vector type for attribute `%s'", 1254 IDENTIFIER_POINTER (name)); 1255 return NULL_TREE; 1256 } 1257 1258 /* Calculate how many units fit in the vector. */ 1259 nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1); 1260 1261 /* Find a suitably sized vector. */ 1262 new_mode = VOIDmode; 1263 for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT 1264 ? MODE_VECTOR_INT 1265 : MODE_VECTOR_FLOAT); 1266 mode != VOIDmode; 1267 mode = GET_MODE_WIDER_MODE (mode)) 1268 if (vecsize == GET_MODE_SIZE (mode) 1269 && nunits == (unsigned HOST_WIDE_INT) GET_MODE_NUNITS (mode)) 1270 { 1271 new_mode = mode; 1272 break; 1273 } 1274 1275 if (new_mode == VOIDmode) 1276 error ("no vector mode with the size and type specified could be found"); 1277 else 1278 { 1279 new_type = type_for_mode (new_mode, TREE_UNSIGNED (type)); 1280 if (!new_type) 1281 error ("no vector mode with the size and type specified could be found"); 1282 else 1283 /* Build back pointers if needed. */ 1284 *node = vector_size_helper (*node, new_type); 1285 } 1286 1287 return NULL_TREE; 1288} 1289 1290/* HACK. GROSS. This is absolutely disgusting. I wish there was a 1291 better way. 1292 1293 If we requested a pointer to a vector, build up the pointers that 1294 we stripped off while looking for the inner type. Similarly for 1295 return values from functions. 1296 1297 The argument "type" is the top of the chain, and "bottom" is the 1298 new type which we will point to. */ 1299 1300static tree 1301vector_size_helper (type, bottom) 1302 tree type, bottom; 1303{ 1304 tree inner, outer; 1305 1306 if (POINTER_TYPE_P (type)) 1307 { 1308 inner = vector_size_helper (TREE_TYPE (type), bottom); 1309 outer = build_pointer_type (inner); 1310 } 1311 else if (TREE_CODE (type) == ARRAY_TYPE) 1312 { 1313 inner = vector_size_helper (TREE_TYPE (type), bottom); 1314 outer = build_array_type (inner, TYPE_VALUES (type)); 1315 } 1316 else if (TREE_CODE (type) == FUNCTION_TYPE) 1317 { 1318 inner = vector_size_helper (TREE_TYPE (type), bottom); 1319 outer = build_function_type (inner, TYPE_VALUES (type)); 1320 } 1321 else 1322 return bottom; 1323 1324 TREE_READONLY (outer) = TREE_READONLY (type); 1325 TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type); 1326 1327 return outer; 1328} 1329 1330/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two 1331 lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE). 1332 1333 The head of the declspec list is stored in DECLSPECS. 1334 The head of the attribute list is stored in PREFIX_ATTRIBUTES. 1335 1336 Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of 1337 the list elements. We drop the containing TREE_LIST nodes and link the 1338 resulting attributes together the way decl_attributes expects them. */ 1339 1340void 1341split_specs_attrs (specs_attrs, declspecs, prefix_attributes) 1342 tree specs_attrs; 1343 tree *declspecs, *prefix_attributes; 1344{ 1345 tree t, s, a, next, specs, attrs; 1346 1347 /* This can happen after an __extension__ in pedantic mode. */ 1348 if (specs_attrs != NULL_TREE 1349 && TREE_CODE (specs_attrs) == INTEGER_CST) 1350 { 1351 *declspecs = NULL_TREE; 1352 *prefix_attributes = NULL_TREE; 1353 return; 1354 } 1355 1356 /* This can happen in c++ (eg: decl: typespec initdecls ';'). */ 1357 if (specs_attrs != NULL_TREE 1358 && TREE_CODE (specs_attrs) != TREE_LIST) 1359 { 1360 *declspecs = specs_attrs; 1361 *prefix_attributes = NULL_TREE; 1362 return; 1363 } 1364 1365 /* Remember to keep the lists in the same order, element-wise. */ 1366 1367 specs = s = NULL_TREE; 1368 attrs = a = NULL_TREE; 1369 for (t = specs_attrs; t; t = next) 1370 { 1371 next = TREE_CHAIN (t); 1372 /* Declspecs have a non-NULL TREE_VALUE. */ 1373 if (TREE_VALUE (t) != NULL_TREE) 1374 { 1375 if (specs == NULL_TREE) 1376 specs = s = t; 1377 else 1378 { 1379 TREE_CHAIN (s) = t; 1380 s = t; 1381 } 1382 } 1383 /* The TREE_PURPOSE may also be empty in the case of 1384 __attribute__(()). */ 1385 else if (TREE_PURPOSE (t) != NULL_TREE) 1386 { 1387 if (attrs == NULL_TREE) 1388 attrs = a = TREE_PURPOSE (t); 1389 else 1390 { 1391 TREE_CHAIN (a) = TREE_PURPOSE (t); 1392 a = TREE_PURPOSE (t); 1393 } 1394 /* More attrs can be linked here, move A to the end. */ 1395 while (TREE_CHAIN (a) != NULL_TREE) 1396 a = TREE_CHAIN (a); 1397 } 1398 } 1399 1400 /* Terminate the lists. */ 1401 if (s != NULL_TREE) 1402 TREE_CHAIN (s) = NULL_TREE; 1403 if (a != NULL_TREE) 1404 TREE_CHAIN (a) = NULL_TREE; 1405 1406 /* All done. */ 1407 *declspecs = specs; 1408 *prefix_attributes = attrs; 1409} 1410 1411/* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes. 1412 This function is used by the parser when a rule will accept attributes 1413 in a particular position, but we don't want to support that just yet. 1414 1415 A warning is issued for every ignored attribute. */ 1416 1417tree 1418strip_attrs (specs_attrs) 1419 tree specs_attrs; 1420{ 1421 tree specs, attrs; 1422 1423 split_specs_attrs (specs_attrs, &specs, &attrs); 1424 1425 while (attrs) 1426 { 1427 warning ("`%s' attribute ignored", 1428 IDENTIFIER_POINTER (TREE_PURPOSE (attrs))); 1429 attrs = TREE_CHAIN (attrs); 1430 } 1431 1432 return specs; 1433} 1434