diff options
Diffstat (limited to 'gnu/usr.bin/cc/cc1plus/decl.c')
-rw-r--r-- | gnu/usr.bin/cc/cc1plus/decl.c | 534 |
1 files changed, 243 insertions, 291 deletions
diff --git a/gnu/usr.bin/cc/cc1plus/decl.c b/gnu/usr.bin/cc/cc1plus/decl.c index 0690340..048ce5e 100644 --- a/gnu/usr.bin/cc/cc1plus/decl.c +++ b/gnu/usr.bin/cc/cc1plus/decl.c @@ -162,6 +162,8 @@ tree wchar_type_node; tree signed_wchar_type_node; tree unsigned_wchar_type_node; +tree wchar_decl_node; + tree float_type_node; tree double_type_node; tree long_double_type_node; @@ -401,6 +403,11 @@ extern int flag_short_double; extern int flag_no_builtin; +/* Nonzero means don't recognize the non-ANSI builtin functions. + -ansi sets this. */ + +extern int flag_no_nonansi_builtin; + /* Nonzero means disable GNU extensions. */ extern int flag_ansi; @@ -1743,6 +1750,7 @@ pushtag (name, type, globalize) #else d = build_decl (TYPE_DECL, name, type); #endif + SET_DECL_ARTIFICIAL (d); #ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) { @@ -1778,6 +1786,7 @@ pushtag (name, type, globalize) /* Make nested declarations go into class-level scope. */ newdecl = 1; d = build_decl (TYPE_DECL, name, type); + SET_DECL_ARTIFICIAL (d); #ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG) { @@ -1981,11 +1990,11 @@ decls_match (newdecl, olddecl) for (i = 0; i < len; i++) { - tree newarg = TREE_VEC_ELT (newargs, i); - tree oldarg = TREE_VEC_ELT (oldargs, i); + tree newarg = TREE_VALUE (TREE_VEC_ELT (newargs, i)); + tree oldarg = TREE_VALUE (TREE_VEC_ELT (oldargs, i)); if (TREE_CODE (newarg) != TREE_CODE (oldarg)) return 0; - else if (TREE_CODE (newarg) == IDENTIFIER_NODE) + else if (TREE_CODE (newarg) == TYPE_DECL) /* continue */; else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1)) return 0; @@ -2104,6 +2113,7 @@ duplicate_decls (newdecl, olddecl) after implicit decl. */ ; else if (TREE_CODE (olddecl) == FUNCTION_DECL + && DECL_ARTIFICIAL (olddecl) && (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl))) { /* If you declare a built-in or predefined function name as static, @@ -2188,9 +2198,8 @@ duplicate_decls (newdecl, olddecl) newdecl); cp_error_at ("previous declaration `%#D' here", olddecl); } - - if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), - TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2)) + else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)), + TYPE_ARG_TYPES (TREE_TYPE (olddecl)), 2)) { cp_error ("new declaration `%#D'", newdecl); cp_error_at ("ambiguates old declaration `%#D'", olddecl); @@ -2199,16 +2208,21 @@ duplicate_decls (newdecl, olddecl) return 0; } + if (olddecl == wchar_decl_node) + { + if (pedantic && ! DECL_IN_SYSTEM_HEADER (newdecl)) + cp_pedwarn ("redeclaration of wchar_t as `%T'", + TREE_TYPE (newdecl)); + + /* Throw away the redeclaration. */ + return 1; + } + /* Already complained about this, so don't do so again. */ else if (current_class_type == NULL_TREE || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type) { - /* Since we're doing this before finish_struct can set the - line number on NEWDECL, we just do a regular error here. */ - if (DECL_SOURCE_LINE (newdecl) == 0) - cp_error ("conflicting types for `%#D'", newdecl); - else - cp_error_at ("conflicting types for `%#D'", newdecl); + cp_error ("conflicting types for `%#D'", newdecl); cp_error_at ("previous declaration as `%#D'", olddecl); } } @@ -2521,12 +2535,15 @@ duplicate_decls (newdecl, olddecl) DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl); DECL_TEMPLATE_INSTANTIATIONS (newdecl) = DECL_TEMPLATE_INSTANTIATIONS (olddecl); + if (DECL_CHAIN (newdecl) == NULL_TREE) + DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl); } /* Now preserve various other info from the definition. */ TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl); TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl); DECL_COMMON (newdecl) = DECL_COMMON (olddecl); + DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl); /* Don't really know how much of the language-specific values we should copy from old to new. */ @@ -2678,7 +2695,8 @@ pushdecl (x) /* don't do anything just yet */; else if (TREE_CODE (t) != TREE_CODE (x)) { - if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL) + if ((TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)) + || (TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x))) { /* We do nothing special here, because C++ does such nasty things with TYPE_DECLs. Instead, just let the TYPE_DECL @@ -3892,7 +3910,9 @@ lookup_name_real (name, prefer_type, nonclass) if (got_scope != NULL_TREE) { - if (got_scope == void_type_node) + if (got_scope == error_mark_node) + return error_mark_node; + else if (got_scope == void_type_node) val = IDENTIFIER_GLOBAL_VALUE (name); else if (TREE_CODE (got_scope) == TEMPLATE_TYPE_PARM /* TFIXME -- don't do this for UPTs in new model. */ @@ -4540,14 +4560,29 @@ init_decl_processing () sizetype, endlink)), BUILT_IN_ALLOCA, "alloca"); -#if 0 - builtin_function ("alloca", - build_function_type (ptr_type_node, - tree_cons (NULL_TREE, - sizetype, - endlink)), - BUILT_IN_ALLOCA, NULL_PTR); -#endif + /* Define alloca, ffs as builtins. + Declare _exit just to mark it as volatile. */ + if (! flag_no_builtin && !flag_no_nonansi_builtin) + { + temp = builtin_function ("alloca", + build_function_type (ptr_type_node, + tree_cons (NULL_TREE, + sizetype, + endlink)), + BUILT_IN_ALLOCA, NULL_PTR); + /* Suppress error if redefined as a non-function. */ + DECL_BUILT_IN_NONANSI (temp) = 1; + temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR); + /* Suppress error if redefined as a non-function. */ + DECL_BUILT_IN_NONANSI (temp) = 1; + temp = builtin_function ("_exit", build_function_type (void_type_node, + int_endlink), + NOT_BUILT_IN, NULL_PTR); + TREE_THIS_VOLATILE (temp) = 1; + TREE_SIDE_EFFECTS (temp) = 1; + /* Suppress error if redefined as a non-function. */ + DECL_BUILT_IN_NONANSI (temp) = 1; + } builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR); @@ -4647,6 +4682,23 @@ init_decl_processing () builtin_function ("strlen", sizet_ftype_string, BUILT_IN_STRLEN, NULL_PTR); builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR); builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR); + + /* Declare these functions volatile + to avoid spurious "control drops through" warnings. */ + temp = builtin_function ("abort", + build_function_type (void_type_node, endlink), + NOT_BUILT_IN, NULL_PTR); + TREE_THIS_VOLATILE (temp) = 1; + TREE_SIDE_EFFECTS (temp) = 1; + /* Well, these are actually ANSI, but we can't set DECL_BUILT_IN on + them... */ + DECL_BUILT_IN_NONANSI (temp) = 1; + temp = builtin_function ("exit", build_function_type (void_type_node, + int_endlink), + NOT_BUILT_IN, NULL_PTR); + TREE_THIS_VOLATILE (temp) = 1; + TREE_SIDE_EFFECTS (temp) = 1; + DECL_BUILT_IN_NONANSI (temp) = 1; } #if 0 @@ -4708,6 +4760,11 @@ init_decl_processing () : signed_wchar_type_node; record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node); + /* Artificial declaration of wchar_t -- can be bashed */ + wchar_decl_node = build_decl (TYPE_DECL, get_identifier ("wchar_t"), + wchar_type_node); + pushdecl (wchar_decl_node); + /* This is for wide string constants. */ wchar_array_type_node = build_array_type (wchar_type_node, array_domain_type); @@ -4758,7 +4815,7 @@ init_decl_processing () vtbl_type_node = build_array_type (vtable_entry_type, NULL_TREE); layout_type (vtbl_type_node); - vtbl_type_node = c_build_type_variant (vtbl_type_node, 1, 0); + vtbl_type_node = cp_build_type_variant (vtbl_type_node, 1, 0); record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node); /* Simplify life by making a "sigtable_entry_type". Give its @@ -4928,7 +4985,7 @@ init_decl_processing () NOT_BUILT_IN); abort_fndecl - = define_function ("abort", + = define_function ("__pure_virtual", build_function_type (void_type_node, void_list_node), NOT_BUILT_IN, 0, 0); @@ -5010,7 +5067,6 @@ shadow_tag (declspecs) tree declspecs; { int found_tag = 0; - int warned = 0; tree ob_modifier = NULL_TREE; register tree link; register enum tree_code code, ok_code = ERROR_MARK; @@ -5023,41 +5079,14 @@ shadow_tag (declspecs) code = TREE_CODE (value); if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE) { - register tree name = TYPE_NAME (value); + my_friendly_assert (TYPE_NAME (value) != NULL_TREE, 261); if (code == ENUMERAL_TYPE && TYPE_SIZE (value) == 0) cp_error ("forward declaration of `%#T'", value); - if (name == NULL_TREE) - name = lookup_tag_reverse (value, NULL_TREE); - - if (name && TREE_CODE (name) == TYPE_DECL) - name = DECL_NAME (name); - - t = lookup_tag (code, name, inner_binding_level, 1); - - if (t == NULL_TREE) - { - push_obstacks (&permanent_obstack, &permanent_obstack); - if (IS_AGGR_TYPE_CODE (code)) - t = make_lang_type (code); - else - t = make_node (code); - pushtag (name, t, 0); - pop_obstacks (); - ok_code = code; - } - else if (name != NULL_TREE || code == ENUMERAL_TYPE) - ok_code = code; - - if (ok_code != ERROR_MARK) - found_tag++; - else - { - if (!warned) - pedwarn ("useless keyword or type name in declaration"); - warned = 1; - } + t = value; + ok_code = code; + found_tag++; } else if (value == ridpointers[(int) RID_STATIC] || value == ridpointers[(int) RID_EXTERN] @@ -5097,32 +5126,9 @@ shadow_tag (declspecs) cp_error ("`%D' can only be specified for objects and functions", ob_modifier); - if (ok_code == RECORD_TYPE - && found_tag == 1 - && TYPE_LANG_SPECIFIC (t) - && CLASSTYPE_DECLARED_EXCEPTION (t)) - { - if (TYPE_SIZE (t)) - cp_error ("redeclaration of exception `%T'", t); - else - { - tree ename, decl; - - push_obstacks (&permanent_obstack, &permanent_obstack); - - pushclass (t, 0); - - ename = TYPE_NAME (t); - if (TREE_CODE (ename) == TYPE_DECL) - ename = DECL_NAME (ename); - decl = build_lang_field_decl (VAR_DECL, ename, t); - - pop_obstacks (); - } - } - else if (found_tag == 0) + if (found_tag == 0) pedwarn ("abstract declarator used as declaration"); - else if (!warned && found_tag > 1) + else if (found_tag > 1) pedwarn ("multiple types in one declaration"); } } @@ -5255,8 +5261,7 @@ start_decl (declarator, declspecs, initialized, raises) if (interface_unknown && flag_external_templates && ! DECL_IN_SYSTEM_HEADER (decl)) warn_if_unknown_interface (); - TREE_PUBLIC (d) = TREE_PUBLIC (decl) = - flag_external_templates && !interface_unknown; + TREE_PUBLIC (d) = TREE_PUBLIC (decl); TREE_STATIC (d) = TREE_STATIC (decl); DECL_EXTERNAL (d) = (DECL_EXTERNAL (decl) && !(context && !DECL_THIS_EXTERN (decl))); @@ -5714,6 +5719,14 @@ finish_decl (decl, init, asmspec_tree, need_pop) type = TREE_TYPE (decl); + if (type == error_mark_node) + { + if (current_binding_level == global_binding_level && temporary) + end_temporary_allocation (); + + return; + } + was_incomplete = (DECL_SIZE (decl) == NULL_TREE); /* Take care of TYPE_DECLs up front. */ @@ -5808,6 +5821,10 @@ finish_decl (decl, init, asmspec_tree, need_pop) else if (TREE_CODE (type) == REFERENCE_TYPE || (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE_REFERENCE (type))) { + if (TREE_STATIC (decl)) + make_decl_rtl (decl, NULL_PTR, + current_binding_level == global_binding_level + || pseudo_global_level_p ()); grok_reference_init (decl, type, init, &cleanup); init = NULL_TREE; } @@ -6315,9 +6332,11 @@ finish_decl (decl, init, asmspec_tree, need_pop) expand_aggr_init (decl, init, 0); } - /* Set this to 0 so we can tell whether an aggregate - which was initialized was ever used. */ - if (TYPE_NEEDS_CONSTRUCTING (type)) + /* Set this to 0 so we can tell whether an aggregate which + was initialized was ever used. Don't do this if it has a + destructor, so we don't complain about the 'resource + allocation is initialization' idiom. */ + if (TYPE_NEEDS_CONSTRUCTING (type) && cleanup == NULL_TREE) TREE_USED (decl) = 0; /* Store the cleanup, if there was one. */ @@ -6792,6 +6811,7 @@ grokvardecl (type, declarator, specbits, initialized) decl = build_lang_field_decl (VAR_DECL, declarator, type); DECL_CONTEXT (decl) = basetype; DECL_CLASS_CONTEXT (decl) = basetype; + DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator); } else decl = build_decl (VAR_DECL, declarator, type); @@ -6857,6 +6877,8 @@ build_ptrmemfunc_type (type) /* Let the front-end know this is a pointer to member function. */ TYPE_PTRMEMFUNC_FLAG(t) = 1; + /* and not really an aggregate. */ + IS_AGGR_TYPE (t) = 0; fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier, delta_type_node); @@ -7091,7 +7113,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) dname = decl; decl = NULL_TREE; - if (IDENTIFIER_OPNAME_P (dname)) + if (! IDENTIFIER_OPNAME_P (dname) + /* Linux headers use '__op'. Arrgh. */ + || IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname)) + name = IDENTIFIER_POINTER (dname); + else { if (IDENTIFIER_TYPENAME_P (dname)) { @@ -7102,8 +7128,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } name = operator_name_string (dname); } - else - name = IDENTIFIER_POINTER (dname); break; case RECORD_TYPE: @@ -7281,7 +7305,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) goto found; } - for (i = (int) RID_FIRST_MODIFIER; i < (int) RID_MAX; i++) + for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++) { if (ridpointers[i] == id) { @@ -7521,10 +7545,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) volatilep = !! RIDBIT_SETP (RID_VOLATILE, specbits) + TYPE_VOLATILE (type); staticp = 0; inlinep = !! RIDBIT_SETP (RID_INLINE, specbits); +#if 0 + /* This sort of redundancy is blessed in a footnote to the Sep 94 WP. */ if (constp > 1) warning ("duplicate `const'"); if (volatilep > 1) warning ("duplicate `volatile'"); +#endif virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits); if (RIDBIT_SETP (RID_STATIC, specbits)) @@ -7688,17 +7715,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) break; } - if (scanner == IDENTIFIER_AS_LIST (ridpointers [(int) RID_TYPEDEF])) - { - if (previous_declspec) - TREE_CHAIN (previous_declspec) - = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]); - else - declspecs - = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]); - } + if (previous_declspec) + TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner); else - TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC]; + declspecs = TREE_CHAIN (scanner); + + declspecs = tree_cons (NULL_TREE, ridpointers[(int) RID_STATIC], + declspecs); /* In the recursive call to grokdeclarator we need to know whether we are working on a signature-local typedef. */ @@ -7707,6 +7730,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) loc_typedecl = grokdeclarator (declarator, declspecs, FIELD, 0, NULL_TREE); + + if (previous_declspec) + TREE_CHAIN (previous_declspec) = scanner; if (loc_typedecl != error_mark_node) { @@ -7714,6 +7740,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) register int *pi; TREE_SET_CODE (loc_typedecl, TYPE_DECL); + /* This is the same field as DECL_ARGUMENTS, which is set for + function typedefs by the above grokdeclarator. */ + DECL_NESTED_TYPENAME (loc_typedecl) = 0; pi = (int *) permalloc (sizeof (struct lang_decl_flags)); while (i > 0) @@ -7983,7 +8012,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) type = build_cplus_array_type (type, itype); if (constp || volatilep) - type = c_build_type_variant (type, constp, volatilep); + type = cp_build_type_variant (type, constp, volatilep); ctype = NULL_TREE; } @@ -7992,6 +8021,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) case CALL_EXPR: { tree arg_types; + int funcdecl_p; + tree inner_parms = TREE_OPERAND (declarator, 1); + tree inner_decl = TREE_OPERAND (declarator, 0); /* Declaring a function type. Make sure we have a valid type for the function to return. */ @@ -8005,7 +8037,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (constp || volatilep) { - type = c_build_type_variant (type, constp, volatilep); + type = cp_build_type_variant (type, constp, volatilep); if (IS_AGGR_TYPE (type)) build_pointer_type (type); constp = 0; @@ -8026,8 +8058,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) type = integer_type_node; } + if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) + inner_decl = TREE_OPERAND (inner_decl, 1); + + /* Say it's a definition only for the CALL_EXPR + closest to the identifier. */ + funcdecl_p = + inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE; + if (ctype == NULL_TREE && decl_context == FIELD + && funcdecl_p && (friendp == 0 || dname == current_class_name)) ctype = current_class_type; @@ -8141,27 +8182,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) /* Construct the function type and go to the next inner layer of declarator. */ - { - int funcdef_p; - tree inner_parms = TREE_OPERAND (declarator, 1); - tree inner_decl = TREE_OPERAND (declarator, 0); - - declarator = TREE_OPERAND (declarator, 0); - - if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) - inner_decl = TREE_OPERAND (inner_decl, 1); - - /* Say it's a definition only for the CALL_EXPR - closest to the identifier. */ - funcdef_p = - (inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE) - ? funcdef_flag : 0; + declarator = TREE_OPERAND (declarator, 0); - /* FIXME: This is where default args should be fully - processed. */ + /* FIXME: This is where default args should be fully + processed. */ - arg_types = grokparms (inner_parms, funcdef_p); - } + arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0); if (declarator) { @@ -8216,7 +8242,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) signature pointer/reference itself. */ if (! IS_SIGNATURE (type)) { - type = c_build_type_variant (type, constp, volatilep); + type = cp_build_type_variant (type, constp, volatilep); if (IS_AGGR_TYPE (type)) build_pointer_type (type); constp = 0; @@ -8511,7 +8537,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) /* Note that the grammar rejects storage classes in typenames, fields or parameters. */ if (constp || volatilep) - type = c_build_type_variant (type, constp, volatilep); + type = cp_build_type_variant (type, constp, volatilep); /* If the user declares "struct {...} foo" then `foo' will have an anonymous name. Fill that name in now. Nothing can @@ -8600,7 +8626,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (IS_SIGNATURE (type)) error ("`const' or `volatile' specified with signature type"); else - type = c_build_type_variant (type, constp, volatilep); + type = cp_build_type_variant (type, constp, volatilep); /* Special case: "friend class foo" looks like a TYPENAME context. */ if (friendp) @@ -8682,7 +8708,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) { /* Transfer const-ness of array into that of type pointed to. */ type = build_pointer_type - (c_build_type_variant (TREE_TYPE (type), constp, volatilep)); + (cp_build_type_variant (TREE_TYPE (type), constp, volatilep)); volatilep = constp = 0; } else if (TREE_CODE (type) == FUNCTION_TYPE) @@ -8961,14 +8987,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) type = build_cplus_method_type (build_type_variant (ctype, constp, volatilep), TREE_TYPE (type), TYPE_ARG_TYPES (type)); - /* Record presence of `static'. In C++, `inline' is like `static'. - Methods of classes should be public, unless we're dropping them - into some other file, so we don't clear TREE_PUBLIC for them. */ + /* Record presence of `static'. In C++, `inline' is like `static'. */ publicp - = ((ctype - && CLASSTYPE_INTERFACE_KNOWN (ctype)) - || !(RIDBIT_SETP (RID_STATIC, specbits) - || RIDBIT_SETP (RID_INLINE, specbits))); + = !(RIDBIT_SETP (RID_STATIC, specbits) + || RIDBIT_SETP (RID_INLINE, specbits)); decl = grokfndecl (ctype, type, original_name, virtualp, flags, quals, @@ -8989,7 +9011,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) declaring main to be static. */ if (TREE_CODE (type) == METHOD_TYPE) { - cp_error_at ("cannot declare member function `%D' to have static linkage", decl); + cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl); illegal_static = 1; } else if (! ctype @@ -9791,6 +9813,7 @@ xref_defn_tag (code_type_node, name, binfo) if (! ANON_AGGRNAME_P (name)) { register tree type_decl = build_decl (TYPE_DECL, ncp, rv); + SET_DECL_ARTIFICIAL (type_decl); #ifdef DWARF_DEBUGGING_INFO /* Mark the TYPE_DECL node created just above as a gratuitous one so that dwarfout.c will know not to generate a TAG_typedef DIE @@ -9939,48 +9962,21 @@ xref_tag (code_type_node, name, binfo, globalize) } else { - extern tree pending_vtables; struct binding_level *old_b = class_binding_level; - int needs_writing; ref = make_lang_type (code); - /* A signature type will contain the fields of the signature - table. Therefore, it's not only an interface. */ if (tag_code == signature_type) { SET_SIGNATURE (ref); + /* Since a signature type will be turned into the type + of signature tables, it's not only an interface. */ CLASSTYPE_INTERFACE_ONLY (ref) = 0; - CLASSTYPE_INTERFACE_UNKNOWN (ref) = 0; - } - - /* Record how to set the access of this class's - virtual functions. If write_virtuals == 2 or 3, then - inline virtuals are ``extern inline''. */ - switch (write_virtuals) - { - case 0: - case 1: - needs_writing = 1; - break; - case 2: - needs_writing = !! value_member (name, pending_vtables); - break; - case 3: - needs_writing = ! CLASSTYPE_INTERFACE_ONLY (ref) - && CLASSTYPE_INTERFACE_KNOWN (ref); - break; - default: - needs_writing = 0; + SET_CLASSTYPE_INTERFACE_KNOWN (ref); + /* A signature doesn't have a vtable. */ + CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = 0; } - /* Signatures don't have a vtable. As long as we don't have default - implementations, they behave as if `write_virtuals' were 3. */ - if (tag_code == signature_type) - CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = 0; - else - CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = needs_writing; - #ifdef NONNESTED_CLASSES /* Class types don't nest the way enums do. */ class_binding_level = (struct binding_level *)0; @@ -10108,6 +10104,7 @@ xref_tag (code_type_node, name, binfo, globalize) TREE_VIA_PUBLIC (base_binfo) = via_public; TREE_VIA_PROTECTED (base_binfo) = via_protected; TREE_VIA_VIRTUAL (base_binfo) = via_virtual; + BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref); SET_CLASSTYPE_MARKED (basetype); #if 0 @@ -10209,6 +10206,7 @@ start_enum (name) TREE_ADDRESSABLE (b->tags) = 1; current_local_enum = NULL_TREE; +#if 0 /* This stuff gets cleared in finish_enum anyway. */ if (TYPE_VALUES (enumtype) != NULL_TREE) /* Completely replace its old definition. The old enumerators remain defined, however. */ @@ -10221,7 +10219,8 @@ start_enum (name) TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node); TYPE_SIZE (enumtype) = NULL_TREE; - fixup_unsigned_type (enumtype); + fixup_signed_type (enumtype); +#endif /* We copy this value because enumerated type constants are really of the type of the enumerator, not integer_type_node. */ @@ -10241,84 +10240,89 @@ tree finish_enum (enumtype, values) register tree enumtype, values; { - register tree pair, tem; - register HOST_WIDE_INT maxvalue = 0; - register HOST_WIDE_INT minvalue = 0; - register HOST_WIDE_INT i; - + register tree minnode, maxnode; /* Calculate the maximum value of any enumerator in this type. */ if (values) { + register tree pair; + register tree value = DECL_INITIAL (TREE_VALUE (values)); + /* Speed up the main loop by performing some precalculations */ - - HOST_WIDE_INT value; TREE_TYPE (TREE_VALUE (values)) = enumtype; - TREE_TYPE (DECL_INITIAL (TREE_VALUE (values))) = enumtype; - TREE_VALUE (values) = DECL_INITIAL (TREE_VALUE (values)); - value = TREE_INT_CST_LOW (TREE_VALUE (values)); - minvalue = maxvalue = value; + TREE_TYPE (value) = enumtype; + TREE_VALUE (values) = value; + minnode = maxnode = value; for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair)) { + value = DECL_INITIAL (TREE_VALUE (pair)); TREE_TYPE (TREE_VALUE (pair)) = enumtype; - TREE_TYPE (DECL_INITIAL (TREE_VALUE (pair))) = enumtype; - TREE_VALUE (pair) = DECL_INITIAL (TREE_VALUE (pair)); - value = TREE_INT_CST_LOW (TREE_VALUE (pair)); - if (value > maxvalue) - maxvalue = value; - else if (value < minvalue) - minvalue = value; + TREE_TYPE (value) = enumtype; + TREE_VALUE (pair) = value; + if (tree_int_cst_lt (maxnode, value)) + maxnode = value; + else if (tree_int_cst_lt (value, minnode)) + minnode = value; } } + else + maxnode = minnode = integer_zero_node; TYPE_VALUES (enumtype) = values; - if (flag_short_enums) - { - /* Determine the precision this type needs, lay it out, and define - it. */ - - /* First reset precision */ - TYPE_PRECISION (enumtype) = 0; - - for (i = maxvalue; i; i >>= 1) - TYPE_PRECISION (enumtype)++; - - if (!TYPE_PRECISION (enumtype)) - TYPE_PRECISION (enumtype) = 1; - - /* Cancel the laying out previously done for the enum type, - so that fixup_unsigned_type will do it over. */ - TYPE_SIZE (enumtype) = NULL_TREE; + { + int unsignedp = tree_int_cst_sgn (minnode) >= 0; + int lowprec = min_precision (minnode, unsignedp); + int highprec = min_precision (maxnode, unsignedp); + int precision = MAX (lowprec, highprec); + + if (! flag_short_enums && precision < TYPE_PRECISION (integer_type_node)) + precision = TYPE_PRECISION (integer_type_node); + + + /* + * The following code is unnecessary since the function + * type_promotes_to deals correctly with promotion of enums of + * underlying unsigned types to signed integer types. + * Moreover, it causes an enum bitfield to require one more bit of + * storage than defined by the ANSI/ISO C++ resolution section r.7.2 + * which defines the range of an enum. + */ +#if 0 + /* Unlike the C frontend, we prefer signed types. */ + if (unsignedp && int_fits_type_p (maxnode, type_for_size (precision, 0))) + unsignedp = 0; +#endif + TYPE_PRECISION (enumtype) = precision; + TYPE_SIZE (enumtype) = NULL_TREE; + if (unsignedp) fixup_unsigned_type (enumtype); - } - - TREE_INT_CST_LOW (TYPE_MAX_VALUE (enumtype)) = maxvalue; + else + fixup_signed_type (enumtype); + } - /* An enum can have some negative values; then it is signed. */ - if (minvalue < 0) - { - TREE_INT_CST_LOW (TYPE_MIN_VALUE (enumtype)) = minvalue; - TREE_INT_CST_HIGH (TYPE_MIN_VALUE (enumtype)) = -1; - TREE_UNSIGNED (enumtype) = 0; - } if (flag_cadillac) cadillac_finish_enum (enumtype); - /* Fix up all variant types of this enum type. */ - for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem)) - { - TYPE_VALUES (tem) = TYPE_VALUES (enumtype); - TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype); - TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype); - TYPE_SIZE (tem) = TYPE_SIZE (enumtype); - TYPE_MODE (tem) = TYPE_MODE (enumtype); - TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype); - TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); - TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype); - } + { + register tree tem; + + /* Fix up all variant types of this enum type. */ + for (tem = TYPE_MAIN_VARIANT (enumtype); tem; + tem = TYPE_NEXT_VARIANT (tem)) + { + TYPE_VALUES (tem) = TYPE_VALUES (enumtype); + TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype); + TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype); + TYPE_SIZE (tem) = TYPE_SIZE (enumtype); + TYPE_MODE (tem) = TYPE_MODE (enumtype); + TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype); + TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype); + TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype); + } + } /* Finish debugging output for this type. */ #if 0 @@ -10678,15 +10682,14 @@ start_function (declspecs, declarator, raises, pre_parsed_p) /* If this function belongs to an interface, it is public. If it belongs to someone else's interface, it is also external. It doesn't matter whether it's inline or not. */ - if (interface_unknown == 0) + if (interface_unknown == 0 + && ! TREE_PUBLIC (decl1)) { TREE_PUBLIC (decl1) = 1; DECL_EXTERNAL (decl1) = (interface_only || (DECL_INLINE (decl1) && ! flag_implement_inlines)); } - else if (DECL_EXPLICIT_INSTANTIATION (decl1)) - /* PUBLIC and EXTERNAL set by do_*_instantiation */; else { /* This is a definition, not a reference. @@ -10695,7 +10698,10 @@ start_function (declspecs, declarator, raises, pre_parsed_p) defining how to inline. So set DECL_EXTERNAL in that case. */ DECL_EXTERNAL (decl1) = current_extern_inline; - DECL_DEFER_OUTPUT (decl1) = DECL_INLINE (decl1); + DECL_DEFER_OUTPUT (decl1) + = DECL_INLINE (decl1) && ! TREE_PUBLIC (decl1) + && (DECL_FUNCTION_MEMBER_P (decl1) + || DECL_TEMPLATE_INSTANTIATION (decl1)); } if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)) @@ -11023,59 +11029,6 @@ store_return_init (return_id, init) } } -#if 0 -/* Generate code for default X() constructor. */ -static void -build_default_constructor (fndecl) - tree fndecl; -{ - int i = CLASSTYPE_N_BASECLASSES (current_class_type); - tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); - tree fields = TYPE_FIELDS (current_class_type); - tree binfos = TYPE_BINFO_BASETYPES (current_class_type); - - if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) - parm = TREE_CHAIN (parm); - parm = DECL_REFERENCE_SLOT (parm); - - while (--i >= 0) - { - tree basetype = TREE_VEC_ELT (binfos, i); - if (TYPE_HAS_INIT_REF (basetype)) - { - tree name = TYPE_NAME (basetype); - if (TREE_CODE (name) == TYPE_DECL) - name = DECL_NAME (name); - current_base_init_list = tree_cons (name, parm, current_base_init_list); - } - } - for (; fields; fields = TREE_CHAIN (fields)) - { - tree name, init; - if (TREE_STATIC (fields)) - continue; - if (TREE_CODE (fields) != FIELD_DECL) - continue; - if (DECL_NAME (fields)) - { - if (VFIELD_NAME_P (DECL_NAME (fields))) - continue; - if (VBASE_NAME_P (DECL_NAME (fields))) - continue; - - /* True for duplicate members. */ - if (IDENTIFIER_CLASS_VALUE (DECL_NAME (fields)) != fields) - continue; - } - - init = build (COMPONENT_REF, TREE_TYPE (fields), parm, fields); - init = build_tree_list (NULL_TREE, init); - - current_member_init_list - = tree_cons (DECL_NAME (fields), init, current_member_init_list); - } -} -#endif /* Finish up a function declaration and compile that function all the way to assembler language output. The free the storage @@ -11529,20 +11482,19 @@ finish_function (lineno, call_poplevel) /* So we can tell if jump_optimize sets it to 1. */ can_reach_end = 0; - /* ??? Compensate for Sun brain damage in dealing with data segments - of PIC code. */ - if (flag_pic - && (DECL_CONSTRUCTOR_P (fndecl) - || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) - && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype))) - DECL_INLINE (fndecl) = 0; - if (DECL_EXTERNAL (fndecl) /* This function is just along for the ride. If we can make it inline, that's great. Otherwise, just punt it. */ && (DECL_INLINE (fndecl) == 0 || flag_no_inline - || function_cannot_inline_p (fndecl))) + || function_cannot_inline_p (fndecl) + /* ??? Compensate for Sun brain damage in dealing with + data segments of PIC code. */ + || (flag_pic + && (DECL_CONSTRUCTOR_P (fndecl) + || DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) + && CLASSTYPE_NEEDS_VIRTUAL_REINIT (TYPE_METHOD_BASETYPE (fntype))))) + { extern int rtl_dump_and_exit; int old_rtl_dump_and_exit = rtl_dump_and_exit; @@ -11564,8 +11516,8 @@ finish_function (lineno, call_poplevel) rest_of_compilation (fndecl); } - if (DECL_INLINE (fndecl) - && !TREE_ASM_WRITTEN (fndecl) && DECL_FUNCTION_MEMBER_P (fndecl)) + if (DECL_INLINE (fndecl) && !TREE_ASM_WRITTEN (fndecl) + && DECL_DEFER_OUTPUT (fndecl)) { mark_inline_for_output (fndecl); } |