diff options
author | Mike Stump <mrs@apple.com> | 2005-07-09 22:14:08 +0000 |
---|---|---|
committer | Mike Stump <mrs@apple.com> | 2005-07-09 22:14:08 +0000 |
commit | c68e95c15a69b5be7bc8cf06906b16a8dee7036c (patch) | |
tree | caf3610812070c8e7ed46bedcb0f6dccb1325afd /gcc/cp/decl.c | |
parent | 2ca692836290d5be068cd56899e9b87f58ca8d6f (diff) |
Merge in gcc_4_0_0_release to gcc_4_0_1_release
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/apple-local-200502-branch@101836 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 164 |
1 files changed, 87 insertions, 77 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index be5561835c8..a6e6989c8a7 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1685,13 +1685,14 @@ duplicate_decls (tree newdecl, tree olddecl) DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl); DECL_TEMPLATE_INSTANTIATED (newdecl) |= DECL_TEMPLATE_INSTANTIATED (olddecl); - /* If the OLDDECL is an implicit instantiation, then the NEWDECL - must be too. But, it may not yet be marked as such if the - caller has created NEWDECL, but has not yet figured out that - it is a redeclaration. */ - if (DECL_IMPLICIT_INSTANTIATION (olddecl) - && !DECL_USE_TEMPLATE (newdecl)) - SET_DECL_IMPLICIT_INSTANTIATION (newdecl); + + /* If the OLDDECL is an instantiation and/or specialization, + then the NEWDECL must be too. But, it may not yet be marked + as such if the caller has created NEWDECL, but has not yet + figured out that it is a redeclaration. */ + if (!DECL_USE_TEMPLATE (newdecl)) + DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl); + /* Don't really know how much of the language-specific values we should copy from old to new. */ DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl); @@ -4038,6 +4039,8 @@ maybe_deduce_size_from_array_init (tree decl, tree init) if (failure == 3) error ("zero-size array %qD", decl); + cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl); + layout_decl (decl, 0); } } @@ -5701,7 +5704,7 @@ grokfndecl (tree ctype, } if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) - grok_op_properties (decl, friendp, /*complain=*/true); + grok_op_properties (decl, /*complain=*/true); if (ctype && decl_function_context (decl)) DECL_NO_STATIC_CHAIN (decl) = 1; @@ -7133,30 +7136,7 @@ grokdeclarator (const cp_declarator *declarator, else { if (decl_context == FIELD) - { - tree tmp = NULL_TREE; - int op = 0; - - if (declarator) - { - /* Avoid trying to get an operand off an identifier node. */ - if (declarator->kind != cdk_id) - tmp = declarator->declarator->u.id.unqualified_name; - else - tmp = declarator->u.id.unqualified_name; - op = IDENTIFIER_OPNAME_P (tmp); - if (IDENTIFIER_TYPENAME_P (tmp)) - { - if (is_typename_at_global_scope (tmp)) - name = IDENTIFIER_POINTER (tmp); - else - name = "<invalid operator>"; - } - } - error ("storage class specified for %s %qs", - op ? "member operator" : "field", - name); - } + error ("storage class specified for %qs", name); else { if (decl_context == PARM || decl_context == CATCHPARM) @@ -8790,7 +8770,7 @@ unary_op_p (enum tree_code code) errors are issued for invalid declarations. */ bool -grok_op_properties (tree decl, int friendp, bool complain) +grok_op_properties (tree decl, bool complain) { tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl)); tree argtype; @@ -8799,6 +8779,7 @@ grok_op_properties (tree decl, int friendp, bool complain) enum tree_code operator_code; int arity; bool ok; + tree class_type; /* Assume that the declaration is valid. */ ok = true; @@ -8809,8 +8790,9 @@ grok_op_properties (tree decl, int friendp, bool complain) argtype = TREE_CHAIN (argtype)) ++arity; - if (current_class_type == NULL_TREE) - friendp = 1; + class_type = DECL_CONTEXT (decl); + if (class_type && !CLASS_TYPE_P (class_type)) + class_type = NULL_TREE; if (DECL_CONV_FN_P (decl)) operator_code = TYPE_EXPR; @@ -8839,30 +8821,28 @@ grok_op_properties (tree decl, int friendp, bool complain) gcc_assert (operator_code != LAST_CPLUS_TREE_CODE); SET_OVERLOADED_OPERATOR_CODE (decl, operator_code); - if (! friendp) - { - switch (operator_code) - { - case NEW_EXPR: - TYPE_HAS_NEW_OPERATOR (current_class_type) = 1; - break; + if (class_type) + switch (operator_code) + { + case NEW_EXPR: + TYPE_HAS_NEW_OPERATOR (class_type) = 1; + break; - case DELETE_EXPR: - TYPE_GETS_DELETE (current_class_type) |= 1; - break; + case DELETE_EXPR: + TYPE_GETS_DELETE (class_type) |= 1; + break; - case VEC_NEW_EXPR: - TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1; - break; + case VEC_NEW_EXPR: + TYPE_HAS_ARRAY_NEW_OPERATOR (class_type) = 1; + break; - case VEC_DELETE_EXPR: - TYPE_GETS_DELETE (current_class_type) |= 2; - break; + case VEC_DELETE_EXPR: + TYPE_GETS_DELETE (class_type) |= 2; + break; - default: - break; - } - } + default: + break; + } /* [basic.std.dynamic.allocation]/1: @@ -8936,32 +8916,37 @@ grok_op_properties (tree decl, int friendp, bool complain) if (operator_code == CALL_EXPR) return ok; - if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl)) + if (IDENTIFIER_TYPENAME_P (name) + && ! DECL_TEMPLATE_INFO (decl) + && warn_conversion + /* Warn only declaring the function; there is no need to + warn again about out-of-class definitions. */ + && class_type == current_class_type) { tree t = TREE_TYPE (name); - if (! friendp) - { - int ref = (TREE_CODE (t) == REFERENCE_TYPE); - const char *what = 0; + int ref = (TREE_CODE (t) == REFERENCE_TYPE); + const char *what = 0; - if (ref) - t = TYPE_MAIN_VARIANT (TREE_TYPE (t)); + if (ref) + t = TYPE_MAIN_VARIANT (TREE_TYPE (t)); - if (TREE_CODE (t) == VOID_TYPE) - what = "void"; - else if (t == current_class_type) + if (TREE_CODE (t) == VOID_TYPE) + what = "void"; + else if (class_type) + { + if (t == current_class_type) what = "the same type"; /* Don't force t to be complete here. */ else if (IS_AGGR_TYPE (t) && COMPLETE_TYPE_P (t) - && DERIVED_FROM_P (t, current_class_type)) + && DERIVED_FROM_P (t, class_type)) what = "a base class"; - - if (what && warn_conversion) - warning ("conversion to %s%s will never use a type " - "conversion operator", - ref ? "a reference to " : "", what); } + + if (what) + warning ("conversion to %s%s will never use a type " + "conversion operator", + ref ? "a reference to " : "", what); } if (operator_code == COND_EXPR) { @@ -9219,7 +9204,6 @@ check_elaborated_type_specifier (enum tag_types tag_code, void f(class C); // No template header here then the required template argument is missing. */ - error ("template argument required for %<%s %T%>", tag_name (tag_code), DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))); @@ -9241,7 +9225,19 @@ lookup_and_check_tag (enum tag_types tag_code, tree name, tree t; tree decl; if (scope == ts_global) - decl = lookup_name (name, 2); + { + /* First try ordinary name lookup, ignoring hidden class name + injected via friend declaration. */ + decl = lookup_name (name, 2); + /* If that fails, the name will be placed in the smallest + non-class, non-function-prototype scope according to 3.3.1/5. + We may already have a hidden name declared as friend in this + scope. So lookup again but not ignoring hidden name. + If we find one, that name will be made visible rather than + creating a new tag. */ + if (!decl) + decl = lookup_type_scope (name, ts_within_enclosing_non_class); + } else decl = lookup_type_scope (name, scope); @@ -9401,8 +9397,7 @@ xref_tag (enum tag_types tag_code, tree name, { t = make_aggr_type (code); TYPE_CONTEXT (t) = context; - /* pushtag only cares whether SCOPE is zero or not. */ - t = pushtag (name, t, scope != ts_current); + t = pushtag (name, t, scope); } } else @@ -9416,6 +9411,20 @@ xref_tag (enum tag_types tag_code, tree name, error ("redeclaration of %qT as a non-template", t); t = error_mark_node; } + + /* Make injected friend class visible. */ + if (scope != ts_within_enclosing_non_class + && hidden_name_p (TYPE_NAME (t))) + { + DECL_ANTICIPATED (TYPE_NAME (t)) = 0; + DECL_FRIEND_P (TYPE_NAME (t)) = 0; + + if (TYPE_TEMPLATE_INFO (t)) + { + DECL_ANTICIPATED (TYPE_TI_TEMPLATE (t)) = 0; + DECL_FRIEND_P (TYPE_TI_TEMPLATE (t)) = 0; + } + } } POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t); @@ -9657,7 +9666,7 @@ start_enum (tree name) name = make_anon_name (); enumtype = make_node (ENUMERAL_TYPE); - enumtype = pushtag (name, enumtype, 0); + enumtype = pushtag (name, enumtype, /*tag_scope=*/ts_current); } return enumtype; @@ -10037,7 +10046,8 @@ start_preparsed_function (tree decl1, tree attrs, int flags) int doing_friend = 0; struct cp_binding_level *bl; tree current_function_parms; - struct c_fileinfo *finfo = get_fileinfo (lbasename (input_filename)); + struct c_fileinfo *finfo + = get_fileinfo (lbasename (LOCATION_FILE (DECL_SOURCE_LOCATION (decl1)))); /* Sanity check. */ gcc_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE); |