diff options
Diffstat (limited to 'contrib/gcc/cp/decl.c')
-rw-r--r-- | contrib/gcc/cp/decl.c | 242 |
1 files changed, 173 insertions, 69 deletions
diff --git a/contrib/gcc/cp/decl.c b/contrib/gcc/cp/decl.c index eb34d39ce8c0..6c7cece8eee1 100644 --- a/contrib/gcc/cp/decl.c +++ b/contrib/gcc/cp/decl.c @@ -1,6 +1,6 @@ /* Process declarations and variables for C++ compiler. Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com) This file is part of GCC. @@ -119,6 +119,7 @@ static void initialize_local_var (tree, tree); static void expand_static_init (tree, tree); static tree next_initializable_field (tree); static tree reshape_init (tree, tree *); +static bool reshape_init_array (tree, tree, tree *, tree); static tree build_typename_type (tree, tree, tree); /* Erroneous argument lists can use this *IFF* they do not modify it. */ @@ -1067,6 +1068,12 @@ decls_match (tree newdecl, tree olddecl) } else { + /* Need to check scope for variable declaration (VAR_DECL). + For typedef (TYPE_DECL), scope is ignored. */ + if (TREE_CODE (newdecl) == VAR_DECL + && CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)) + return 0; + if (TREE_TYPE (newdecl) == error_mark_node) types_match = TREE_TYPE (olddecl) == error_mark_node; else if (TREE_TYPE (olddecl) == NULL_TREE) @@ -1410,19 +1417,32 @@ duplicate_decls (tree newdecl, tree olddecl) /* One of the declarations is a template instantiation, and the other is not a template at all. That's OK. */ return NULL_TREE; - else if (TREE_CODE (newdecl) == NAMESPACE_DECL - && DECL_NAMESPACE_ALIAS (newdecl) - && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl)) - /* In [namespace.alias] we have: - - In a declarative region, a namespace-alias-definition can be - used to redefine a namespace-alias declared in that declarative - region to refer only to the namespace to which it already - refers. - - Therefore, if we encounter a second alias directive for the same - alias, we can just ignore the second directive. */ - return olddecl; + else if (TREE_CODE (newdecl) == NAMESPACE_DECL) + { + /* In [namespace.alias] we have: + + In a declarative region, a namespace-alias-definition can be + used to redefine a namespace-alias declared in that declarative + region to refer only to the namespace to which it already + refers. + + Therefore, if we encounter a second alias directive for the same + alias, we can just ignore the second directive. */ + if (DECL_NAMESPACE_ALIAS (newdecl) + && (DECL_NAMESPACE_ALIAS (newdecl) + == DECL_NAMESPACE_ALIAS (olddecl))) + return olddecl; + /* [namespace.alias] + + A namespace-name or namespace-alias shall not be declared as + the name of any other entity in the same declarative region. + A namespace-name defined at global scope shall not be + declared as the name of any other entity in any glogal scope + of the program. */ + error ("declaration of `namespace %D' conflicts with", newdecl); + cp_error_at ("previous declaration of `namespace %D' here", olddecl); + return error_mark_node; + } else { const char *errmsg = redeclaration_error_message (newdecl, olddecl); @@ -2009,7 +2029,8 @@ redeclaration_error_message (tree newdecl, tree olddecl) /* If both functions come from different namespaces, this is not a redeclaration - this is a conflict with a used function. */ if (DECL_NAMESPACE_SCOPE_P (olddecl) - && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl)) + && DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl) + && ! decls_match (olddecl, newdecl)) return "`%D' conflicts with used function"; /* We'll complain about linkage mismatches in @@ -3690,12 +3711,12 @@ start_decl (tree declarator, deprecated_state = DEPRECATED_NORMAL; if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE) - return NULL_TREE; + return error_mark_node; type = TREE_TYPE (decl); if (type == error_mark_node) - return NULL_TREE; + return error_mark_node; context = DECL_CONTEXT (decl); @@ -4183,6 +4204,62 @@ next_initializable_field (tree field) return field; } +/* Subroutine of reshape_init. Reshape the constructor for an array. INITP + is the pointer to the old constructor list (to the CONSTRUCTOR_ELTS of + the CONSTRUCTOR we are processing), while NEW_INIT is the CONSTRUCTOR we + are building. + ELT_TYPE is the element type of the array. MAX_INDEX is an INTEGER_CST + representing the size of the array minus one (the maximum index), or + NULL_TREE if the array was declared without specifying the size. */ + +static bool +reshape_init_array (tree elt_type, tree max_index, + tree *initp, tree new_init) +{ + bool sized_array_p = (max_index != NULL_TREE); + unsigned HOST_WIDE_INT max_index_cst = 0; + unsigned HOST_WIDE_INT index; + + if (sized_array_p) + { + if (host_integerp (max_index, 1)) + max_index_cst = tree_low_cst (max_index, 1); + /* sizetype is sign extended, not zero extended. */ + else + max_index_cst = tree_low_cst (convert (size_type_node, max_index), 1); + } + + /* Loop until there are no more initializers. */ + for (index = 0; + *initp && (!sized_array_p || index <= max_index_cst); + ++index) + { + tree element_init; + tree designated_index; + + element_init = reshape_init (elt_type, initp); + if (element_init == error_mark_node) + return false; + TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init); + CONSTRUCTOR_ELTS (new_init) = element_init; + designated_index = TREE_PURPOSE (element_init); + if (designated_index) + { + /* Handle array designated initializers (GNU extension). */ + if (TREE_CODE (designated_index) == IDENTIFIER_NODE) + { + error ("name `%D' used in a GNU-style designated " + "initializer for an array", designated_index); + TREE_PURPOSE (element_init) = NULL_TREE; + } + else + abort (); + } + } + + return true; +} + /* Undo the brace-elision allowed by [dcl.init.aggr] in a brace-enclosed aggregate initializer. @@ -4206,6 +4283,7 @@ reshape_init (tree type, tree *initp) tree old_init_value; tree new_init; bool brace_enclosed_p; + bool string_init_p; old_init = *initp; old_init_value = (TREE_CODE (*initp) == TREE_LIST @@ -4270,6 +4348,7 @@ reshape_init (tree type, tree *initp) return old_init; } + string_init_p = false; if (TREE_CODE (old_init_value) == STRING_CST && TREE_CODE (type) == ARRAY_TYPE && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))) @@ -4284,6 +4363,7 @@ reshape_init (tree type, tree *initp) /* Move past the initializer. */ *initp = TREE_CHAIN (old_init); TREE_CHAIN (old_init) = NULL_TREE; + string_init_p = true; } else { @@ -4351,38 +4431,15 @@ reshape_init (tree type, tree *initp) } else if ((TREE_CODE (type) == ARRAY_TYPE)|| (TREE_CODE (type) == VECTOR_TYPE)) { - tree index; tree max_index; /* If the bound of the array is known, take no more initializers than are allowed. */ max_index = ((TYPE_DOMAIN (type) && (TREE_CODE (type) == ARRAY_TYPE)) ? array_type_nelts (type) : NULL_TREE); - /* Loop through the array elements, gathering initializers. */ - for (index = size_zero_node; - *initp && (!max_index || !tree_int_cst_lt (max_index, index)); - index = size_binop (PLUS_EXPR, index, size_one_node)) - { - tree element_init; - - element_init = reshape_init (TREE_TYPE (type), initp); - if (element_init == error_mark_node) - return error_mark_node; - TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init); - CONSTRUCTOR_ELTS (new_init) = element_init; - if (TREE_PURPOSE (element_init)) - { - tree next_index = TREE_PURPOSE (element_init); - if (TREE_CODE (next_index) == IDENTIFIER_NODE) - { - error ("name `%D' used in a GNU-style designated " - "initializer for an array", next_index); - TREE_PURPOSE (element_init) = NULL_TREE; - } - else - index = next_index; - } - } + if (!reshape_init_array (TREE_TYPE (type), max_index, + initp, new_init)) + return error_mark_node; } else abort (); @@ -4395,10 +4452,15 @@ reshape_init (tree type, tree *initp) new_init = build_tree_list (TREE_PURPOSE (old_init), new_init); } - /* If this was a brace-enclosed initializer and all of the - initializers were not used up, there is a problem. */ - if (brace_enclosed_p && *initp) - error ("too many initializers for `%T'", type); + /* If there are more initializers than necessary, issue a + diagnostic. */ + if (*initp) + { + if (brace_enclosed_p) + error ("too many initializers for `%T'", type); + else if (warn_missing_braces && !string_init_p) + warning ("missing braces around initializer"); + } return new_init; } @@ -4723,6 +4785,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) tree cleanup; const char *asmspec = NULL; int was_readonly = 0; + bool var_definition_p = false; if (decl == error_mark_node) return; @@ -4875,6 +4938,11 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) /* Remember that the initialization for this variable has taken place. */ DECL_INITIALIZED_P (decl) = 1; + /* This declaration is the definition of this variable, + unless we are initializing a static data member within + the class specifier. */ + if (!DECL_EXTERNAL (decl)) + var_definition_p = true; } /* If the variable has an array type, lay out the type, even if there is no initializer. It is valid to index through the @@ -4949,8 +5017,16 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags) initialize_local_var (decl, init); } - if (TREE_STATIC (decl)) - expand_static_init (decl, init); + /* If a variable is defined, and then a subsequent + definintion with external linkage is encountered, we will + get here twice for the same variable. We want to avoid + calling expand_static_init more than once. For variables + that are not static data members, we can call + expand_static_init only when we actually process the + initializer. It is not legal to redeclare a static data + member, so this issue does not arise in that case. */ + if (var_definition_p && TREE_STATIC (decl)) + expand_static_init (decl, init); } finish_end0: @@ -6317,6 +6393,32 @@ check_special_function_return_type (special_function_kind sfk, return type; } +/* A variable or data member (whose unqualified name is IDENTIFIER) + has been declared with the indicated TYPE. If the TYPE is not + acceptable, issue an error message and return a type to use for + error-recovery purposes. */ + +tree +check_var_type (tree identifier, tree type) +{ + if (VOID_TYPE_P (type)) + { + if (!identifier) + error ("unnamed variable or field declared void"); + else if (TREE_CODE (identifier) == IDENTIFIER_NODE) + { + if (IDENTIFIER_OPNAME_P (identifier)) + abort (); + error ("variable or field `%E' declared void", identifier); + } + else + error ("variable or field declared void"); + type = integer_type_node; + } + + return type; +} + /* Given declspecs and a declarator (abstract or otherwise), determine the name and type of the object declared and construct a DECL node for it. @@ -8016,30 +8118,25 @@ grokdeclarator (tree declarator, && ! bitfield) { error ("abstract declarator `%T' used as declaration", type); - declarator = make_anon_name (); + return error_mark_node; } - /* `void' at top level (not within pointer) - is allowed only in typedefs or type names. - We don't complain about parms either, but that is because - a better error message can be made later. */ - - if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM) + /* Only functions may be declared using an operator-function-id. */ + if (declarator + && TREE_CODE (declarator) == IDENTIFIER_NODE + && IDENTIFIER_OPNAME_P (declarator) + && TREE_CODE (type) != FUNCTION_TYPE + && TREE_CODE (type) != METHOD_TYPE) { - if (! declarator) - error ("unnamed variable or field declared void"); - else if (TREE_CODE (declarator) == IDENTIFIER_NODE) - { - if (IDENTIFIER_OPNAME_P (declarator)) - abort (); - else - error ("variable or field `%s' declared void", name); - } - else - error ("variable or field declared void"); - type = integer_type_node; + error ("declaration of `%D' as non-function", declarator); + return error_mark_node; } + /* We don't check parameter types here because we can emit a better + error message later. */ + if (decl_context != PARM) + type = check_var_type (declarator, type); + /* Now create the decl, which may be a VAR_DECL, a PARM_DECL or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE. */ @@ -9848,7 +9945,14 @@ finish_enum (tree enumtype) underlying type in the range bmin to bmax, where bmin and bmax are, respectively, the smallest and largest values of the smallest bit- field that can store emin and emax. */ - TYPE_PRECISION (enumtype) = precision; + + /* The middle-end currently assumes that types with TYPE_PRECISION + narrower than their underlying type are suitably zero or sign + extended to fill their mode. g++ doesn't make these guarantees. + Until the middle-end can represent such paradoxical types, we + set the TYPE_PRECISON to the width of the underlying type. */ + TYPE_PRECISION (enumtype) = TYPE_PRECISION (underlying_type); + set_min_and_max_values_for_integral_type (enumtype, precision, unsignedp); /* [dcl.enum] |