aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/decl.c
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2005-07-09 22:14:08 +0000
committerMike Stump <mrs@apple.com>2005-07-09 22:14:08 +0000
commitc68e95c15a69b5be7bc8cf06906b16a8dee7036c (patch)
treecaf3610812070c8e7ed46bedcb0f6dccb1325afd /gcc/cp/decl.c
parent2ca692836290d5be068cd56899e9b87f58ca8d6f (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.c164
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);