|
|
1.1 ! root 1: #define NEW_OVERLOAD_SCHEME /* only if you don't care about compatibility */ ! 2: /* Process declarations and variables for C compiler. ! 3: Copyright (C) 1988, 1992 Free Software Foundation, Inc. ! 4: Hacked by Michael Tiemann ([email protected]) ! 5: ! 6: This file is part of GNU CC. ! 7: ! 8: GNU CC is free software; you can redistribute it and/or modify ! 9: it under the terms of the GNU General Public License as published by ! 10: the Free Software Foundation; either version 2, or (at your option) ! 11: any later version. ! 12: ! 13: GNU CC is distributed in the hope that it will be useful, ! 14: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 16: GNU General Public License for more details. ! 17: ! 18: You should have received a copy of the GNU General Public License ! 19: along with GNU CC; see the file COPYING. If not, write to ! 20: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 21: ! 22: ! 23: /* Process declarations and symbol lookup for C front end. ! 24: Also constructs types; the standard scalar types at initialization, ! 25: and structure, union, array and enum types when they are declared. */ ! 26: ! 27: /* ??? not all decl nodes are given the most useful possible ! 28: line numbers. For example, the CONST_DECLs for enum values. */ ! 29: ! 30: #include "config.h" ! 31: #include "tree.h" ! 32: #include "flags.h" ! 33: #include "cp-tree.h" ! 34: #include "cp-lex.h" ! 35: #include "cp-decl.h" ! 36: #include "assert.h" ! 37: ! 38: #define NULL 0 ! 39: ! 40: extern tree grokdeclarator (); ! 41: static void grok_function_init (); ! 42: ! 43: /* A list of virtual function tables we must make sure to write out. */ ! 44: tree pending_vtables; ! 45: ! 46: /* A list of static class variables. This is needed, because a ! 47: static class variable can be declared inside the class without ! 48: an initializer, and then initialized, staticly, outside the class. */ ! 49: tree pending_statics; ! 50: ! 51: extern tree pending_addressable_inlines; ! 52: ! 53: /* Used to help generate temporary names which are unique within ! 54: a function. Reset to 0 by start_function. */ ! 55: ! 56: static int temp_name_counter; ! 57: ! 58: /* Same, but not reset. Local temp variables and global temp variables ! 59: can have the same name. */ ! 60: static int global_temp_name_counter; ! 61: ! 62: /* The (assembler) name of the first globally-visible object output. */ ! 63: extern char * first_global_object_name; ! 64: ! 65: /* C (and C++) language-specific option variables. */ ! 66: ! 67: /* Nonzero means allow type mismatches in conditional expressions; ! 68: just make their values `void'. */ ! 69: ! 70: int flag_cond_mismatch; ! 71: ! 72: /* Nonzero means give `double' the same size as `float'. */ ! 73: ! 74: int flag_short_double; ! 75: ! 76: /* Nonzero means don't recognize the keyword `asm'. */ ! 77: ! 78: int flag_no_asm; ! 79: ! 80: /* Nonzero means don't recognize the non-ANSI builtin functions. */ ! 81: ! 82: int flag_no_builtin; ! 83: ! 84: /* Nonzero means do some things the same way PCC does. */ ! 85: ! 86: int flag_traditional; ! 87: ! 88: /* Nonzero means to treat bitfields as unsigned unless they say `signed'. */ ! 89: ! 90: int flag_signed_bitfields = 1; ! 91: ! 92: /* Nonzero means handle `#ident' directives. 0 means ignore them. */ ! 93: ! 94: int flag_no_ident = 0; ! 95: ! 96: /* Nonzero means handle things in ANSI, instead of GNU fashion. This ! 97: flag should be tested for language behavior that's different between ! 98: ANSI and GNU, but not so horrible as to merit a PEDANTIC label. */ ! 99: ! 100: int flag_ansi = 0; ! 101: ! 102: /* Nonzero means warn about implicit declarations. */ ! 103: ! 104: int warn_implicit = 1; ! 105: ! 106: /* Like `warn_return_type', but this is set by users, whereas ! 107: `warn_return_type' is set by the compiler. */ ! 108: ! 109: int explicit_warn_return_type; ! 110: ! 111: /* Nonzero means give string constants the type `const char *' ! 112: to get extra warnings from them. These warnings will be too numerous ! 113: to be useful, except in thoroughly ANSIfied programs. */ ! 114: ! 115: int warn_write_strings; ! 116: ! 117: /* Nonzero means warn about pointer casts that can drop a type qualifier ! 118: from the pointer target type. */ ! 119: ! 120: int warn_cast_qual; ! 121: ! 122: /* Nonzero means warn about sizeof(function) or addition/subtraction ! 123: of function pointers. */ ! 124: ! 125: int warn_pointer_arith; ! 126: ! 127: /* Nonzero means warn for non-prototype function decls ! 128: or non-prototyped defs without previous prototype. */ ! 129: ! 130: int warn_strict_prototypes; ! 131: ! 132: /* Nonzero means warn for any function def without prototype decl. */ ! 133: ! 134: int warn_missing_prototypes; ! 135: ! 136: /* Warn about *printf or *scanf format/argument anomalies. */ ! 137: ! 138: int warn_format; ! 139: ! 140: /* Warn if a type conversion is done that might have confusing results. */ ! 141: ! 142: int warn_conversion; ! 143: ! 144: /* Warn if adding () is suggested. */ ! 145: ! 146: int warn_parentheses = 1; ! 147: ! 148: /* Non-zero means warn in function declared in derived class has the ! 149: same name as a virtual in the base class, but fails to match the ! 150: type signature of any virtual function in the base class. */ ! 151: int warn_overloaded_virtual; ! 152: ! 153: /* Non-zero means warn when converting between different enumeral types. */ ! 154: int warn_enum_clash; ! 155: ! 156: /* Nonzero means `$' can be in an identifier. ! 157: See cccp.c for reasons why this breaks some obscure ANSI C programs. */ ! 158: ! 159: #ifndef DOLLARS_IN_IDENTIFIERS ! 160: #define DOLLARS_IN_IDENTIFIERS 1 ! 161: #endif ! 162: int dollars_in_ident = DOLLARS_IN_IDENTIFIERS; ! 163: ! 164: /* Nonzero for -no-strict-prototype switch: do not consider empty ! 165: argument prototype to mean function takes no arguments. */ ! 166: ! 167: int strict_prototype = 1; ! 168: int strict_prototypes_lang_c, strict_prototypes_lang_cplusplus = 1; ! 169: ! 170: /* Nonzero means that labels can be used as first-class objects */ ! 171: ! 172: int flag_labels_ok; ! 173: ! 174: /* Non-zero means to collect statistics which might be expensive ! 175: and to print them when we are done. */ ! 176: int flag_detailed_statistics; ! 177: ! 178: /* C++ specific flags. */ ! 179: /* Nonzero for -fall-virtual: make every member function (except ! 180: constructors) lay down in the virtual function table. Calls ! 181: can then either go through the virtual function table or not, ! 182: depending. */ ! 183: ! 184: int flag_all_virtual; ! 185: ! 186: /* Zero means that `this' is a *const. This gives nice behavior in the ! 187: 2.0 world. 1 gives 1.2-compatible behavior. 2 gives Spring behavior. */ ! 188: ! 189: int flag_this_is_variable; ! 190: ! 191: /* Nonzero means memoize our member lookups. */ ! 192: ! 193: int flag_memoize_lookups; int flag_save_memoized_contexts; ! 194: ! 195: /* 3 means write out only virtuals function tables `defined' ! 196: in this implementation file. ! 197: 2 means write out only specific virtual function tables ! 198: and give them (C) public visibility. ! 199: 1 means write out virtual function tables and give them ! 200: (C) public visibility. ! 201: 0 means write out virtual function tables and give them ! 202: (C) static visibility (default). ! 203: -1 means declare virtual function tables extern. */ ! 204: ! 205: int write_virtuals; ! 206: ! 207: /* Nonzero means we should attempt to elide constructors when possible. */ ! 208: ! 209: int flag_elide_constructors; ! 210: ! 211: /* Same, but for inline functions: nonzero means write out debug info ! 212: for inlines. Zero means do not. */ ! 213: ! 214: int flag_inline_debug; ! 215: ! 216: /* Nonzero means recognize and handle exception handling constructs. ! 217: 2 means handle exceptions the way Spring wants them handled. */ ! 218: ! 219: int flag_handle_exceptions; ! 220: ! 221: /* Nonzero means recognize and handle exception handling constructs. ! 222: Use ansi syntax and semantics. WORK IN PROGRESS! ! 223: 2 means handle exceptions the way Spring wants them handled. */ ! 224: ! 225: int flag_ansi_exceptions; ! 226: ! 227: /* Nonzero means that member functions defined in class scope are ! 228: inline by default. */ ! 229: ! 230: int flag_default_inline = 1; ! 231: ! 232: /* Controls whether enums and ints freely convert. ! 233: 1 means with complete freedom. ! 234: 0 means enums can convert to ints, but not vice-versa. */ ! 235: int flag_int_enum_equivalence; ! 236: ! 237: /* Controls whether compiler is operating under LUCID's Cadillac ! 238: system. 1 means yes, 0 means no. */ ! 239: int flag_cadillac; ! 240: ! 241: /* Controls whether compiler generates code to build objects ! 242: that can be collected when they become garbage. */ ! 243: int flag_gc; ! 244: ! 245: /* Controls whether compiler generates 'dossiers' that give ! 246: run-time type information. */ ! 247: int flag_dossier; ! 248: ! 249: /* Nonzero if we wish to output cross-referencing information ! 250: for the GNU class browser. */ ! 251: extern int flag_gnu_xref; ! 252: ! 253: /* Controls how compiler generates code in case there are ! 254: no GNU binutils. */ ! 255: ! 256: #ifndef DBX_DEBUGGING_INFO ! 257: int flag_gnu_binutils = 0; ! 258: #else ! 259: int flag_gnu_binutils = 1; ! 260: #endif ! 261: ! 262: /* Nonzero if compiler can make `reasonable' assumptions about ! 263: references and objects. For example, the compiler must be ! 264: conservative about the following and not assume that `a' is nonnull: ! 265: ! 266: obj &a = g (); ! 267: a.f (2); ! 268: ! 269: In general, it is `reasonable' to assume that for many programs, ! 270: and better code can be generated in that case. */ ! 271: ! 272: int flag_assume_nonnull_objects; ! 273: ! 274: /* Table of language-dependent -f options. ! 275: STRING is the option name. VARIABLE is the address of the variable. ! 276: ON_VALUE is the value to store in VARIABLE ! 277: if `-fSTRING' is seen as an option. ! 278: (If `-fno-STRING' is seen as an option, the opposite value is stored.) */ ! 279: ! 280: static struct { char *string; int *variable; int on_value;} lang_f_options[] = ! 281: { ! 282: {"signed-char", &flag_signed_char, 1}, ! 283: {"unsigned-char", &flag_signed_char, 0}, ! 284: {"signed-bitfields", &flag_signed_bitfields, 1}, ! 285: {"unsigned-bitfields", &flag_signed_bitfields, 0}, ! 286: {"short-enums", &flag_short_enums, 1}, ! 287: {"short-double", &flag_short_double, 1}, ! 288: {"cond-mismatch", &flag_cond_mismatch, 1}, ! 289: {"asm", &flag_no_asm, 0}, ! 290: {"builtin", &flag_no_builtin, 0}, ! 291: {"ident", &flag_no_ident, 0}, ! 292: {"labels-ok", &flag_labels_ok, 1}, ! 293: {"stats", &flag_detailed_statistics, 1}, ! 294: {"this-is-variable", &flag_this_is_variable, 1}, ! 295: {"strict-prototype", &strict_prototypes_lang_cplusplus, 1}, ! 296: {"all-virtual", &flag_all_virtual, 1}, ! 297: {"memoize-lookups", &flag_memoize_lookups, 1}, ! 298: {"elide-constructors", &flag_elide_constructors, 1}, ! 299: {"inline-debug", &flag_inline_debug, 0}, ! 300: {"handle-exceptions", &flag_handle_exceptions, 1}, ! 301: {"ansi-exceptions", &flag_ansi_exceptions, 1}, ! 302: {"spring-exceptions", &flag_handle_exceptions, 2}, ! 303: {"default-inline", &flag_default_inline, 1}, ! 304: {"dollars-in-identifiers", &dollars_in_ident, 1}, ! 305: {"enum-int-equiv", &flag_int_enum_equivalence, 1}, ! 306: {"gc", &flag_gc, 1}, ! 307: {"dossier", &flag_dossier, 1}, ! 308: {"gnu-binutils", &flag_gnu_binutils, 1}, ! 309: {"xref", &flag_gnu_xref, 1}, ! 310: {"nonnull-objects", &flag_assume_nonnull_objects, 1}, ! 311: }; ! 312: ! 313: /* Decode the string P as a language-specific option. ! 314: Return 1 if it is recognized (and handle it); ! 315: return 0 if not recognized. */ ! 316: ! 317: int ! 318: lang_decode_option (p) ! 319: char *p; ! 320: { ! 321: if (!strcmp (p, "-ftraditional") || !strcmp (p, "-traditional")) ! 322: flag_traditional = 1, dollars_in_ident = 1, flag_writable_strings = 1, ! 323: flag_this_is_variable = 1; ! 324: /* The +e options are for cfront compatability. */ ! 325: else if (p[0] == '+' && p[1] == 'e') ! 326: { ! 327: int old_write_virtuals = write_virtuals; ! 328: if (p[2] == '1') ! 329: write_virtuals = 1; ! 330: else if (p[2] == '0') ! 331: write_virtuals = -1; ! 332: else if (p[2] == '2') ! 333: write_virtuals = 2; ! 334: else error ("invalid +e option"); ! 335: if (old_write_virtuals != 0 ! 336: && write_virtuals != old_write_virtuals) ! 337: error ("conflicting +e options given"); ! 338: } ! 339: else if (p[0] == '-' && p[1] == 'f') ! 340: { ! 341: /* Some kind of -f option. ! 342: P's value is the option sans `-f'. ! 343: Search for it in the table of options. */ ! 344: int found = 0, j; ! 345: ! 346: p += 2; ! 347: /* Try special -f options. */ ! 348: ! 349: if (!strcmp (p, "save-memoized")) ! 350: { ! 351: flag_memoize_lookups = 1; ! 352: flag_save_memoized_contexts = 1; ! 353: found = 1; ! 354: } ! 355: if (!strcmp (p, "no-save-memoized")) ! 356: { ! 357: flag_memoize_lookups = 0; ! 358: flag_save_memoized_contexts = 0; ! 359: found = 1; ! 360: } ! 361: else if (!strcmp (p, "SOS")) ! 362: { ! 363: flag_all_virtual = 2; ! 364: found = 1; ! 365: } ! 366: else if (!strcmp (p, "no-SOS")) ! 367: { ! 368: flag_all_virtual = 0; ! 369: found = 1; ! 370: } ! 371: else if (! strncmp (p, "cadillac", 8)) ! 372: { ! 373: flag_cadillac = atoi (p+9); ! 374: found = 1; ! 375: } ! 376: else if (! strncmp (p, "no-cadillac", 11)) ! 377: { ! 378: flag_cadillac = 0; ! 379: found = 1; ! 380: } ! 381: else if (! strcmp (p, "gc")) ! 382: { ! 383: flag_gc = 1; ! 384: /* This must come along for the ride. */ ! 385: flag_dossier = 1; ! 386: found = 1; ! 387: } ! 388: else if (! strcmp (p, "no-gc")) ! 389: { ! 390: flag_gc = 0; ! 391: /* This must come along for the ride. */ ! 392: flag_dossier = 0; ! 393: found = 1; ! 394: } ! 395: else for (j = 0; ! 396: !found && j < sizeof (lang_f_options) / sizeof (lang_f_options[0]); ! 397: j++) ! 398: { ! 399: if (!strcmp (p, lang_f_options[j].string)) ! 400: { ! 401: *lang_f_options[j].variable = lang_f_options[j].on_value; ! 402: /* A goto here would be cleaner, ! 403: but breaks the vax pcc. */ ! 404: found = 1; ! 405: } ! 406: if (p[0] == 'n' && p[1] == 'o' && p[2] == '-' ! 407: && ! strcmp (p+3, lang_f_options[j].string)) ! 408: { ! 409: *lang_f_options[j].variable = ! lang_f_options[j].on_value; ! 410: found = 1; ! 411: } ! 412: } ! 413: return found; ! 414: } ! 415: else if (p[0] == '-' && p[1] == 'W') ! 416: { ! 417: int setting = 1; ! 418: ! 419: /* The -W options control the warning behavior of the compiler. */ ! 420: p += 2; ! 421: ! 422: if (p[0] == 'n' && p[1] == 'o' && p[2] == '-') ! 423: setting = 0, p += 3; ! 424: ! 425: if (!strcmp (p, "implicit")) ! 426: warn_implicit = setting; ! 427: else if (!strcmp (p, "return-type")) ! 428: explicit_warn_return_type = setting; ! 429: else if (!strcmp (p, "write-strings")) ! 430: warn_write_strings = setting; ! 431: else if (!strcmp (p, "cast-qual")) ! 432: warn_cast_qual = setting; ! 433: else if (!strcmp (p, "pointer-arith")) ! 434: warn_pointer_arith = setting; ! 435: else if (!strcmp (p, "strict-prototypes")) ! 436: warn_strict_prototypes = setting; ! 437: else if (!strcmp (p, "missing-prototypes")) ! 438: warn_missing_prototypes = setting; ! 439: else if (!strcmp (p, "format")) ! 440: warn_format = setting; ! 441: else if (!strcmp (p, "conversion")) ! 442: warn_conversion = setting; ! 443: else if (!strcmp (p, "parentheses")) ! 444: warn_parentheses = setting; ! 445: else if (!strcmp (p, "comment")) ! 446: ; /* cpp handles this one. */ ! 447: else if (!strcmp (p, "comments")) ! 448: ; /* cpp handles this one. */ ! 449: else if (!strcmp (p, "trigraphs")) ! 450: ; /* cpp handles this one. */ ! 451: else if (!strcmp (p, "all")) ! 452: { ! 453: extra_warnings = setting; ! 454: warn_implicit = setting; ! 455: explicit_warn_return_type = setting; ! 456: warn_unused = setting; ! 457: warn_switch = setting; ! 458: warn_uninitialized = setting; ! 459: #if 0 ! 460: warn_enum_clash = setting; ! 461: #endif ! 462: } ! 463: ! 464: else if (!strcmp (p, "overloaded-virtual")) ! 465: warn_overloaded_virtual = setting; ! 466: else if (!strcmp (p, "enum-clash")) ! 467: warn_enum_clash = setting; ! 468: else return 0; ! 469: } ! 470: else if (!strcmp (p, "-ansi")) ! 471: flag_no_asm = 1, dollars_in_ident = 0, flag_ansi = 1; ! 472: else ! 473: return 0; ! 474: ! 475: return 1; ! 476: } ! 477: ! 478: /* Incorporate `const' and `volatile' qualifiers for member functions. ! 479: FUNCTION is a TYPE_DECL or a FUNCTION_DECL. ! 480: QUALS is a list of qualifiers. */ ! 481: tree ! 482: grok_method_quals (ctype, function, quals) ! 483: tree ctype, function, quals; ! 484: { ! 485: tree fntype = TREE_TYPE (function); ! 486: tree raises = TYPE_RAISES_EXCEPTIONS (fntype); ! 487: ! 488: do ! 489: { ! 490: extern tree ridpointers[]; ! 491: ! 492: if (TREE_VALUE (quals) == ridpointers[(int)RID_CONST]) ! 493: { ! 494: if (TYPE_READONLY (ctype)) ! 495: error ("duplicate `%s' %s", ! 496: IDENTIFIER_POINTER (TREE_VALUE (quals)), ! 497: (TREE_CODE (function) == FUNCTION_DECL ! 498: ? "for member function" : "in type declaration")); ! 499: ctype = build_type_variant (ctype, 1, TYPE_VOLATILE (ctype)); ! 500: build_pointer_type (ctype); ! 501: } ! 502: else if (TREE_VALUE (quals) == ridpointers[(int)RID_VOLATILE]) ! 503: { ! 504: if (TYPE_VOLATILE (ctype)) ! 505: error ("duplicate `%s' %s", ! 506: IDENTIFIER_POINTER (TREE_VALUE (quals)), ! 507: (TREE_CODE (function) == FUNCTION_DECL ! 508: ? "for member function" : "in type declaration")); ! 509: ctype = build_type_variant (ctype, TYPE_READONLY (ctype), 1); ! 510: build_pointer_type (ctype); ! 511: } ! 512: else ! 513: abort (); ! 514: quals = TREE_CHAIN (quals); ! 515: } ! 516: while (quals); ! 517: fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype), ! 518: (TREE_CODE (fntype) == METHOD_TYPE ! 519: ? TREE_CHAIN (TYPE_ARG_TYPES (fntype)) ! 520: : TYPE_ARG_TYPES (fntype))); ! 521: if (raises) ! 522: fntype = build_exception_variant (ctype, fntype, raises); ! 523: ! 524: TREE_TYPE (function) = fntype; ! 525: return ctype; ! 526: } ! 527: ! 528: /* Classes overload their constituent function names automatically. ! 529: When a function name is declared in a record structure, ! 530: its name is changed to it overloaded name. Since names for ! 531: constructors and destructors can conflict, we place a leading ! 532: '$' for destructors. ! 533: ! 534: CNAME is the name of the class we are grokking for. ! 535: ! 536: FUNCTION is a FUNCTION_DECL. It was created by `grokdeclarator'. ! 537: ! 538: FLAGS contains bits saying what's special about today's ! 539: arguments. 1 == DESTRUCTOR. 2 == OPERATOR. ! 540: ! 541: If FUNCTION is a destructor, then we must add the `auto-delete' field ! 542: as a second parameter. There is some hair associated with the fact ! 543: that we must "declare" this variable in the manner consistent with the ! 544: way the rest of the arguements were declared. ! 545: ! 546: If FUNCTION is a constructor, and we are doing SOS hacks for dynamic ! 547: classes, then the second hidden argument is the virtual function table ! 548: pointer with which to initialize the object. ! 549: ! 550: QUALS are the qualifiers for the this pointer. */ ! 551: ! 552: void ! 553: grokclassfn (ctype, cname, function, flags, quals) ! 554: tree ctype, cname, function; ! 555: enum overload_flags flags; ! 556: tree quals; ! 557: { ! 558: tree fn_name = DECL_NAME (function); ! 559: tree arg_types; ! 560: tree parm; ! 561: char *name; ! 562: ! 563: if (fn_name == NULL_TREE) ! 564: { ! 565: error ("name missing for member function"); ! 566: fn_name = get_identifier ("<anonymous>"); ! 567: DECL_NAME (function) = fn_name; ! 568: } ! 569: ! 570: if (quals) ! 571: ctype = grok_method_quals (ctype, function, quals); ! 572: ! 573: arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); ! 574: if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) ! 575: { ! 576: /* Must add the class instance variable up front. */ ! 577: /* Right now we just make this a pointer. But later ! 578: we may wish to make it special. */ ! 579: tree type = TREE_VALUE (arg_types); ! 580: ! 581: if (flags == DTOR_FLAG) ! 582: type = TYPE_MAIN_VARIANT (type); ! 583: else if (DECL_CONSTRUCTOR_P (function)) ! 584: { ! 585: if (TYPE_DYNAMIC (ctype)) ! 586: { ! 587: parm = build_decl (PARM_DECL, get_identifier (AUTO_VTABLE_NAME), TYPE_POINTER_TO (ptr_type_node)); ! 588: TREE_USED (parm) = 1; ! 589: TREE_READONLY (parm) = 1; ! 590: DECL_ARG_TYPE (parm) = TYPE_POINTER_TO (ptr_type_node); ! 591: TREE_CHAIN (parm) = last_function_parms; ! 592: last_function_parms = parm; ! 593: } ! 594: ! 595: if (TYPE_USES_VIRTUAL_BASECLASSES (ctype)) ! 596: { ! 597: DECL_CONSTRUCTOR_FOR_VBASE_P (function) = 1; ! 598: /* In this case we need "in-charge" flag saying whether ! 599: this constructor is responsible for initialization ! 600: of virtual baseclasses or not. */ ! 601: parm = build_decl (PARM_DECL, in_charge_identifier, integer_type_node); ! 602: DECL_ARG_TYPE (parm) = integer_type_node; ! 603: TREE_REGDECL (parm) = 1; ! 604: TREE_CHAIN (parm) = last_function_parms; ! 605: last_function_parms = parm; ! 606: } ! 607: } ! 608: ! 609: parm = build_decl (PARM_DECL, this_identifier, type); ! 610: DECL_ARG_TYPE (parm) = type; ! 611: /* We can make this a register, so long as we don't ! 612: accidently complain if someone tries to take its address. */ ! 613: TREE_REGDECL (parm) = 1; ! 614: if (flags != DTOR_FLAG ! 615: && (!flag_this_is_variable || TYPE_READONLY (type))) ! 616: TREE_READONLY (parm) = 1; ! 617: TREE_CHAIN (parm) = last_function_parms; ! 618: last_function_parms = parm; ! 619: } ! 620: ! 621: if (flags == DTOR_FLAG) ! 622: { ! 623: char *buf, *dbuf; ! 624: tree const_integer_type = build_type_variant (integer_type_node, 1, 0); ! 625: int len = sizeof (DESTRUCTOR_DECL_PREFIX)-1; ! 626: ! 627: arg_types = hash_tree_chain (const_integer_type, void_list_node); ! 628: /* Build the overload name. It will look like e.g. 7Example. */ ! 629: dbuf = build_overload_name (IDENTIFIER_TYPE_VALUE (cname), 1, 1); ! 630: buf = (char *)alloca (strlen (dbuf) + sizeof (DESTRUCTOR_DECL_PREFIX)); ! 631: bcopy (DESTRUCTOR_DECL_PREFIX, buf, len); ! 632: buf[len] = '\0'; ! 633: strcat (buf, dbuf); ! 634: DECL_ASSEMBLER_NAME (function) = get_identifier (buf); ! 635: parm = build_decl (PARM_DECL, in_charge_identifier, const_integer_type); ! 636: TREE_USED (parm) = 1; ! 637: TREE_READONLY (parm) = 1; ! 638: DECL_ARG_TYPE (parm) = const_integer_type; ! 639: /* This is the same chain as DECL_ARGUMENTS (...). */ ! 640: TREE_CHAIN (last_function_parms) = parm; ! 641: ! 642: TREE_TYPE (function) = build_cplus_method_type (ctype, void_type_node, arg_types); ! 643: TYPE_HAS_DESTRUCTOR (ctype) = 1; ! 644: } ! 645: else if (flags == WRAPPER_FLAG || flags == ANTI_WRAPPER_FLAG) ! 646: { ! 647: name = (char *)alloca (sizeof (WRAPPER_DECL_FORMAT) ! 648: + sizeof (ANTI_WRAPPER_DECL_FORMAT) ! 649: + IDENTIFIER_LENGTH (cname) + 2); ! 650: sprintf (name, ! 651: flags == WRAPPER_FLAG ? WRAPPER_DECL_FORMAT : ANTI_WRAPPER_DECL_FORMAT, ! 652: IDENTIFIER_POINTER (cname)); ! 653: DECL_ASSEMBLER_NAME (function) = build_decl_overload (name, arg_types, 1); ! 654: sprintf (name, flags == WRAPPER_FLAG ? WRAPPER_NAME_FORMAT : ANTI_WRAPPER_NAME_FORMAT, ! 655: IDENTIFIER_POINTER (cname)); ! 656: DECL_NAME (function) = fn_name = get_identifier (name); ! 657: } ! 658: else if (flags == WRAPPER_PRED_FLAG) ! 659: { ! 660: name = (char *)alloca (sizeof (WRAPPER_PRED_DECL_FORMAT) ! 661: + sizeof (WRAPPER_PRED_NAME_FORMAT) ! 662: + IDENTIFIER_LENGTH (cname) + 2); ! 663: sprintf (name, WRAPPER_PRED_DECL_FORMAT, IDENTIFIER_POINTER (cname)); ! 664: DECL_ASSEMBLER_NAME (function) = build_decl_overload (name, arg_types, 1); ! 665: sprintf (name, WRAPPER_PRED_NAME_FORMAT, IDENTIFIER_POINTER (cname)); ! 666: DECL_NAME (function) = fn_name = get_identifier (name); ! 667: } ! 668: else ! 669: { ! 670: tree these_arg_types; ! 671: ! 672: if (TYPE_DYNAMIC (ctype) && DECL_CONSTRUCTOR_P (function)) ! 673: { ! 674: arg_types = hash_tree_chain (build_pointer_type (ptr_type_node), ! 675: TREE_CHAIN (arg_types)); ! 676: TREE_TYPE (function) ! 677: = build_cplus_method_type (ctype, TREE_TYPE (TREE_TYPE (function)), arg_types); ! 678: arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); ! 679: } ! 680: ! 681: if (DECL_CONSTRUCTOR_FOR_VBASE_P (function)) ! 682: { ! 683: arg_types = hash_tree_chain (integer_type_node, TREE_CHAIN (arg_types)); ! 684: TREE_TYPE (function) ! 685: = build_cplus_method_type (ctype, TREE_TYPE (TREE_TYPE (function)), arg_types); ! 686: arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); ! 687: } ! 688: ! 689: these_arg_types = arg_types; ! 690: ! 691: if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE) ! 692: /* Only true for static member functions. */ ! 693: these_arg_types = hash_tree_chain (TYPE_POINTER_TO (ctype), arg_types); ! 694: ! 695: DECL_ASSEMBLER_NAME (function) ! 696: = build_decl_overload (IDENTIFIER_POINTER (fn_name), ! 697: these_arg_types, ! 698: 1 + DECL_CONSTRUCTOR_P (function)); ! 699: #if 0 ! 700: if (flags == TYPENAME_FLAG) ! 701: /* Not exactly an IDENTIFIER_TYPE_VALUE. */ ! 702: TREE_TYPE (DECL_ASSEMBLER_NAME (function)) = TREE_TYPE (fn_name); ! 703: #endif ! 704: } ! 705: ! 706: DECL_ARGUMENTS (function) = last_function_parms; ! 707: /* First approximations. */ ! 708: DECL_CONTEXT (function) = ctype; ! 709: DECL_CLASS_CONTEXT (function) = ctype; ! 710: } ! 711: ! 712: /* Sanity check: report error if this function FUNCTION is not ! 713: really a member of the class (CTYPE) it is supposed to belong to. ! 714: CNAME and FLAGS are the same here as they are for grokclassfn above. */ ! 715: ! 716: void ! 717: check_classfn (ctype, cname, function, flags) ! 718: tree ctype, cname, function; ! 719: int flags; ! 720: { ! 721: tree fn_name = DECL_NAME (function); ! 722: tree fndecl; ! 723: int need_quotes = 0; ! 724: char *err_name; ! 725: tree method_vec = CLASSTYPE_METHOD_VEC (ctype); ! 726: tree *methods = 0; ! 727: tree *end = 0; ! 728: ! 729: if (method_vec != 0) ! 730: { ! 731: methods = &TREE_VEC_ELT (method_vec, 0); ! 732: end = TREE_VEC_END (method_vec); ! 733: ! 734: /* First suss out ctors and dtors. */ ! 735: if (*methods && fn_name == cname) ! 736: goto got_it; ! 737: ! 738: while (++methods != end) ! 739: { ! 740: if (fn_name == DECL_NAME (*methods)) ! 741: { ! 742: got_it: ! 743: fndecl = *methods; ! 744: while (fndecl) ! 745: { ! 746: if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl)) ! 747: return; ! 748: fndecl = DECL_CHAIN (fndecl); ! 749: } ! 750: break; /* loser */ ! 751: } ! 752: } ! 753: } ! 754: ! 755: if (fn_name == ansi_opname[TYPE_EXPR]) ! 756: { ! 757: if (TYPE_HAS_CONVERSION (ctype)) ! 758: err_name = "such type conversion operator"; ! 759: } ! 760: else if (IDENTIFIER_OPNAME_P (fn_name)) ! 761: { ! 762: err_name = (char *)alloca (1024); ! 763: sprintf (err_name, "`operator %s'", operator_name_string (fn_name)); ! 764: } ! 765: else if (flags == WRAPPER_FLAG) ! 766: err_name = "wrapper"; ! 767: else if (flags == WRAPPER_PRED_FLAG) ! 768: err_name = "wrapper predicate"; ! 769: else ! 770: { ! 771: err_name = IDENTIFIER_POINTER (fn_name); ! 772: need_quotes = 1; ! 773: } ! 774: ! 775: if (methods != end) ! 776: if (need_quotes) ! 777: error ("argument list for `%s' does not match any in class", err_name); ! 778: else ! 779: error ("argument list for %s does not match any in class", err_name); ! 780: else ! 781: { ! 782: methods = 0; ! 783: if (need_quotes) ! 784: error ("no `%s' member function declared in class", err_name); ! 785: else ! 786: error ("no %s declared in class", err_name); ! 787: } ! 788: ! 789: /* If we did not find the method in the class, add it to ! 790: avoid spurious errors. */ ! 791: add_method (ctype, methods, function); ! 792: } ! 793: ! 794: /* Process the specs, declarator (NULL if omitted) and width (NULL if omitted) ! 795: of a structure component, returning a FIELD_DECL node. ! 796: QUALS is a list of type qualifiers for this decl (such as for declaring ! 797: const member functions). ! 798: ! 799: This is done during the parsing of the struct declaration. ! 800: The FIELD_DECL nodes are chained together and the lot of them ! 801: are ultimately passed to `build_struct' to make the RECORD_TYPE node. ! 802: ! 803: C++: ! 804: ! 805: If class A defines that certain functions in class B are friends, then ! 806: the way I have set things up, it is B who is interested in permission ! 807: granted by A. However, it is in A's context that these declarations ! 808: are parsed. By returning a void_type_node, class A does not attempt ! 809: to incorporate the declarations of the friends within its structure. ! 810: ! 811: DO NOT MAKE ANY CHANGES TO THIS CODE WITHOUT MAKING CORRESPONDING ! 812: CHANGES TO CODE IN `start_method'. */ ! 813: ! 814: tree ! 815: grokfield (declarator, declspecs, raises, init, asmspec_tree) ! 816: tree declarator, declspecs, raises, init; ! 817: tree asmspec_tree; ! 818: { ! 819: register tree value; ! 820: char *asmspec = 0; ! 821: ! 822: /* Convert () initializers to = initializers. */ ! 823: if (init == NULL_TREE && declarator != NULL_TREE ! 824: && TREE_CODE (declarator) == CALL_EXPR ! 825: && TREE_OPERAND (declarator, 0) ! 826: && (TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE ! 827: || TREE_CODE (TREE_OPERAND (declarator, 0)) == SCOPE_REF) ! 828: && parmlist_is_exprlist (TREE_OPERAND (declarator, 1))) ! 829: { ! 830: init = TREE_OPERAND (declarator, 1); ! 831: declarator = TREE_OPERAND (declarator, 0); ! 832: } ! 833: ! 834: value = grokdeclarator (declarator, declspecs, FIELD, init != 0, raises); ! 835: if (! value) ! 836: return NULL_TREE; /* friends went bad. */ ! 837: ! 838: /* Pass friendly classes back. */ ! 839: if (TREE_CODE (value) == VOID_TYPE) ! 840: return void_type_node; ! 841: ! 842: if (DECL_NAME (value) != NULL_TREE ! 843: && IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_' ! 844: && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr")) ! 845: error_with_decl (value, "member `%s' conflicts with virtual function table field name"); ! 846: ! 847: /* Stash away type declarations. */ ! 848: if (TREE_CODE (value) == TYPE_DECL) ! 849: { ! 850: TREE_NONLOCAL (value) = 1; ! 851: CLASSTYPE_LOCAL_TYPEDECLS (current_class_type) = 1; ! 852: pushdecl_class_level (value); ! 853: return value; ! 854: } ! 855: ! 856: if (DECL_IN_AGGR_P (value)) ! 857: { ! 858: error_with_decl (value, "`%s' is already defined in aggregate scope"); ! 859: return void_type_node; ! 860: } ! 861: ! 862: if (flag_cadillac) ! 863: cadillac_start_decl (value); ! 864: ! 865: if (asmspec_tree) ! 866: asmspec = TREE_STRING_POINTER (asmspec_tree); ! 867: ! 868: if (init != 0) ! 869: { ! 870: if (TREE_CODE (value) == FUNCTION_DECL) ! 871: { ! 872: grok_function_init (value, init); ! 873: init = NULL_TREE; ! 874: } ! 875: else if (pedantic) ! 876: { ! 877: error ("fields cannot have initializers"); ! 878: init = NULL_TREE; ! 879: } ! 880: else ! 881: { ! 882: /* We allow initializers to become parameters to base initializers. */ ! 883: if (TREE_CODE (init) == TREE_LIST) ! 884: { ! 885: if (TREE_CHAIN (init) == NULL_TREE) ! 886: init = TREE_VALUE (init); ! 887: else ! 888: init = digest_init (TREE_TYPE (value), init, 0, 1, 0, ! 889: "field declaration"); ! 890: } ! 891: ! 892: if (TREE_CODE (init) == CONST_DECL) ! 893: init = DECL_INITIAL (init); ! 894: else if (TREE_READONLY_DECL_P (init)) ! 895: init = decl_constant_value (init); ! 896: else if (TREE_CODE (init) == CONSTRUCTOR) ! 897: init = digest_init (TREE_TYPE (value), init, 0); ! 898: assert (TREE_PERMANENT (init)); ! 899: if (init == error_mark_node) ! 900: /* We must make this look different than `error_mark_node' ! 901: because `decl_const_value' would mis-interpret it ! 902: as only meaning that this VAR_DECL is defined. */ ! 903: init = build1 (NOP_EXPR, TREE_TYPE (value), init); ! 904: else if (! TREE_CONSTANT (init)) ! 905: { ! 906: /* We can allow references to things that are effectively ! 907: static, since references are initialized with the address. */ ! 908: if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE ! 909: || (TREE_STATIC (init) == 0 ! 910: && (TREE_CODE_CLASS (TREE_CODE (init)) != 'd' ! 911: || TREE_EXTERNAL (init) == 0))) ! 912: { ! 913: error ("field initializer is not constant"); ! 914: init = error_mark_node; ! 915: } ! 916: } ! 917: } ! 918: } ! 919: ! 920: /* The corresponding pop_obstacks is in finish_decl. */ ! 921: push_obstacks_nochange (); ! 922: ! 923: if (TREE_CODE (value) == VAR_DECL) ! 924: { ! 925: /* We cannot call pushdecl here, because that would ! 926: fill in the value of our TREE_CHAIN. Instead, we ! 927: modify finish_decl to do the right thing, namely, to ! 928: put this decl out straight away. */ ! 929: if (TREE_STATIC (value)) ! 930: { ! 931: if (asmspec == 0) ! 932: { ! 933: tree name; ! 934: char *buf, *buf2; ! 935: ! 936: #ifdef NEW_OVERLOAD_SCHEME ! 937: buf2 = build_overload_name (current_class_type, 1, 1); ! 938: #else ! 939: if (IDENTIFIER_TEMPLATE (current_class_name)) ! 940: buf2 = build_overload_name (current_class_type, 1, 1); ! 941: else ! 942: buf2 = current_class_name; ! 943: #endif ! 944: buf = (char *)alloca (IDENTIFIER_LENGTH (DECL_NAME (value)) ! 945: + sizeof (STATIC_NAME_FORMAT) ! 946: + strlen (buf2)); ! 947: sprintf (buf, STATIC_NAME_FORMAT, buf2, ! 948: IDENTIFIER_POINTER (DECL_NAME (value))); ! 949: name = get_identifier (buf); ! 950: TREE_PUBLIC (value) = 1; ! 951: DECL_INITIAL (value) = error_mark_node; ! 952: DECL_ASSEMBLER_NAME (value) = name; ! 953: } ! 954: pending_statics = perm_tree_cons (NULL_TREE, value, pending_statics); ! 955: ! 956: /* Static consts need not be initialized in the class definition. */ ! 957: if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (value))) ! 958: { ! 959: static int explanation = 0; ! 960: ! 961: error ("initializer invalid for static member with constructor"); ! 962: if (explanation++ == 0) ! 963: error ("(you really want to initialize it separately)"); ! 964: init = 0; ! 965: } ! 966: /* Force the compiler to know when an uninitialized static ! 967: const member is being used. */ ! 968: if (TYPE_READONLY (value) && init == 0) ! 969: TREE_USED (value) = 1; ! 970: } ! 971: DECL_INITIAL (value) = init; ! 972: DECL_IN_AGGR_P (value) = 1; ! 973: ! 974: finish_decl (value, init, asmspec_tree, 1); ! 975: pushdecl_class_level (value); ! 976: return value; ! 977: } ! 978: if (TREE_CODE (value) == FIELD_DECL) ! 979: { ! 980: if (asmspec) ! 981: DECL_ASSEMBLER_NAME (value) = get_identifier (asmspec); ! 982: if (DECL_INITIAL (value) == error_mark_node) ! 983: init = error_mark_node; ! 984: finish_decl (value, init, asmspec_tree, 1); ! 985: DECL_INITIAL (value) = init; ! 986: DECL_IN_AGGR_P (value) = 1; ! 987: return value; ! 988: } ! 989: if (TREE_CODE (value) == FUNCTION_DECL) ! 990: { ! 991: /* grokdeclarator defers setting this. */ ! 992: TREE_PUBLIC (value) = 1; ! 993: if (DECL_CHAIN (value) != NULL_TREE) ! 994: { ! 995: /* Need a fresh node here so that we don't get circularity ! 996: when we link these together. */ ! 997: value = copy_node (value); ! 998: /* When does this happen? */ ! 999: assert (init == NULL_TREE); ! 1000: } ! 1001: finish_decl (value, init, asmspec_tree, 1); ! 1002: ! 1003: /* Pass friends back this way. */ ! 1004: if (DECL_FRIEND_P (value)) ! 1005: return void_type_node; ! 1006: ! 1007: DECL_IN_AGGR_P (value) = 1; ! 1008: return value; ! 1009: } ! 1010: abort (); ! 1011: /* NOTREACHED */ ! 1012: return NULL_TREE; ! 1013: } ! 1014: ! 1015: /* Like `grokfield', but for bitfields. ! 1016: WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node. */ ! 1017: ! 1018: tree ! 1019: grokbitfield (declarator, declspecs, width) ! 1020: tree declarator, declspecs, width; ! 1021: { ! 1022: register tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL_TREE); ! 1023: ! 1024: if (! value) return NULL_TREE; /* friends went bad. */ ! 1025: ! 1026: /* Pass friendly classes back. */ ! 1027: if (TREE_CODE (value) == VOID_TYPE) ! 1028: return void_type_node; ! 1029: ! 1030: if (TREE_CODE (value) == TYPE_DECL) ! 1031: { ! 1032: error_with_decl (value, "cannot declare `%s' to be a bitfield type"); ! 1033: return NULL_TREE; ! 1034: } ! 1035: ! 1036: if (DECL_IN_AGGR_P (value)) ! 1037: { ! 1038: error_with_decl (value, "`%s' is already defined in aggregate scope"); ! 1039: return void_type_node; ! 1040: } ! 1041: ! 1042: GNU_xref_member (current_class_name, value); ! 1043: ! 1044: if (TREE_STATIC (value)) ! 1045: { ! 1046: error_with_decl (value, "static member `%s' cannot be a bitfield"); ! 1047: return NULL_TREE; ! 1048: } ! 1049: finish_decl (value, NULL_TREE, NULL_TREE, 0); ! 1050: /* detect invalid field size. */ ! 1051: if (TREE_CODE (width) == CONST_DECL) ! 1052: width = DECL_INITIAL (width); ! 1053: else if (TREE_READONLY_DECL_P (width)) ! 1054: width = decl_constant_value (width); ! 1055: ! 1056: if (TREE_CODE (width) != INTEGER_CST) ! 1057: { ! 1058: error_with_decl (value, "structure field `%s' width not an integer constant"); ! 1059: DECL_INITIAL (value) = NULL; ! 1060: } ! 1061: else ! 1062: { ! 1063: DECL_INITIAL (value) = width; ! 1064: DECL_BIT_FIELD (value) = 1; ! 1065: } ! 1066: DECL_IN_AGGR_P (value) = 1; ! 1067: return value; ! 1068: } ! 1069: ! 1070: /* Like GROKFIELD, except that the declarator has been ! 1071: buried in DECLSPECS. Find the declarator, and ! 1072: return something that looks like it came from ! 1073: GROKFIELD. */ ! 1074: tree ! 1075: groktypefield (declspecs, parmlist) ! 1076: tree declspecs; ! 1077: tree parmlist; ! 1078: { ! 1079: tree spec = declspecs; ! 1080: tree prev = NULL_TREE; ! 1081: ! 1082: tree type_id = NULL_TREE; ! 1083: tree quals = NULL_TREE; ! 1084: tree lengths = NULL_TREE; ! 1085: tree decl = NULL_TREE; ! 1086: ! 1087: while (spec) ! 1088: { ! 1089: register tree id = TREE_VALUE (spec); ! 1090: ! 1091: if (TREE_CODE (spec) != TREE_LIST) ! 1092: /* Certain parse errors slip through. For example, ! 1093: `int class ();' is not caught by the parser. Try ! 1094: weakly to recover here. */ ! 1095: return NULL_TREE; ! 1096: ! 1097: if (TREE_CODE (id) == TYPE_DECL ! 1098: || (TREE_CODE (id) == IDENTIFIER_NODE && TREE_TYPE (id))) ! 1099: { ! 1100: /* We have a constructor/destructor or ! 1101: conversion operator. Use it. */ ! 1102: if (prev) ! 1103: TREE_CHAIN (prev) = TREE_CHAIN (spec); ! 1104: else ! 1105: declspecs = TREE_CHAIN (spec); ! 1106: ! 1107: type_id = id; ! 1108: goto found; ! 1109: } ! 1110: prev = spec; ! 1111: spec = TREE_CHAIN (spec); ! 1112: } ! 1113: ! 1114: /* Nope, we have a conversion operator to a scalar type. */ ! 1115: spec = declspecs; ! 1116: while (spec) ! 1117: { ! 1118: tree id = TREE_VALUE (spec); ! 1119: ! 1120: if (TREE_CODE (id) == IDENTIFIER_NODE) ! 1121: { ! 1122: if (id == ridpointers[(int)RID_INT] ! 1123: || id == ridpointers[(int)RID_DOUBLE] ! 1124: || id == ridpointers[(int)RID_FLOAT]) ! 1125: { ! 1126: if (type_id) ! 1127: error ("extra `%s' ignored", ! 1128: IDENTIFIER_POINTER (id)); ! 1129: else ! 1130: type_id = id; ! 1131: } ! 1132: else if (id == ridpointers[(int)RID_LONG] ! 1133: || id == ridpointers[(int)RID_SHORT] ! 1134: || id == ridpointers[(int)RID_CHAR]) ! 1135: { ! 1136: lengths = tree_cons (NULL_TREE, id, lengths); ! 1137: } ! 1138: else if (id == ridpointers[(int)RID_VOID]) ! 1139: { ! 1140: if (type_id) ! 1141: error ("spurious `void' type ignored"); ! 1142: else ! 1143: error ("conversion to `void' type invalid"); ! 1144: } ! 1145: else if (id == ridpointers[(int)RID_AUTO] ! 1146: || id == ridpointers[(int)RID_REGISTER] ! 1147: || id == ridpointers[(int)RID_TYPEDEF] ! 1148: || id == ridpointers[(int)RID_CONST] ! 1149: || id == ridpointers[(int)RID_VOLATILE]) ! 1150: { ! 1151: error ("type specifier `%s' used invalidly", ! 1152: IDENTIFIER_POINTER (id)); ! 1153: } ! 1154: else if (id == ridpointers[(int)RID_FRIEND] ! 1155: || id == ridpointers[(int)RID_VIRTUAL] ! 1156: || id == ridpointers[(int)RID_INLINE] ! 1157: || id == ridpointers[(int)RID_UNSIGNED] ! 1158: || id == ridpointers[(int)RID_SIGNED] ! 1159: || id == ridpointers[(int)RID_STATIC] ! 1160: || id == ridpointers[(int)RID_EXTERN]) ! 1161: { ! 1162: quals = tree_cons (NULL_TREE, id, quals); ! 1163: } ! 1164: else ! 1165: { ! 1166: /* Happens when we have a global typedef ! 1167: and a class-local member function with ! 1168: the same name. */ ! 1169: type_id = id; ! 1170: goto found; ! 1171: } ! 1172: } ! 1173: else if (TREE_CODE (id) == RECORD_TYPE) ! 1174: { ! 1175: type_id = TYPE_NAME (id); ! 1176: if (TREE_CODE (type_id) == TYPE_DECL) ! 1177: type_id = DECL_NAME (type_id); ! 1178: if (type_id == NULL_TREE) ! 1179: error ("identifier for aggregate type conversion omitted"); ! 1180: } ! 1181: else ! 1182: assert (0); ! 1183: spec = TREE_CHAIN (spec); ! 1184: } ! 1185: ! 1186: if (type_id) ! 1187: { ! 1188: declspecs = chainon (lengths, quals); ! 1189: } ! 1190: else if (lengths) ! 1191: { ! 1192: if (TREE_CHAIN (lengths)) ! 1193: error ("multiple length specifiers"); ! 1194: type_id = ridpointers[(int)RID_INT]; ! 1195: declspecs = chainon (lengths, quals); ! 1196: } ! 1197: else if (quals) ! 1198: { ! 1199: error ("no type given, defaulting to `operator int ...'"); ! 1200: type_id = ridpointers[(int)RID_INT]; ! 1201: declspecs = quals; ! 1202: } ! 1203: else return NULL_TREE; ! 1204: found: ! 1205: decl = grokdeclarator (build_parse_node (CALL_EXPR, type_id, parmlist, NULL_TREE), ! 1206: declspecs, FIELD, 0, NULL_TREE); ! 1207: if (decl == NULL_TREE) ! 1208: return NULL_TREE; ! 1209: ! 1210: if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CHAIN (decl) != NULL_TREE) ! 1211: { ! 1212: /* Need a fresh node here so that we don't get circularity ! 1213: when we link these together. */ ! 1214: decl = copy_node (decl); ! 1215: } ! 1216: ! 1217: if (decl == void_type_node ! 1218: || (TREE_CODE (decl) == FUNCTION_DECL ! 1219: && TREE_CODE (TREE_TYPE (decl)) != METHOD_TYPE)) ! 1220: /* bunch of friends. */ ! 1221: return decl; ! 1222: ! 1223: if (DECL_IN_AGGR_P (decl)) ! 1224: { ! 1225: error_with_decl (decl, "`%s' already defined in aggregate scope"); ! 1226: return void_type_node; ! 1227: } ! 1228: ! 1229: finish_decl (decl, NULL_TREE, NULL_TREE, 0); ! 1230: ! 1231: /* If this declaration is common to another declaration ! 1232: complain about such redundancy, and return NULL_TREE ! 1233: so that we don't build a circular list. */ ! 1234: if (DECL_CHAIN (decl)) ! 1235: { ! 1236: error_with_decl (decl, "function `%s' declared twice in aggregate"); ! 1237: return NULL_TREE; ! 1238: } ! 1239: DECL_IN_AGGR_P (decl) = 1; ! 1240: return decl; ! 1241: } ! 1242: ! 1243: /* The precedence rules of this grammar (or any other deterministic LALR ! 1244: grammar, for that matter), place the CALL_EXPR somewhere where we ! 1245: may not want it. The solution is to grab the first CALL_EXPR we see, ! 1246: pretend that that is the one that belongs to the parameter list of ! 1247: the type conversion function, and leave everything else alone. ! 1248: We pull it out in place. ! 1249: ! 1250: CALL_REQUIRED is non-zero if we should complain if a CALL_EXPR ! 1251: does not appear in DECL. */ ! 1252: tree ! 1253: grokoptypename (decl, call_required) ! 1254: tree decl; ! 1255: int call_required; ! 1256: { ! 1257: tree tmp, last; ! 1258: ! 1259: assert (TREE_CODE (decl) == TYPE_EXPR); ! 1260: ! 1261: tmp = TREE_OPERAND (decl, 0); ! 1262: last = NULL_TREE; ! 1263: ! 1264: while (tmp) ! 1265: { ! 1266: switch (TREE_CODE (tmp)) ! 1267: { ! 1268: case CALL_EXPR: ! 1269: { ! 1270: tree parms = TREE_OPERAND (tmp, 1); ! 1271: ! 1272: if (last) ! 1273: TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0); ! 1274: else ! 1275: TREE_OPERAND (decl, 0) = TREE_OPERAND (tmp, 0); ! 1276: if (parms ! 1277: && TREE_CODE (TREE_VALUE (parms)) == TREE_LIST) ! 1278: TREE_VALUE (parms) ! 1279: = grokdeclarator (TREE_VALUE (TREE_VALUE (parms)), ! 1280: TREE_PURPOSE (TREE_VALUE (parms)), ! 1281: TYPENAME, 0, NULL_TREE); ! 1282: if (parms) ! 1283: { ! 1284: if (TREE_VALUE (parms) != void_type_node) ! 1285: error ("operator <typename> requires empty parameter list"); ! 1286: else ! 1287: /* Canonicalize parameter lists. */ ! 1288: TREE_OPERAND (tmp, 1) = void_list_node; ! 1289: } ! 1290: ! 1291: last = grokdeclarator (TREE_OPERAND (decl, 0), ! 1292: TREE_TYPE (decl), ! 1293: TYPENAME, 0, NULL_TREE); ! 1294: TREE_OPERAND (tmp, 0) = build_typename_overload (last); ! 1295: TREE_TYPE (TREE_OPERAND (tmp, 0)) = last; ! 1296: return tmp; ! 1297: } ! 1298: ! 1299: case INDIRECT_REF: ! 1300: case ADDR_EXPR: ! 1301: case ARRAY_REF: ! 1302: break; ! 1303: ! 1304: case SCOPE_REF: ! 1305: /* This is legal when declaring a conversion to ! 1306: something of type pointer-to-member. */ ! 1307: if (TREE_CODE (TREE_OPERAND (tmp, 1)) == INDIRECT_REF) ! 1308: { ! 1309: tmp = TREE_OPERAND (tmp, 1); ! 1310: } ! 1311: else ! 1312: { ! 1313: #if 0 ! 1314: /* We may need to do this if grokdeclarator cannot handle this. */ ! 1315: error ("type `member of class %s' invalid return type", ! 1316: TYPE_NAME_STRING (TREE_OPERAND (tmp, 0))); ! 1317: TREE_OPERAND (tmp, 1) = build_parse_node (INDIRECT_REF, TREE_OPERAND (tmp, 1)); ! 1318: #endif ! 1319: tmp = TREE_OPERAND (tmp, 1); ! 1320: } ! 1321: break; ! 1322: ! 1323: default: ! 1324: assert (0); ! 1325: } ! 1326: last = tmp; ! 1327: tmp = TREE_OPERAND (tmp, 0); ! 1328: } ! 1329: ! 1330: if (call_required) ! 1331: error ("operator <typename> construct requires parameter list"); ! 1332: ! 1333: last = grokdeclarator (TREE_OPERAND (decl, 0), ! 1334: TREE_TYPE (decl), ! 1335: TYPENAME, 0, NULL_TREE); ! 1336: tmp = build_parse_node (CALL_EXPR, build_typename_overload (last), ! 1337: void_list_node, NULL_TREE); ! 1338: TREE_TYPE (TREE_OPERAND (tmp, 0)) = last; ! 1339: return tmp; ! 1340: } ! 1341: ! 1342: /* When a function is declared with an initialializer, ! 1343: do the right thing. Currently, there are two possibilities: ! 1344: ! 1345: class B ! 1346: { ! 1347: public: ! 1348: // initialization possibility #1. ! 1349: virtual void f () = 0; ! 1350: int g (); ! 1351: }; ! 1352: ! 1353: class D1 : B ! 1354: { ! 1355: public: ! 1356: int d1; ! 1357: // error, no f (); ! 1358: }; ! 1359: ! 1360: class D2 : B ! 1361: { ! 1362: public: ! 1363: int d2; ! 1364: void f (); ! 1365: }; ! 1366: ! 1367: class D3 : B ! 1368: { ! 1369: public: ! 1370: int d3; ! 1371: // initialization possibility #2 ! 1372: void f () = B::f; ! 1373: }; ! 1374: ! 1375: */ ! 1376: ! 1377: static void ! 1378: grok_function_init (decl, init) ! 1379: tree decl; ! 1380: tree init; ! 1381: { ! 1382: /* An initializer for a function tells how this function should ! 1383: be inherited. */ ! 1384: tree type = TREE_TYPE (decl); ! 1385: extern tree abort_fndecl; ! 1386: ! 1387: if (TREE_CODE (type) == FUNCTION_TYPE) ! 1388: error_with_decl (decl, "initializer specified for non-member function `%s'"); ! 1389: else if (DECL_VINDEX (decl) == NULL_TREE) ! 1390: error_with_decl (decl, "initializer specified for non-virtual method `%s'"); ! 1391: else if (integer_zerop (init)) ! 1392: { ! 1393: /* Mark this function as being "defined". */ ! 1394: DECL_INITIAL (decl) = error_mark_node; ! 1395: /* Give this node rtl from `abort'. */ ! 1396: DECL_RTL (decl) = DECL_RTL (abort_fndecl); ! 1397: DECL_ABSTRACT_VIRTUAL_P (decl) = 1; ! 1398: } ! 1399: else if (TREE_CODE (init) == OFFSET_REF ! 1400: && TREE_OPERAND (init, 0) == NULL_TREE ! 1401: && TREE_CODE (TREE_TYPE (init)) == METHOD_TYPE) ! 1402: { ! 1403: tree basetype = DECL_CLASS_CONTEXT (init); ! 1404: tree basefn = TREE_OPERAND (init, 1); ! 1405: if (TREE_CODE (basefn) != FUNCTION_DECL) ! 1406: error_with_decl (decl, "non-method initializer invalid for method `%s'"); ! 1407: else if (! BINFO_OFFSET_ZEROP (TYPE_BINFO (DECL_CLASS_CONTEXT (basefn)))) ! 1408: sorry ("base member function from other than first base class"); ! 1409: else ! 1410: { ! 1411: tree binfo = get_binfo (basetype, TYPE_METHOD_BASETYPE (type), 1); ! 1412: if (binfo == error_mark_node) ! 1413: ; ! 1414: else if (binfo == 0) ! 1415: error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (init)), ! 1416: TYPE_METHOD_BASETYPE (type)); ! 1417: else ! 1418: { ! 1419: /* Mark this function as being defined, ! 1420: and give it new rtl. */ ! 1421: DECL_INITIAL (decl) = error_mark_node; ! 1422: DECL_RTL (decl) = DECL_RTL (basefn); ! 1423: } ! 1424: } ! 1425: } ! 1426: else ! 1427: error_with_decl (decl, "invalid initializer for virtual method `%s'"); ! 1428: } ! 1429: ! 1430: /* When we get a declaration of the form ! 1431: ! 1432: type cname::fname ... ! 1433: ! 1434: the node for `cname::fname' gets built here in a special way. ! 1435: Namely, we push into `cname's scope. When this declaration is ! 1436: processed, we pop back out. */ ! 1437: tree ! 1438: build_push_scope (cname, name) ! 1439: tree cname; ! 1440: tree name; ! 1441: { ! 1442: extern int current_class_depth; ! 1443: tree ctype, rval; ! 1444: ! 1445: if (cname == error_mark_node) ! 1446: return error_mark_node; ! 1447: ! 1448: ctype = IDENTIFIER_TYPE_VALUE (cname); ! 1449: ! 1450: if (ctype == NULL_TREE || ! IS_AGGR_TYPE (ctype)) ! 1451: { ! 1452: error ("`%s' not defined as aggregate type", IDENTIFIER_POINTER (cname)); ! 1453: return name; ! 1454: } ! 1455: ! 1456: rval = build_parse_node (SCOPE_REF, cname, name); ! 1457: ! 1458: /* Don't need to push the scope here, but we do need to return ! 1459: a SCOPE_REF for something like ! 1460: ! 1461: class foo { typedef int bar (foo::*foo_fn)(void); }; */ ! 1462: if (ctype == current_class_type) ! 1463: return rval; ! 1464: ! 1465: pushclass (ctype, 3); ! 1466: TREE_COMPLEXITY (rval) = current_class_depth; ! 1467: return rval; ! 1468: } ! 1469: ! 1470: /* CONSTRUCTOR_NAME: ! 1471: Return the name for the constructor (or destructor) for the specified ! 1472: class. Argument can be RECORD_TYPE, TYPE_DECL, or IDENTIFIER_NODE. */ ! 1473: tree ! 1474: constructor_name (thing) ! 1475: tree thing; ! 1476: { ! 1477: tree t; ! 1478: if (TREE_CODE (thing) == UNINSTANTIATED_P_TYPE) ! 1479: return DECL_NAME (UPT_TEMPLATE (thing)); ! 1480: if (TREE_CODE (thing) == RECORD_TYPE || TREE_CODE (thing) == UNION_TYPE) ! 1481: thing = TYPE_NAME (thing); ! 1482: if (TREE_CODE (thing) == TYPE_DECL ! 1483: || (TREE_CODE (thing) == TEMPLATE_DECL ! 1484: && DECL_TEMPLATE_IS_CLASS (thing))) ! 1485: thing = DECL_NAME (thing); ! 1486: assert (TREE_CODE (thing) == IDENTIFIER_NODE); ! 1487: t = IDENTIFIER_TEMPLATE (thing); ! 1488: if (!t) ! 1489: return thing; ! 1490: t = TREE_PURPOSE (t); ! 1491: return DECL_NAME (t); ! 1492: } ! 1493: ! 1494: /* Cache the value of this class's main virtual function table pointer ! 1495: in a register variable. This will save one indirection if a ! 1496: more than one virtual function call is made this function. */ ! 1497: void ! 1498: setup_vtbl_ptr () ! 1499: { ! 1500: extern struct rtx_def *base_init_insns; ! 1501: ! 1502: if (base_init_insns == 0 ! 1503: && DECL_CONSTRUCTOR_P (current_function_decl)) ! 1504: emit_base_init (current_class_type, 0); ! 1505: ! 1506: if ((flag_this_is_variable & 1) == 0 ! 1507: && optimize ! 1508: && current_class_type ! 1509: && CLASSTYPE_VSIZE (current_class_type) ! 1510: && ! DECL_STATIC_FUNCTION_P (current_function_decl)) ! 1511: { ! 1512: tree vfield = build_vfield_ref (C_C_D, current_class_type); ! 1513: current_vtable_decl = CLASSTYPE_VTBL_PTR (current_class_type); ! 1514: DECL_RTL (current_vtable_decl) = 0; ! 1515: DECL_INITIAL (current_vtable_decl) = error_mark_node; ! 1516: /* Have to cast the initializer, since it may have come from a ! 1517: more base class then we ascribe CURRENT_VTABLE_DECL to be. */ ! 1518: finish_decl (current_vtable_decl, convert_force (TREE_TYPE (current_vtable_decl), vfield), 0, 0); ! 1519: current_vtable_decl = build_indirect_ref (current_vtable_decl, 0); ! 1520: } ! 1521: else ! 1522: current_vtable_decl = NULL_TREE; ! 1523: } ! 1524: ! 1525: /* Record the existence of an addressable inline function. */ ! 1526: void ! 1527: mark_inline_for_output (decl) ! 1528: tree decl; ! 1529: { ! 1530: if (DECL_PENDING_INLINE_INFO (decl) != 0 ! 1531: && ! DECL_PENDING_INLINE_INFO (decl)->deja_vu) ! 1532: { ! 1533: struct pending_inline *t = pending_inlines; ! 1534: assert (DECL_SAVED_INSNS (decl) == 0); ! 1535: while (t) ! 1536: { ! 1537: if (t == DECL_PENDING_INLINE_INFO (decl)) ! 1538: break; ! 1539: t = t->next; ! 1540: } ! 1541: if (t == 0) ! 1542: { ! 1543: t = DECL_PENDING_INLINE_INFO (decl); ! 1544: t->next = pending_inlines; ! 1545: pending_inlines = t; ! 1546: } ! 1547: DECL_PENDING_INLINE_INFO (decl) = 0; ! 1548: } ! 1549: pending_addressable_inlines = perm_tree_cons (NULL_TREE, decl, ! 1550: pending_addressable_inlines); ! 1551: } ! 1552: ! 1553: void ! 1554: clear_temp_name () ! 1555: { ! 1556: temp_name_counter = 0; ! 1557: } ! 1558: ! 1559: /* Hand off a unique name which can be used for variable we don't really ! 1560: want to know about anyway, for example, the anonymous variables which ! 1561: are needed to make references work. Declare this thing so we can use it. ! 1562: The variable created will be of type TYPE. ! 1563: ! 1564: STATICP is nonzero if this variable should be static. */ ! 1565: ! 1566: tree ! 1567: get_temp_name (type, staticp) ! 1568: tree type; ! 1569: int staticp; ! 1570: { ! 1571: char buf[sizeof (AUTO_TEMP_FORMAT) + 20]; ! 1572: tree decl; ! 1573: int temp = 0; ! 1574: int toplev = global_bindings_p (); ! 1575: ! 1576: push_obstacks_nochange (); ! 1577: if (toplev || staticp) ! 1578: { ! 1579: end_temporary_allocation (); ! 1580: sprintf (buf, AUTO_TEMP_FORMAT, global_temp_name_counter++); ! 1581: decl = pushdecl_top_level (build_decl (VAR_DECL, get_identifier (buf), type)); ! 1582: } ! 1583: else ! 1584: { ! 1585: sprintf (buf, AUTO_TEMP_FORMAT, temp_name_counter++); ! 1586: decl = pushdecl (build_decl (VAR_DECL, get_identifier (buf), type)); ! 1587: } ! 1588: TREE_USED (decl) = 1; ! 1589: TREE_STATIC (decl) = staticp; ! 1590: ! 1591: /* If this is a local variable, then lay out its rtl now. ! 1592: Otherwise, callers of this function are responsible for dealing ! 1593: with this variable's rtl. */ ! 1594: if (! toplev) ! 1595: { ! 1596: expand_decl (decl); ! 1597: expand_decl_init (decl); ! 1598: } ! 1599: pop_obstacks (); ! 1600: ! 1601: return decl; ! 1602: } ! 1603: ! 1604: /* Get a variable which we can use for multiple assignments. ! 1605: It is not entered into current_binding_level, because ! 1606: that breaks things when it comes time to do final cleanups ! 1607: (which take place "outside" the binding contour of the function). */ ! 1608: tree ! 1609: get_temp_regvar (type, init) ! 1610: tree type, init; ! 1611: { ! 1612: static char buf[sizeof (AUTO_TEMP_FORMAT) + 20] = { '_' }; ! 1613: tree decl; ! 1614: ! 1615: sprintf (buf+1, AUTO_TEMP_FORMAT, temp_name_counter++); ! 1616: decl = build_decl (VAR_DECL, get_identifier (buf), type); ! 1617: TREE_USED (decl) = 1; ! 1618: TREE_REGDECL (decl) = 1; ! 1619: ! 1620: if (init) ! 1621: store_init_value (decl, init); ! 1622: ! 1623: /* We can expand these without fear, since they cannot need ! 1624: constructors or destructors. */ ! 1625: expand_decl (decl); ! 1626: expand_decl_init (decl); ! 1627: ! 1628: if (type_needs_gc_entry (type)) ! 1629: DECL_GC_OFFSET (decl) = size_int (++current_function_obstack_index); ! 1630: ! 1631: return decl; ! 1632: } ! 1633: ! 1634: /* Make the macro TEMP_NAME_P available to units which do not ! 1635: include c-tree.h. */ ! 1636: int ! 1637: temp_name_p (decl) ! 1638: tree decl; ! 1639: { ! 1640: return TEMP_NAME_P (decl); ! 1641: } ! 1642: ! 1643: /* Finish off the processing of a UNION_TYPE structure. ! 1644: If there are static members, then all members are ! 1645: static, and must be laid out together. If the ! 1646: union is an anonymous union, we arrage for that ! 1647: as well. PUBLICP is nonzero if this union is ! 1648: not declared static. */ ! 1649: void ! 1650: finish_anon_union (anon_union_decl) ! 1651: tree anon_union_decl; ! 1652: { ! 1653: tree type = TREE_TYPE (anon_union_decl); ! 1654: tree field, decl; ! 1655: tree elems = NULL_TREE; ! 1656: int public_p = TREE_PUBLIC (anon_union_decl); ! 1657: int static_p = TREE_STATIC (anon_union_decl); ! 1658: int external_p = TREE_EXTERNAL (anon_union_decl); ! 1659: ! 1660: if ((field = TYPE_FIELDS (type)) == NULL_TREE) ! 1661: return; ! 1662: ! 1663: if (public_p && (static_p || external_p)) ! 1664: error ("optimizer cannot handle global anonymous unions"); ! 1665: ! 1666: while (field) ! 1667: { ! 1668: decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field)); ! 1669: /* tell `pushdecl' that this is not tentative. */ ! 1670: DECL_INITIAL (decl) = error_mark_node; ! 1671: TREE_PUBLIC (decl) = public_p; ! 1672: TREE_STATIC (decl) = static_p; ! 1673: TREE_EXTERNAL (decl) = external_p; ! 1674: decl = pushdecl (decl); ! 1675: DECL_INITIAL (decl) = NULL_TREE; ! 1676: /* If there's a cleanup to do, it belongs in the ! 1677: TREE_PURPOSE of the following TREE_LIST. */ ! 1678: elems = tree_cons (NULL_TREE, decl, elems); ! 1679: TREE_TYPE (elems) = type; ! 1680: field = TREE_CHAIN (field); ! 1681: } ! 1682: if (static_p) ! 1683: make_decl_rtl (decl, 0, global_bindings_p ()); ! 1684: ! 1685: /* The following call assumes that there are never any cleanups ! 1686: for anonymous unions--a reasonable assumption. */ ! 1687: expand_anon_union_decl (anon_union_decl, NULL_TREE, elems); ! 1688: ! 1689: if (flag_cadillac) ! 1690: cadillac_finish_anon_union (decl); ! 1691: } ! 1692: ! 1693: /* Finish and output a table which is generated by the compiler. ! 1694: NAME is the name to give the table. ! 1695: TYPE is the type of the table entry. ! 1696: INIT is all the elements in the table. ! 1697: PUBLICP is non-zero if this table should be given external visibility. */ ! 1698: tree ! 1699: finish_table (name, type, init, publicp) ! 1700: tree name, type, init; ! 1701: { ! 1702: tree itype, atype, decl; ! 1703: static tree empty_table; ! 1704: int is_empty = 0; ! 1705: tree asmspec; ! 1706: ! 1707: itype = build_index_type (size_int (list_length (init) - 1)); ! 1708: atype = build_cplus_array_type (type, itype); ! 1709: layout_type (atype); ! 1710: ! 1711: if (TREE_VALUE (init) == integer_zero_node ! 1712: && TREE_CHAIN (init) == NULL_TREE) ! 1713: { ! 1714: if (empty_table == NULL_TREE) ! 1715: { ! 1716: empty_table = get_temp_name (atype, 1); ! 1717: init = build (CONSTRUCTOR, atype, NULL_TREE, init); ! 1718: TREE_CONSTANT (init) = 1; ! 1719: TREE_STATIC (init) = 1; ! 1720: DECL_INITIAL (empty_table) = init; ! 1721: asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)), ! 1722: IDENTIFIER_POINTER (DECL_NAME (empty_table))); ! 1723: finish_decl (empty_table, init, asmspec, 0); ! 1724: } ! 1725: is_empty = 1; ! 1726: } ! 1727: ! 1728: if (name == NULL_TREE) ! 1729: { ! 1730: if (is_empty) ! 1731: return empty_table; ! 1732: decl = get_temp_name (atype, 1); ! 1733: } ! 1734: else ! 1735: { ! 1736: decl = build_decl (VAR_DECL, name, atype); ! 1737: decl = pushdecl (decl); ! 1738: TREE_STATIC (decl) = 1; ! 1739: } ! 1740: ! 1741: if (is_empty == 0) ! 1742: { ! 1743: TREE_PUBLIC (decl) = publicp; ! 1744: init = build (CONSTRUCTOR, atype, NULL_TREE, init); ! 1745: TREE_CONSTANT (init) = 1; ! 1746: TREE_STATIC (init) = 1; ! 1747: DECL_INITIAL (decl) = init; ! 1748: asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (decl)), ! 1749: IDENTIFIER_POINTER (DECL_NAME (decl))); ! 1750: } ! 1751: else ! 1752: { ! 1753: /* This will cause DECL to point to EMPTY_TABLE in rtl-land. */ ! 1754: TREE_EXTERNAL (decl) = 1; ! 1755: TREE_STATIC (decl) = 0; ! 1756: init = 0; ! 1757: asmspec = build_string (IDENTIFIER_LENGTH (DECL_NAME (empty_table)), ! 1758: IDENTIFIER_POINTER (DECL_NAME (empty_table))); ! 1759: } ! 1760: ! 1761: finish_decl (decl, init, asmspec, 0); ! 1762: return decl; ! 1763: } ! 1764: ! 1765: /* Finish processing a builtin type TYPE. It's name is NAME, ! 1766: its fields are in the array FIELDS. LEN is the number of elements ! 1767: in FIELDS. ! 1768: ! 1769: It is given the same alignment as ALIGN_TYPE. */ ! 1770: void ! 1771: finish_builtin_type (type, name, fields, len, align_type) ! 1772: tree type; ! 1773: char *name; ! 1774: tree fields[]; ! 1775: tree align_type; ! 1776: { ! 1777: register int i; ! 1778: ! 1779: TYPE_FIELDS (type) = fields[0]; ! 1780: for (i = 0; i < len; i++) ! 1781: { ! 1782: layout_type (TREE_TYPE (fields[i])); ! 1783: DECL_FIELD_CONTEXT (fields[i]) = type; ! 1784: TREE_CHAIN (fields[i]) = fields[i+1]; ! 1785: } ! 1786: DECL_FIELD_CONTEXT (fields[i]) = type; ! 1787: DECL_CLASS_CONTEXT (fields[i]) = type; ! 1788: TYPE_ALIGN (type) = TYPE_ALIGN (align_type); ! 1789: layout_type (type); ! 1790: TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type); ! 1791: layout_decl (TYPE_NAME (type), 0); ! 1792: } ! 1793: ! 1794: /* Auxilliary functions to make type signatures for ! 1795: `operator new' and `operator delete' correspond to ! 1796: what compiler will be expecting. */ ! 1797: ! 1798: extern tree sizetype; ! 1799: ! 1800: tree ! 1801: coerce_new_type (ctype, type) ! 1802: tree ctype; ! 1803: tree type; ! 1804: { ! 1805: int e1 = 0, e2 = 0; ! 1806: ! 1807: if (TREE_CODE (type) == METHOD_TYPE) ! 1808: type = build_function_type (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type))); ! 1809: if (TREE_TYPE (type) != ptr_type_node) ! 1810: e1 = 1, error ("`operator new' must return type `void *'"); ! 1811: ! 1812: /* Technically the type must be `size_t', but we may not know ! 1813: what that is. */ ! 1814: if (TYPE_ARG_TYPES (type) == NULL_TREE) ! 1815: e1 = 1, error ("`operator new' takes type `size_t' parameter"); ! 1816: else if (TREE_CODE (TREE_VALUE (TYPE_ARG_TYPES (type))) != INTEGER_TYPE ! 1817: || TYPE_PRECISION (TREE_VALUE (TYPE_ARG_TYPES (type))) != TYPE_PRECISION (sizetype)) ! 1818: e2 = 1, error ("`operator new' takes type `size_t' as first parameter"); ! 1819: if (e2) ! 1820: type = build_function_type (ptr_type_node, tree_cons (NULL_TREE, sizetype, TREE_CHAIN (TYPE_ARG_TYPES (type)))); ! 1821: else if (e1) ! 1822: type = build_function_type (ptr_type_node, TYPE_ARG_TYPES (type)); ! 1823: return type; ! 1824: } ! 1825: ! 1826: tree ! 1827: coerce_delete_type (ctype, type) ! 1828: tree ctype; ! 1829: tree type; ! 1830: { ! 1831: int e1 = 0, e2 = 0, e3 = 0; ! 1832: tree arg_types = TYPE_ARG_TYPES (type); ! 1833: ! 1834: if (TREE_CODE (type) == METHOD_TYPE) ! 1835: { ! 1836: type = build_function_type (TREE_TYPE (type), TREE_CHAIN (arg_types)); ! 1837: arg_types = TREE_CHAIN (arg_types); ! 1838: } ! 1839: if (TREE_TYPE (type) != void_type_node) ! 1840: e1 = 1, error ("`operator delete' must return type `void'"); ! 1841: if (arg_types == NULL_TREE ! 1842: || TREE_VALUE (arg_types) != ptr_type_node) ! 1843: e2 = 1, error ("`operator delete' takes type `void *' as first parameter"); ! 1844: ! 1845: if (arg_types ! 1846: && TREE_CHAIN (arg_types) ! 1847: && TREE_CHAIN (arg_types) != void_list_node) ! 1848: { ! 1849: /* Again, technically this argument must be `size_t', but again ! 1850: we may not know what that is. */ ! 1851: tree t2 = TREE_VALUE (TREE_CHAIN (arg_types)); ! 1852: if (TREE_CODE (t2) != INTEGER_TYPE ! 1853: || TYPE_PRECISION (t2) != TYPE_PRECISION (sizetype)) ! 1854: e3 = 1, error ("second argument to `operator delete' must be of type `size_t'"); ! 1855: else if (TREE_CHAIN (TREE_CHAIN (arg_types)) != void_list_node) ! 1856: { ! 1857: e3 = 1; ! 1858: if (TREE_CHAIN (TREE_CHAIN (arg_types))) ! 1859: error ("too many arguments in declaration of `operator delete'"); ! 1860: else ! 1861: error ("`...' invalid in specification of `operator delete'"); ! 1862: } ! 1863: } ! 1864: if (e3) ! 1865: arg_types = tree_cons (NULL_TREE, ptr_type_node, build_tree_list (NULL_TREE, sizetype)); ! 1866: else if (e3 |= e2) ! 1867: { ! 1868: if (arg_types == NULL_TREE) ! 1869: arg_types = void_list_node; ! 1870: else ! 1871: arg_types = tree_cons (NULL_TREE, ptr_type_node, TREE_CHAIN (arg_types)); ! 1872: } ! 1873: else e3 |= e1; ! 1874: ! 1875: if (e3) ! 1876: type = build_function_type (void_type_node, arg_types); ! 1877: ! 1878: return type; ! 1879: } ! 1880: ! 1881: static void ! 1882: write_vtable_entries (decl) ! 1883: tree decl; ! 1884: { ! 1885: tree entries = TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (decl))); ! 1886: ! 1887: if (flag_dossier) ! 1888: entries = TREE_CHAIN (entries); ! 1889: ! 1890: for (; entries; entries = TREE_CHAIN (entries)) ! 1891: { ! 1892: tree fnaddr = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (entries)); ! 1893: tree fn = TREE_OPERAND (fnaddr, 0); ! 1894: if (! TREE_ASM_WRITTEN (fn) && DECL_SAVED_INSNS (fn)) ! 1895: { ! 1896: if (TREE_PUBLIC (DECL_CLASS_CONTEXT (fn))) ! 1897: TREE_PUBLIC (fn) = 1; ! 1898: TREE_ADDRESSABLE (fn) = 1; ! 1899: output_inline_function (fn); ! 1900: } ! 1901: else ! 1902: assemble_external (fn); ! 1903: } ! 1904: } ! 1905: ! 1906: static void ! 1907: finish_vtable_typedecl (prev, vars) ! 1908: tree prev, vars; ! 1909: { ! 1910: tree decl = TYPE_BINFO_VTABLE (TREE_TYPE (vars)); ! 1911: ! 1912: /* If we are controlled by `+e2', obey. */ ! 1913: if (write_virtuals == 2) ! 1914: { ! 1915: tree binfo = value_member (DECL_NAME (vars), pending_vtables); ! 1916: if (binfo) ! 1917: TREE_PURPOSE (binfo) = void_type_node; ! 1918: else ! 1919: decl = NULL_TREE; ! 1920: } ! 1921: /* If this type has inline virtual functions, then ! 1922: write those functions out now. */ ! 1923: if (decl && write_virtuals >= 0 ! 1924: && (TREE_PUBLIC (decl) || (! TREE_EXTERNAL (decl) && TREE_USED (decl)))) ! 1925: write_vtable_entries (decl); ! 1926: } ! 1927: ! 1928: static void ! 1929: finish_vtable_vardecl (prev, vars) ! 1930: tree prev, vars; ! 1931: { ! 1932: if (write_virtuals < 0) ! 1933: ; ! 1934: else if (write_virtuals == 0 ! 1935: ? TREE_USED (vars) ! 1936: : (TREE_PUBLIC (vars) ! 1937: || (! TREE_EXTERNAL (vars) && TREE_USED (vars)))) ! 1938: { ! 1939: extern tree the_null_vtable_entry; ! 1940: ! 1941: /* Stuff this virtual function table's size into ! 1942: `pfn' slot of `the_null_vtable_entry'. */ ! 1943: tree nelts = array_type_nelts (TREE_TYPE (vars)); ! 1944: SET_FNADDR_FROM_VTABLE_ENTRY (the_null_vtable_entry, nelts); ! 1945: /* Kick out the dossier before writing out the vtable. */ ! 1946: if (flag_dossier) ! 1947: rest_of_decl_compilation (TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (DECL_INITIAL (vars))))), 0), 0, 1, 1); ! 1948: ! 1949: /* Write it out. */ ! 1950: write_vtable_entries (vars); ! 1951: if (TREE_TYPE (DECL_INITIAL (vars)) == 0) ! 1952: store_init_value (vars, DECL_INITIAL (vars)); ! 1953: rest_of_decl_compilation (vars, 0, 1, 1); ! 1954: } ! 1955: /* We know that PREV must be non-zero here. */ ! 1956: TREE_CHAIN (prev) = TREE_CHAIN (vars); ! 1957: } ! 1958: ! 1959: void ! 1960: walk_vtables (typedecl_fn, vardecl_fn) ! 1961: register void (*typedecl_fn)(); ! 1962: register void (*vardecl_fn)(); ! 1963: { ! 1964: tree prev, vars; ! 1965: ! 1966: for (prev = 0, vars = getdecls (); vars; vars = TREE_CHAIN (vars)) ! 1967: { ! 1968: if (TREE_CODE (vars) == TYPE_DECL ! 1969: && TYPE_LANG_SPECIFIC (TREE_TYPE (vars)) ! 1970: && CLASSTYPE_VSIZE (TREE_TYPE (vars))) ! 1971: { ! 1972: if (typedecl_fn) (*typedecl_fn) (prev, vars); ! 1973: } ! 1974: else if (TREE_CODE (vars) == VAR_DECL && DECL_VIRTUAL_P (vars)) ! 1975: { ! 1976: if (vardecl_fn) (*vardecl_fn) (prev, vars); ! 1977: } ! 1978: else ! 1979: prev = vars; ! 1980: } ! 1981: } ! 1982: ! 1983: extern int parse_time, varconst_time; ! 1984: ! 1985: #define TIMEVAR(VAR, BODY) \ ! 1986: do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0) ! 1987: ! 1988: /* This routine is called from the last rule in yyparse (). ! 1989: Its job is to create all the code needed to initialize and ! 1990: destroy the global aggregates. We do the destruction ! 1991: first, since that way we only need to reverse the decls once. */ ! 1992: ! 1993: void ! 1994: finish_file () ! 1995: { ! 1996: extern struct rtx_def *const0_rtx; ! 1997: extern int lineno; ! 1998: extern struct _iob *asm_out_file; ! 1999: int start_time, this_time; ! 2000: char *init_function_name; ! 2001: ! 2002: char *buf; ! 2003: char *p; ! 2004: tree fnname; ! 2005: tree vars = static_aggregates; ! 2006: int needs_cleaning = 0, needs_messing_up = 0; ! 2007: ! 2008: if (main_input_filename == 0) ! 2009: main_input_filename = input_filename; ! 2010: if (!first_global_object_name) ! 2011: first_global_object_name = main_input_filename; ! 2012: ! 2013: buf = (char *) alloca (sizeof (FILE_FUNCTION_FORMAT) ! 2014: + strlen (first_global_object_name)); ! 2015: ! 2016: if (flag_detailed_statistics) ! 2017: dump_tree_statistics (); ! 2018: ! 2019: /* Bad parse errors. Just forget about it. */ ! 2020: if (! global_bindings_p ()) ! 2021: return; ! 2022: ! 2023: start_time = get_run_time (); ! 2024: ! 2025: /* Push into C language context, because that's all ! 2026: we'll need here. */ ! 2027: push_lang_context (lang_name_c); ! 2028: ! 2029: /* Set up the name of the file-level functions we may need. */ ! 2030: /* Use a global object (which is already required to be unique over ! 2031: the program) rather than the file name (which imposes extra ! 2032: constraints). -- [email protected], 10 Jan 1990. */ ! 2033: sprintf (buf, FILE_FUNCTION_FORMAT, first_global_object_name); ! 2034: ! 2035: /* Don't need to pull wierd characters out of global names. */ ! 2036: if (first_global_object_name == main_input_filename) ! 2037: { ! 2038: for (p = buf+11; *p; p++) ! 2039: if (! ((*p >= '0' && *p <= '9') ! 2040: #if 0 /* we always want labels, which are valid C++ identifiers (+ `$') */ ! 2041: #ifndef ASM_IDENTIFY_GCC /* this is required if `.' is invalid -- k. raeburn */ ! 2042: || *p == '.' ! 2043: #endif ! 2044: #endif ! 2045: #ifndef NO_DOLLAR_IN_LABEL /* this for `$'; unlikely, but... -- kr */ ! 2046: || *p == '$' ! 2047: #endif ! 2048: || (*p >= 'A' && *p <= 'Z') ! 2049: || (*p >= 'a' && *p <= 'z'))) ! 2050: *p = '_'; ! 2051: } ! 2052: ! 2053: /* See if we really need the hassle. */ ! 2054: while (vars && needs_cleaning == 0) ! 2055: { ! 2056: tree decl = TREE_VALUE (vars); ! 2057: tree type = TREE_TYPE (decl); ! 2058: if (TYPE_NEEDS_DESTRUCTOR (type)) ! 2059: { ! 2060: needs_cleaning = 1; ! 2061: needs_messing_up = 1; ! 2062: break; ! 2063: } ! 2064: else ! 2065: needs_messing_up |= TYPE_NEEDS_CONSTRUCTING (type); ! 2066: vars = TREE_CHAIN (vars); ! 2067: } ! 2068: if (needs_cleaning == 0) ! 2069: goto mess_up; ! 2070: ! 2071: /* Otherwise, GDB can get confused, because in only knows ! 2072: about source for LINENO-1 lines. */ ! 2073: lineno -= 1; ! 2074: ! 2075: fnname = get_identifier (buf); ! 2076: start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); ! 2077: fnname = DECL_ASSEMBLER_NAME (current_function_decl); ! 2078: store_parm_decls (); ! 2079: ! 2080: pushlevel (0); ! 2081: clear_last_expr (); ! 2082: push_momentary (); ! 2083: expand_start_bindings (0); ! 2084: ! 2085: /* These must be done in backward order to destroy, ! 2086: in which they happen to be! */ ! 2087: while (vars) ! 2088: { ! 2089: tree decl = TREE_VALUE (vars); ! 2090: tree type = TREE_TYPE (decl); ! 2091: tree temp = TREE_PURPOSE (vars); ! 2092: ! 2093: if (TYPE_NEEDS_DESTRUCTOR (type)) ! 2094: { ! 2095: if (TREE_STATIC (vars)) ! 2096: expand_start_cond (build_binary_op (NE_EXPR, temp, integer_zero_node), 0); ! 2097: if (TREE_CODE (type) == ARRAY_TYPE) ! 2098: temp = decl; ! 2099: else ! 2100: { ! 2101: mark_addressable (decl); ! 2102: temp = build1 (ADDR_EXPR, TYPE_POINTER_TO (type), decl); ! 2103: } ! 2104: temp = build_delete (TREE_TYPE (temp), temp, ! 2105: integer_two_node, LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0, 0); ! 2106: expand_expr_stmt (temp); ! 2107: ! 2108: if (TREE_STATIC (vars)) ! 2109: expand_end_cond (); ! 2110: } ! 2111: vars = TREE_CHAIN (vars); ! 2112: } ! 2113: ! 2114: expand_end_bindings (getdecls (), 1, 0); ! 2115: poplevel (1, 0, 1); ! 2116: pop_momentary (); ! 2117: ! 2118: finish_function (lineno, 0); ! 2119: ! 2120: assemble_destructor (IDENTIFIER_POINTER (fnname)); ! 2121: ! 2122: /* if it needed cleaning, then it will need messing up: drop through */ ! 2123: ! 2124: mess_up: ! 2125: /* Must do this while we think we are at the top level. */ ! 2126: vars = nreverse (static_aggregates); ! 2127: if (vars != NULL_TREE) ! 2128: { ! 2129: buf[FILE_FUNCTION_PREFIX_LEN] = 'I'; ! 2130: ! 2131: fnname = get_identifier (buf); ! 2132: start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); ! 2133: fnname = DECL_ASSEMBLER_NAME (current_function_decl); ! 2134: store_parm_decls (); ! 2135: ! 2136: pushlevel (0); ! 2137: clear_last_expr (); ! 2138: push_momentary (); ! 2139: expand_start_bindings (0); ! 2140: ! 2141: #ifdef SOS ! 2142: if (flag_all_virtual == 2) ! 2143: { ! 2144: tree decl; ! 2145: char c = buf[FILE_FUNCTION_PREFIX_LEN]; ! 2146: buf[FILE_FUNCTION_PREFIX_LEN] = 'Z'; ! 2147: ! 2148: decl = pushdecl (build_lang_decl (FUNCTION_DECL, get_identifier (buf), default_function_type)); ! 2149: finish_decl (decl, NULL_TREE, NULL_TREE, 0); ! 2150: expand_expr_stmt (build_function_call (decl, NULL_TREE)); ! 2151: buf[FILE_FUNCTION_PREFIX_LEN] = c; ! 2152: } ! 2153: #endif ! 2154: ! 2155: while (vars) ! 2156: { ! 2157: tree decl = TREE_VALUE (vars); ! 2158: tree init = TREE_PURPOSE (vars); ! 2159: ! 2160: /* If this was a static attribute within some function's scope, ! 2161: then don't initialize it here. Also, don't bother ! 2162: with initializers that contain errors. */ ! 2163: if (TREE_STATIC (vars) ! 2164: || (init && TREE_CODE (init) == TREE_LIST ! 2165: && value_member (error_mark_node, init))) ! 2166: { ! 2167: vars = TREE_CHAIN (vars); ! 2168: continue; ! 2169: } ! 2170: ! 2171: if (TREE_CODE (decl) == VAR_DECL) ! 2172: { ! 2173: /* Set these global variables so that GDB at least puts ! 2174: us near the declaration which required the initialization. */ ! 2175: input_filename = DECL_SOURCE_FILE (decl); ! 2176: lineno = DECL_SOURCE_LINE (decl); ! 2177: emit_note (input_filename, lineno); ! 2178: ! 2179: if (init) ! 2180: { ! 2181: if (TREE_CODE (init) == VAR_DECL) ! 2182: { ! 2183: /* This behavior results when there are ! 2184: multiple declarations of an aggregate, ! 2185: the last of which defines it. */ ! 2186: if (DECL_RTL (init) == DECL_RTL (decl)) ! 2187: { ! 2188: assert (DECL_INITIAL (decl) == error_mark_node ! 2189: || (TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR ! 2190: && CONSTRUCTOR_ELTS (DECL_INITIAL (decl)) == NULL_TREE)); ! 2191: init = DECL_INITIAL (init); ! 2192: if (TREE_CODE (init) == CONSTRUCTOR ! 2193: && CONSTRUCTOR_ELTS (init) == NULL_TREE) ! 2194: init = NULL_TREE; ! 2195: } ! 2196: #if 0 ! 2197: else if (TREE_TYPE (decl) == TREE_TYPE (init)) ! 2198: { ! 2199: #if 1 ! 2200: assert (0); ! 2201: #else ! 2202: /* point to real decl's rtl anyway. */ ! 2203: DECL_RTL (init) = DECL_RTL (decl); ! 2204: assert (DECL_INITIAL (decl) == error_mark_node); ! 2205: init = DECL_INITIAL (init); ! 2206: #endif /* 1 */ ! 2207: } ! 2208: #endif /* 0 */ ! 2209: } ! 2210: } ! 2211: if (IS_AGGR_TYPE (TREE_TYPE (decl)) ! 2212: || init == 0 ! 2213: || TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) ! 2214: expand_aggr_init (decl, init, 0); ! 2215: else if (TREE_CODE (init) == TREE_VEC) ! 2216: { ! 2217: expand_expr (expand_vec_init (decl, TREE_VEC_ELT (init, 0), ! 2218: TREE_VEC_ELT (init, 1), ! 2219: TREE_VEC_ELT (init, 2), 0), ! 2220: const0_rtx, VOIDmode, 0); ! 2221: free_temp_slots (); ! 2222: } ! 2223: else ! 2224: expand_assignment (decl, init, 0, 0); ! 2225: } ! 2226: else if (TREE_CODE (decl) == SAVE_EXPR) ! 2227: { ! 2228: if (! PARM_DECL_EXPR (decl)) ! 2229: { ! 2230: /* a `new' expression at top level. */ ! 2231: expand_expr (decl, const0_rtx, VOIDmode, 0); ! 2232: free_temp_slots (); ! 2233: expand_aggr_init (build_indirect_ref (decl, 0), init, 0); ! 2234: } ! 2235: } ! 2236: else if (decl == error_mark_node) ! 2237: ; ! 2238: else abort (); ! 2239: vars = TREE_CHAIN (vars); ! 2240: } ! 2241: ! 2242: expand_end_bindings (getdecls (), 1, 0); ! 2243: poplevel (1, 0, 1); ! 2244: pop_momentary (); ! 2245: ! 2246: finish_function (lineno, 0); ! 2247: assemble_constructor (IDENTIFIER_POINTER (fnname)); ! 2248: } ! 2249: ! 2250: #ifdef SOS ! 2251: if (flag_all_virtual == 2) ! 2252: { ! 2253: tree __sosDynError = default_conversion (lookup_name (get_identifier ("sosDynError"), 0)); ! 2254: ! 2255: tree null_string = build1 (ADDR_EXPR, string_type_node, combine_strings (build_string (0, ""))); ! 2256: tree tags = gettags (); ! 2257: tree decls = getdecls (); ! 2258: tree entry; ! 2259: int i; ! 2260: ! 2261: entry = NULL_TREE; ! 2262: for (i = 0; i < 3; i++) ! 2263: entry = tree_cons (NULL_TREE, integer_zero_node, entry); ! 2264: zlink = build_tree_list (NULL_TREE, build (CONSTRUCTOR, zlink_type, NULL_TREE, entry)); ! 2265: TREE_CONSTANT (TREE_VALUE (zlink)) = 1; ! 2266: TREE_STATIC (TREE_VALUE (zlink)) = 1; ! 2267: ! 2268: entry = NULL_TREE; ! 2269: for (i = 0; i < 5; i++) ! 2270: entry = tree_cons (NULL_TREE, integer_zero_node, entry); ! 2271: zret = build_tree_list (NULL_TREE, build (CONSTRUCTOR, zret_type, NULL_TREE, entry)); ! 2272: TREE_CONSTANT (TREE_VALUE (zret)) = 1; ! 2273: TREE_STATIC (TREE_VALUE (zret)) = 1; ! 2274: ! 2275: /* Symbols with external visibility (except globally visible ! 2276: dynamic member functions) into the `zlink' table. */ ! 2277: while (decls) ! 2278: { ! 2279: if (TREE_PUBLIC (decls) ! 2280: && TREE_ASM_WRITTEN (decls) ! 2281: && (TREE_CODE (decls) != FUNCTION_DECL ! 2282: || TREE_CODE (TREE_TYPE (decls)) != METHOD_TYPE ! 2283: || TYPE_DYNAMIC (DECL_CLASS_CONTEXT (decls)) == 0)) ! 2284: { ! 2285: entry = build (CONSTRUCTOR, zlink_type, NULL_TREE, ! 2286: tree_cons (NULL_TREE, ! 2287: build1 (ADDR_EXPR, string_type_node, ! 2288: combine_strings (build_string (IDENTIFIER_LENGTH (DECL_ASSEMBLER_NAME (decls)), ! 2289: IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decls))))), ! 2290: tree_cons (NULL_TREE, integer_one_node, ! 2291: build_tree_list (NULL_TREE, build_unary_op (ADDR_EXPR, decls, 0))))); ! 2292: TREE_CONSTANT (entry) = 1; ! 2293: TREE_STATIC (entry) = 1; ! 2294: zlink = tree_cons (NULL_TREE, entry, zlink); ! 2295: } ! 2296: decls = TREE_CHAIN (decls); ! 2297: } ! 2298: ! 2299: buf[FILE_FUNCTION_PREFIX_LEN] = 'Z'; ! 2300: ! 2301: fnname = get_identifier (buf); ! 2302: start_function (void_list_node, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE), 0, 0); ! 2303: fnname = DECL_ASSEMBLER_NAME (current_function_decl); ! 2304: store_parm_decls (); ! 2305: ! 2306: pushlevel (0); ! 2307: clear_last_expr (); ! 2308: push_momentary (); ! 2309: expand_start_bindings (0); ! 2310: ! 2311: { ! 2312: tree decl, type; ! 2313: /* Lay out a table static to this function ! 2314: with information about all text and data that ! 2315: this file provides. */ ! 2316: tree zlink_table = finish_table (get_identifier ("__ZLINK_tbl"), zlink_type, zlink, 0); ! 2317: decl = pushdecl (build_decl (VAR_DECL, get_identifier ("_ZLINK_once"), integer_type_node)); ! 2318: TREE_STATIC (decl) = 1; ! 2319: finish_decl (decl, NULL_TREE, NULL_TREE, 0); ! 2320: expand_start_cond (truthvalue_conversion (decl), 0); ! 2321: expand_null_return (); ! 2322: expand_end_cond (); ! 2323: finish_stmt (); ! 2324: expand_expr_stmt (build_modify_expr (decl, NOP_EXPR, integer_one_node)); ! 2325: type = build_function_type (void_type_node, NULL_TREE); ! 2326: decl = pushdecl (build_lang_decl (FUNCTION_DECL, get_identifier ("_Ztable_from_cfront"), type)); ! 2327: TREE_EXTERNAL (decl) = 1; ! 2328: finish_decl (decl, NULL_TREE, NULL_TREE, 0); ! 2329: expand_expr_stmt (build_function_call (decl, build_tree_list (NULL_TREE, zlink_table))); ! 2330: expand_null_return (); ! 2331: } ! 2332: expand_end_bindings (0, 1, 0); ! 2333: poplevel (1, 0, 1); ! 2334: pop_momentary (); ! 2335: finish_function (lineno, 0); ! 2336: ! 2337: buf[FILE_FUNCTION_PREFIX_LEN] = 'Y'; ! 2338: fnname = get_identifier (buf); ! 2339: start_function (build_tree_list (NULL_TREE, get_identifier ("int")), ! 2340: build_parse_node (INDIRECT_REF, build_parse_node (CALL_EXPR, fnname, void_list_node, NULL_TREE)), 0, 0); ! 2341: fnname = DECL_ASSEMBLER_NAME (current_function_decl); ! 2342: store_parm_decls (); ! 2343: ! 2344: pushlevel (0); ! 2345: clear_last_expr (); ! 2346: push_momentary (); ! 2347: expand_start_bindings (0); ! 2348: ! 2349: { ! 2350: #define SOS_VERSION 2 ! 2351: tree sosVersionNumber = build_int_2 (SOS_VERSION, 0); ! 2352: tree zret_table; ! 2353: ! 2354: /* For each type defined, if is a dynamic type, write out ! 2355: an entry linking its member functions with their names. */ ! 2356: ! 2357: while (tags) ! 2358: { ! 2359: tree type = TREE_VALUE (tags); ! 2360: if (TYPE_DYNAMIC (type)) ! 2361: { ! 2362: /* SOS currently only implements single inheritance, ! 2363: so we just pick up one string, if this class ! 2364: has a base class. */ ! 2365: tree base_name = TYPE_BINFO_BASETYPES (type) && TYPE_DYNAMIC (TYPE_BINFO_BASECLASS (type, 0)) ! 2366: ? build1 (ADDR_EXPR, string_type_node, CLASSTYPE_TYPENAME_AS_STRING (TYPE_BINFO_BASETYPE (type, 0))) ! 2367: : null_string; ! 2368: tree dyn_table, dyn_entry = NULL_TREE, fns = TYPE_BINFO_VIRTUALS (type); ! 2369: while (fns) ! 2370: { ! 2371: if (TREE_ASM_WRITTEN (TREE_OPERAND (TREE_VALUE (fns), 0))) ! 2372: dyn_entry = tree_cons (NULL_TREE, TREE_VALUE (fns), dyn_entry); ! 2373: else ! 2374: dyn_entry = tree_cons (NULL_TREE, __sosDynError, dyn_entry); ! 2375: fns = TREE_CHAIN (fns); ! 2376: } ! 2377: dyn_entry = nreverse (dyn_entry); ! 2378: dyn_entry = tree_cons (NULL_TREE, build1 (NOP_EXPR, TYPE_POINTER_TO (default_function_type), sosVersionNumber), ! 2379: tree_cons (NULL_TREE, integer_zero_node, ! 2380: tree_cons (NULL_TREE, integer_zero_node, ! 2381: dyn_entry))); ! 2382: dyn_table = finish_table (TYPE_IDENTIFIER (type), TYPE_POINTER_TO (default_function_type), dyn_entry, 0); ! 2383: entry = build (CONSTRUCTOR, zret_type, NULL_TREE, ! 2384: tree_cons (NULL_TREE, build1 (ADDR_EXPR, string_type_node, CLASSTYPE_TYPENAME_AS_STRING (type)), ! 2385: tree_cons (NULL_TREE, default_conversion (dyn_table), ! 2386: tree_cons (NULL_TREE, build_int_2 (CLASSTYPE_VSIZE (type), 0), ! 2387: tree_cons (NULL_TREE, base_name, ! 2388: build_tree_list (NULL_TREE, integer_zero_node)))))); ! 2389: TREE_CONSTANT (entry) = 1; ! 2390: TREE_STATIC (entry) = 1; ! 2391: zret = tree_cons (NULL_TREE, entry, zret); ! 2392: } ! 2393: tags = TREE_CHAIN (tags); ! 2394: } ! 2395: zret_table = finish_table (get_identifier ("__Zret"), zret_type, zret, 0); ! 2396: c_expand_return (convert (build_pointer_type (integer_type_node), default_conversion (zret_table))); ! 2397: } ! 2398: expand_end_bindings (0, 1, 0); ! 2399: poplevel (1, 0, 1); ! 2400: pop_momentary (); ! 2401: finish_function (lineno, 0); ! 2402: ! 2403: assemble_constructor (fnname); ! 2404: } ! 2405: #endif ! 2406: ! 2407: /* Done with C language context needs. */ ! 2408: pop_lang_context (); ! 2409: ! 2410: /* Now write out any static class variables (which may have since ! 2411: learned how to be initialized). */ ! 2412: while (pending_statics) ! 2413: { ! 2414: tree decl = TREE_VALUE (pending_statics); ! 2415: if (TREE_USED (decl) == 1 ! 2416: || TREE_READONLY (decl) == 0 ! 2417: || DECL_INITIAL (decl) == 0) ! 2418: rest_of_decl_compilation (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), 1, 1); ! 2419: pending_statics = TREE_CHAIN (pending_statics); ! 2420: } ! 2421: ! 2422: this_time = get_run_time (); ! 2423: parse_time -= this_time - start_time; ! 2424: varconst_time += this_time - start_time; ! 2425: ! 2426: /* Now write out inline functions which had their addresses taken ! 2427: and which were not declared virtual and which were not declared ! 2428: `extern inline'. */ ! 2429: while (pending_addressable_inlines) ! 2430: { ! 2431: tree decl = TREE_VALUE (pending_addressable_inlines); ! 2432: if (! TREE_ASM_WRITTEN (decl) ! 2433: && ! TREE_EXTERNAL (decl) ! 2434: && DECL_SAVED_INSNS (decl)) ! 2435: output_inline_function (decl); ! 2436: pending_addressable_inlines = TREE_CHAIN (pending_addressable_inlines); ! 2437: } ! 2438: ! 2439: start_time = get_run_time (); ! 2440: ! 2441: /* Now delete from the chain of variables all virtual function tables. ! 2442: We output them all ourselves, because each will be treated specially. */ ! 2443: ! 2444: /* Make last thing in global scope not be a virtual function table. */ ! 2445: vars = build_decl (TYPE_DECL, get_identifier (" @%$#@!"), integer_type_node); ! 2446: pushdecl (vars); ! 2447: ! 2448: walk_vtables (finish_vtable_typedecl, finish_vtable_vardecl); ! 2449: ! 2450: if (write_virtuals == 2) ! 2451: { ! 2452: /* Now complain about an virtual function tables promised ! 2453: but not delivered. */ ! 2454: while (pending_vtables) ! 2455: { ! 2456: if (TREE_PURPOSE (pending_vtables) == NULL_TREE) ! 2457: error ("virtual function table for `%s' not defined", ! 2458: IDENTIFIER_POINTER (TREE_VALUE (pending_vtables))); ! 2459: pending_vtables = TREE_CHAIN (pending_vtables); ! 2460: } ! 2461: } ! 2462: ! 2463: permanent_allocation (); ! 2464: this_time = get_run_time (); ! 2465: parse_time -= this_time - start_time; ! 2466: varconst_time += this_time - start_time; ! 2467: ! 2468: if (flag_detailed_statistics) ! 2469: dump_time_statistics (); ! 2470: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.