diff options
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 214 |
1 files changed, 138 insertions, 76 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index aad3dfb..1ef0ebd 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1664,13 +1664,10 @@ set_nested_typename (decl, classname, name, type) type_decl = build_decl (TYPE_DECL, nested, type); DECL_NESTED_TYPENAME (type_decl) = nested; 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 for it. */ - if (write_symbols == DWARF_DEBUG) - DECL_IGNORED_P (type_decl) = 1; -#endif /* 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 for it, and + sdbout.c won't try to output a .def for "::foo". */ + DECL_IGNORED_P (type_decl) = 1; /* Remove this when local classes are fixed. */ SET_IDENTIFIER_TYPE_VALUE (nested, type); @@ -2447,21 +2444,16 @@ duplicate_decls (newdecl, olddecl) TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype; /* Lay the type out, unless already done. */ - if (oldtype != TREE_TYPE (newdecl)) - { - if (TREE_TYPE (newdecl) != error_mark_node) - layout_type (TREE_TYPE (newdecl)); - if (TREE_CODE (newdecl) != FUNCTION_DECL - && TREE_CODE (newdecl) != TYPE_DECL - && TREE_CODE (newdecl) != CONST_DECL - && TREE_CODE (newdecl) != TEMPLATE_DECL) - layout_decl (newdecl, 0); - } - else - { - /* Since the type is OLDDECL's, make OLDDECL's size go with. */ - DECL_SIZE (newdecl) = DECL_SIZE (olddecl); - } + if (oldtype != TREE_TYPE (newdecl) + && TREE_TYPE (newdecl) != error_mark_node) + layout_type (TREE_TYPE (newdecl)); + + if (TREE_CODE (newdecl) == VAR_DECL + || TREE_CODE (newdecl) == PARM_DECL + || TREE_CODE (newdecl) == RESULT_DECL + || TREE_CODE (newdecl) == FIELD_DECL + || TREE_CODE (newdecl) == TYPE_DECL) + layout_decl (newdecl, 0); /* Merge the type qualifiers. */ if (TREE_READONLY (newdecl)) @@ -7660,7 +7652,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (TREE_CODE (type) == REAL_TYPE) error ("short, signed or unsigned invalid for `%s'", name); - else if (TREE_CODE (type) != INTEGER_TYPE || type == wchar_type_node) + else if (TREE_CODE (type) != INTEGER_TYPE) error ("long, short, signed or unsigned invalid for `%s'", name); else if (RIDBIT_SETP (RID_LONG, specbits) && RIDBIT_SETP (RID_SHORT, specbits)) @@ -7780,6 +7772,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) error ("non-object member `%s' cannot be declared `mutable'", name); RIDBIT_RESET (RID_MUTABLE, specbits); } + else if (constp) + { + error ("const `%s' cannot be declared `mutable'", name); + RIDBIT_RESET (RID_MUTABLE, specbits); + } else if (staticp) { error ("static `%s' cannot be declared `mutable'", name); @@ -7820,7 +7817,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) } /* Give error if `virtual' is used outside of class declaration. */ - if (virtualp && current_class_name == NULL_TREE) + if (virtualp + && (current_class_name == NULL_TREE || decl_context != FIELD)) { error ("virtual outside class declaration"); virtualp = 0; @@ -7972,14 +7970,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) { if (decl_context == FIELD) { - tree tmp = TREE_OPERAND (declarator, 0); - register int op = IDENTIFIER_OPNAME_P (tmp); + tree tmp = NULL_TREE; + register int op = 0; + + if (declarator) + { + tmp = TREE_OPERAND (declarator, 0); + op = IDENTIFIER_OPNAME_P (tmp); + } error ("storage class specified for %s `%s'", IS_SIGNATURE (current_class_type) ? (op ? "signature member operator" : "signature member function") - : (op ? "member operator" : "structure field"), + : (op ? "member operator" : "field"), op ? operator_name_string (tmp) : name); } else @@ -8092,6 +8096,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) { register tree itype = NULL_TREE; register tree size = TREE_OPERAND (declarator, 1); + /* The index is a signed object `sizetype' bits wide. */ + tree index_type = signed_type (sizetype); declarator = TREE_OPERAND (declarator, 0); @@ -8181,8 +8187,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) cp_error ("size of array `%D' is negative", dname); size = integer_one_node; } - itype = build_index_type (size_binop (MINUS_EXPR, size, - integer_one_node)); } else { @@ -8194,15 +8198,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) else cp_pedwarn ("ANSI C++ forbids variable-size array"); } - dont_grok_size: - itype = - build_binary_op (MINUS_EXPR, size, integer_one_node, 1); /* Make sure the array size remains visibly nonconstant - even if it is (eg) a const variable with known value. */ + even if it is (eg) a const variable with known value. */ size_varies = 1; - itype = variable_size (itype); - itype = build_index_type (itype); } + + dont_grok_size: + itype = + fold (build_binary_op (MINUS_EXPR, + convert (index_type, size), + convert (index_type, + integer_one_node), 1)); + if (! TREE_CONSTANT (itype)) + itype = variable_size (itype); + itype = build_index_type (itype); resume_momentary (yes); } @@ -8262,10 +8271,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF) inner_decl = TREE_OPERAND (inner_decl, 1); + /* Pick up type qualifiers which should be applied to `this'. */ + quals = TREE_OPERAND (declarator, 2); + /* Say it's a definition only for the CALL_EXPR closest to the identifier. */ funcdecl_p = - inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE; + inner_decl && (TREE_CODE (inner_decl) == IDENTIFIER_NODE + || TREE_CODE (inner_decl) == BIT_NOT_EXPR); if (ctype == NULL_TREE && decl_context == FIELD @@ -8289,14 +8302,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) may not be static. */ if (staticp == 2) error ("destructor cannot be static member function"); - if (TYPE_READONLY (type)) - { - error ("destructors cannot be declared `const'"); - return void_type_node; - } - if (TYPE_VOLATILE (type)) + if (quals) { - error ("destructors cannot be declared `volatile'"); + error ("destructors cannot be declared `const' or `volatile'"); return void_type_node; } if (decl_context == FIELD) @@ -8320,16 +8328,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) pedwarn ("constructors cannot be declared virtual"); virtualp = 0; } - if (TYPE_READONLY (type)) + if (quals) { - error ("constructors cannot be declared `const'"); + error ("constructors cannot be declared `const' or `volatile'"); return void_type_node; } - if (TYPE_VOLATILE (type)) - { - error ("constructors cannot be declared `volatile'"); - return void_type_node; - } { RID_BIT_TYPE tmp_bits; bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof(RID_BIT_TYPE)); @@ -8358,20 +8361,22 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (decl_context == FIELD) staticp = 0; } - else if (friendp && virtualp) + else if (friendp) { - /* Cannot be both friend and virtual. */ - error ("virtual functions cannot be friends"); - RIDBIT_RESET (RID_FRIEND, specbits); - friendp = 0; + if (initialized) + error ("can't initialize friend function `%s'", name); + if (virtualp) + { + /* Cannot be both friend and virtual. */ + error ("virtual functions cannot be friends"); + RIDBIT_RESET (RID_FRIEND, specbits); + friendp = 0; + } } if (decl_context == NORMAL && friendp) error ("friend declaration not in class definition"); - /* Pick up type qualifiers which should be applied to `this'. */ - quals = TREE_OPERAND (declarator, 2); - /* Traditionally, declaring return type float means double. */ if (flag_traditional @@ -8836,13 +8841,28 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) /* Special case: "friend class foo" looks like a TYPENAME context. */ if (friendp) { - /* A friendly class? */ - if (current_class_type) - make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); - else - error("trying to make class `%s' a friend of global scope", - TYPE_NAME_STRING (type)); - type = void_type_node; + if (volatilep) + { + cp_error ("`volatile' specified for friend class declaration"); + volatilep = 0; + } + if (inlinep) + { + cp_error ("`inline' specified for friend class declaration"); + inlinep = 0; + } + + /* Only try to do this stuff if we didn't already give up. */ + if (type != integer_type_node) + { + /* A friendly class? */ + if (current_class_type) + make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); + else + error ("trying to make class `%s' a friend of global scope", + TYPE_NAME_STRING (type)); + type = void_type_node; + } } else if (quals) { @@ -8878,7 +8898,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) if (TYPE_MAIN_VARIANT (type) == void_type_node && decl_context != PARM) { - if (TREE_CODE (declarator) == IDENTIFIER_NODE) + if (! declarator) + error ("unnamed variable or field declared void"); + else if (TREE_CODE (declarator) == IDENTIFIER_NODE) { if (IDENTIFIER_OPNAME_P (declarator)) #if 0 /* How could this happen? */ @@ -8921,6 +8943,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) type = build_pointer_type (type); else if (TREE_CODE (type) == OFFSET_TYPE) type = build_pointer_type (type); + else if (type == void_type_node && declarator) + { + error ("declaration of `%s' as void", name); + return NULL_TREE; + } decl = build_decl (PARM_DECL, declarator, type); @@ -9030,7 +9057,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) else if (TYPE_SIZE (type) == NULL_TREE && !staticp && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0)) { - cp_error ("field `%D' has incomplete type", declarator); + if (declarator) + cp_error ("field `%D' has incomplete type", declarator); + else + cp_error ("name `%T' has incomplete type", type); /* If we're instantiating a template, tell them which instantiation made the field's type be incomplete. */ @@ -9302,6 +9332,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises) staticp = 0; RIDBIT_RESET (RID_STATIC, specbits); } + if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl)) + { + cp_error ("static member `%D' declared `register'", decl); + RIDBIT_RESET (RID_REGISTER, specbits); + } if (RIDBIT_SETP (RID_EXTERN, specbits)) { cp_error ("cannot explicitly declare member `%#D' to have extern linkage", @@ -9583,7 +9618,8 @@ grokparms (first_parm, funcdef_flag) any_init++; if (TREE_CODE (init) == SAVE_EXPR) PARM_DECL_EXPR (init) = 1; - else if (TREE_CODE (init) == VAR_DECL) + else if (TREE_CODE (init) == VAR_DECL + || TREE_CODE (init) == PARM_DECL) { if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init))) { @@ -10656,6 +10692,8 @@ start_function (declspecs, declarator, raises, pre_parsed_p) original_result_rtx = NULL_RTX; current_function_obstack_index = 0; current_function_obstack_usage = 0; + base_init_insns = NULL_RTX; + protect_list = NULL_TREE; clear_temp_name (); @@ -10751,7 +10789,7 @@ start_function (declspecs, declarator, raises, pre_parsed_p) if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node) { if (pedantic || warn_return_type) - warning ("return type for `main' changed to integer type"); + pedwarn ("return type for `main' changed to integer type"); TREE_TYPE (decl1) = fntype = default_function_type; } warn_about_return_type = 0; @@ -10795,6 +10833,10 @@ start_function (declspecs, declarator, raises, pre_parsed_p) DECL_RESULT (decl1) = build_decl (RESULT_DECL, 0, TREE_TYPE (fntype)); } + if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype)) + && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype))) + abstract_virtuals_error (decl1, TREE_TYPE (fntype)); + if (warn_about_return_type) warning ("return-type defaults to `int'"); @@ -10824,14 +10866,19 @@ start_function (declspecs, declarator, raises, pre_parsed_p) DECL_EXTERNAL (decl1) = current_extern_inline; DECL_INTERFACE_KNOWN (decl1) = 1; } + else if (current_extern_inline) + { + /* `extern inline' acts like a declaration except for + defining how to inline. So set DECL_EXTERNAL in that case. */ + DECL_EXTERNAL (decl1) = 1; + DECL_INTERFACE_KNOWN (decl1) = 1; + } else { /* This is a definition, not a reference. - So normally clear DECL_EXTERNAL. - However, `extern inline' acts like a declaration except for - defining how to inline. So set DECL_EXTERNAL in that case. */ - DECL_EXTERNAL (decl1) = current_extern_inline; - + So clear DECL_EXTERNAL. */ + DECL_EXTERNAL (decl1) = 0; + if (DECL_INLINE (decl1) && (DECL_FUNCTION_MEMBER_P (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))) /* We know nothing yet */; @@ -11423,6 +11470,7 @@ finish_function (lineno, call_poplevel, nested) if (DECL_CONSTRUCTOR_P (current_function_decl)) { + end_protect_partials (); expand_label (ctor_label); ctor_label = NULL_TREE; @@ -11503,6 +11551,8 @@ finish_function (lineno, call_poplevel, nested) if (mark != get_last_insn ()) reorder_insns (next_insn (mark), get_last_insn (), last_parm_insn); + end_protect_partials (); + /* This is where the body of the constructor ends. */ expand_label (ctor_label); ctor_label = NULL_TREE; @@ -11643,8 +11693,14 @@ finish_function (lineno, call_poplevel, nested) /* Run the optimizers and output the assembler code for this function. */ rest_of_compilation (fndecl); - if (DECL_DEFER_OUTPUT (fndecl)) - mark_inline_for_output (fndecl); + if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl)) + { + /* Set DECL_EXTERNAL so that assemble_external will be called as + necessary. We'll clear it again in import_export_inline. */ + if (TREE_PUBLIC (fndecl)) + DECL_EXTERNAL (fndecl) = 1; + mark_inline_for_output (fndecl); + } if (ctype && TREE_ASM_WRITTEN (fndecl)) note_debug_info_needed (ctype); @@ -12121,7 +12177,9 @@ struct cp_function tree shadowed_labels; tree ctor_label; tree dtor_label; + tree protect_list; rtx result_rtx; + rtx base_init_insns; struct cp_function *next; struct binding_level *binding_level; }; @@ -12156,6 +12214,8 @@ push_cp_function_context (toplev) p->just_assigned_this = current_function_just_assigned_this; p->parms_stored = current_function_parms_stored; p->result_rtx = original_result_rtx; + p->base_init_insns = base_init_insns; + p->protect_list = protect_list; } /* Restore the variables used during compilation of a C++ function. */ @@ -12197,10 +12257,12 @@ pop_cp_function_context (toplev) current_binding_level = p->binding_level; ctor_label = p->ctor_label; dtor_label = p->dtor_label; + protect_list = p->protect_list; current_function_assigns_this = p->assigns_this; current_function_just_assigned_this = p->just_assigned_this; current_function_parms_stored = p->parms_stored; original_result_rtx = p->result_rtx; + base_init_insns = p->base_init_insns; free (p); } |