diff options
author | kan <kan@FreeBSD.org> | 2005-06-03 03:28:44 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2005-06-03 03:28:44 +0000 |
commit | 2156e40a831a8e0ab68e4bc091c2940bf46ca6df (patch) | |
tree | f0dc8ad34f9fcaf27052e24e893a4284b5fee6e9 /contrib/gcc/cp/pt.c | |
parent | 0a20abcc95340c9d2bb59421bac84eca4fb43b0c (diff) | |
download | FreeBSD-src-2156e40a831a8e0ab68e4bc091c2940bf46ca6df.zip FreeBSD-src-2156e40a831a8e0ab68e4bc091c2940bf46ca6df.tar.gz |
Gcc 3.4.4 release.
Diffstat (limited to 'contrib/gcc/cp/pt.c')
-rw-r--r-- | contrib/gcc/cp/pt.c | 261 |
1 files changed, 175 insertions, 86 deletions
diff --git a/contrib/gcc/cp/pt.c b/contrib/gcc/cp/pt.c index c5c8e32..e5aadc1 100644 --- a/contrib/gcc/cp/pt.c +++ b/contrib/gcc/cp/pt.c @@ -1,6 +1,6 @@ /* Handle parameterized types (templates) for GNU C++. Copyright (C) 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. Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing. Rewritten by Jason Merrill (jason@cygnus.com). @@ -180,7 +180,9 @@ push_access_scope (tree t) || TREE_CODE (t) == VAR_DECL, 0); - if (DECL_CLASS_SCOPE_P (t)) + if (DECL_FRIEND_CONTEXT (t)) + push_nested_class (DECL_FRIEND_CONTEXT (t)); + else if (DECL_CLASS_SCOPE_P (t)) push_nested_class (DECL_CONTEXT (t)); else push_to_top_level (); @@ -205,7 +207,7 @@ pop_access_scope (tree t) saved_access_scope = TREE_CHAIN (saved_access_scope); } - if (DECL_CLASS_SCOPE_P (t)) + if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t)) pop_nested_class (); else pop_from_top_level (); @@ -706,6 +708,36 @@ end_explicit_instantiation (void) processing_explicit_instantiation = false; } +/* A explicit specialization or partial specialization TMPL is being + declared. Check that the namespace in which the specialization is + occurring is permissible. Returns false iff it is invalid to + specialize TMPL in the current namespace. */ + +static bool +check_specialization_namespace (tree tmpl) +{ + tree tpl_ns = decl_namespace_context (tmpl); + + /* [tmpl.expl.spec] + + An explicit specialization shall be declared in the namespace of + which the template is a member, or, for member templates, in the + namespace of which the enclosing class or enclosing class + template is a member. An explicit specialization of a member + function, member class or static data member of a class template + shall be declared in the namespace of which the class template is + a member. */ + if (is_associated_namespace (current_namespace, tpl_ns)) + /* Same or super-using namespace. */ + return true; + else + { + pedwarn ("specialization of `%D' in different namespace", tmpl); + cp_pedwarn_at (" from definition of `%#D'", tmpl); + return false; + } +} + /* The TYPE is being declared. If it is a template type, that means it is a partial specialization. Do appropriate error-checking. */ @@ -731,15 +763,7 @@ maybe_process_partial_specialization (tree type) if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type)) { - tree tpl_ns = decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)); - if (is_associated_namespace (current_namespace, tpl_ns)) - /* Same or super-using namespace. */; - else - { - pedwarn ("specializing `%#T' in different namespace", type); - cp_pedwarn_at (" from definition of `%#D'", - CLASSTYPE_TI_TEMPLATE (type)); - } + check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type)); SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type); if (processing_template_decl) push_template_decl (TYPE_MAIN_DECL (type)); @@ -1114,6 +1138,12 @@ register_specialization (tree spec, tree tmpl, tree args) } } + /* A specialization must be declared in the same namespace as the + template it is specializing. */ + if (DECL_TEMPLATE_SPECIALIZATION (spec) + && !check_specialization_namespace (tmpl)) + DECL_CONTEXT (spec) = decl_namespace_context (tmpl); + DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); @@ -1927,6 +1957,10 @@ check_explicit_specialization (tree declarator, DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl); DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (tmpl)) = DECL_SOURCE_LOCATION (decl); + /* We want to use the argument list specified in the + definition, not in the original declaration. */ + DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (tmpl)) + = DECL_ARGUMENTS (decl); } return tmpl; } @@ -1963,49 +1997,6 @@ check_explicit_specialization (tree declarator, return decl; } -/* TYPE is being declared. Verify that the use of template headers - and such is reasonable. Issue error messages if not. */ - -void -maybe_check_template_type (tree type) -{ - if (template_header_count) - { - /* We are in the scope of some `template <...>' header. */ - - int context_depth - = template_class_depth_real (TYPE_CONTEXT (type), - /*count_specializations=*/1); - - if (template_header_count <= context_depth) - /* This is OK; the template headers are for the context. We - are actually too lenient here; like - check_explicit_specialization we should consider the number - of template types included in the actual declaration. For - example, - - template <class T> struct S { - template <class U> template <class V> - struct I {}; - }; - - is invalid, but: - - template <class T> struct S { - template <class U> struct I; - }; - - template <class T> template <class U. - struct S<T>::I {}; - - is not. */ - ; - else if (template_header_count > context_depth + 1) - /* There are two many template parameter lists. */ - error ("too many template parameter lists in declaration of `%T'", type); - } -} - /* Returns 1 iff PARMS1 and PARMS2 are identical sets of template parameters. These are represented in the same format used for DECL_TEMPLATE_PARMS. */ @@ -2815,19 +2806,35 @@ push_template_decl_real (tree decl, int is_friend) else if (TREE_CODE (decl) == TYPE_DECL && ANON_AGGRNAME_P (DECL_NAME (decl))) error ("template class without a name"); - else if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_DESTRUCTOR_P (decl)) + else if (TREE_CODE (decl) == FUNCTION_DECL) { - /* [temp.mem] - - A destructor shall not be a member template. */ - error ("destructor `%D' declared as member template", decl); - return error_mark_node; + if (DECL_DESTRUCTOR_P (decl)) + { + /* [temp.mem] + + A destructor shall not be a member template. */ + error ("destructor `%D' declared as member template", decl); + return error_mark_node; + } + if (NEW_DELETE_OPNAME_P (DECL_NAME (decl)) + && (!TYPE_ARG_TYPES (TREE_TYPE (decl)) + || TYPE_ARG_TYPES (TREE_TYPE (decl)) == void_list_node + || !TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl))) + || (TREE_CHAIN (TYPE_ARG_TYPES ((TREE_TYPE (decl)))) + == void_list_node))) + { + /* [basic.stc.dynamic.allocation] + + An allocation function can be a function + template. ... Template allocation functions shall + have two or more parameters. */ + error ("invalid template declaration of `%D'", decl); + return decl; + } } else if ((DECL_IMPLICIT_TYPEDEF_P (decl) && CLASS_TYPE_P (TREE_TYPE (decl))) - || (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx)) - || TREE_CODE (decl) == FUNCTION_DECL) + || (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx))) /* OK */; else { @@ -3199,9 +3206,7 @@ convert_nontype_argument (tree type, tree expr) will not return the initializer. Handle that special case here. */ if (expr == const_expr - && TREE_CODE (expr) == VAR_DECL - && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (expr) - && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (expr)) + && DECL_INTEGRAL_CONSTANT_VAR_P (expr) /* DECL_INITIAL can be NULL if we are processing a variable initialized to an expression involving itself. We know it is initialized to a constant -- but not what @@ -5470,14 +5475,28 @@ instantiate_class_template (tree type) tree tag = t; tree name = TYPE_IDENTIFIER (tag); tree newtag; - + bool class_template_p; + + class_template_p = (TREE_CODE (tag) != ENUMERAL_TYPE + && TYPE_LANG_SPECIFIC (tag) + && CLASSTYPE_IS_TEMPLATE (tag)); + /* If the member is a class template, then -- even after + substituition -- there may be dependent types in the + template argument list for the class. We increment + PROCESSING_TEMPLATE_DECL so that dependent_type_p, as + that function will assume that no types are dependent + when outside of a template. */ + if (class_template_p) + ++processing_template_decl; newtag = tsubst (tag, args, tf_error, NULL_TREE); + if (class_template_p) + --processing_template_decl; if (newtag == error_mark_node) continue; if (TREE_CODE (newtag) != ENUMERAL_TYPE) { - if (TYPE_LANG_SPECIFIC (tag) && CLASSTYPE_IS_TEMPLATE (tag)) + if (class_template_p) /* Unfortunately, lookup_template_class sets CLASSTYPE_IMPLICIT_INSTANTIATION for a partial instantiation (i.e., for the type of a member @@ -5872,6 +5891,9 @@ tsubst_aggr_type (tree t, tree tsubst_default_argument (tree fn, tree type, tree arg) { + tree saved_class_ptr = NULL_TREE; + tree saved_class_ref = NULL_TREE; + /* This default argument came from a template. Instantiate the default argument here, not in tsubst. In the case of something like: @@ -5889,12 +5911,27 @@ tsubst_default_argument (tree fn, tree type, tree arg) within the scope of FN. Since push_access_scope sets current_function_decl, we must explicitly clear it here. */ current_function_decl = NULL_TREE; + /* The "this" pointer is not valid in a default argument. */ + if (cfun) + { + saved_class_ptr = current_class_ptr; + cp_function_chain->x_current_class_ptr = NULL_TREE; + saved_class_ref = current_class_ref; + cp_function_chain->x_current_class_ref = NULL_TREE; + } push_deferring_access_checks(dk_no_deferred); arg = tsubst_expr (arg, DECL_TI_ARGS (fn), tf_error | tf_warning, NULL_TREE); pop_deferring_access_checks(); + /* Restore the "this" pointer. */ + if (cfun) + { + cp_function_chain->x_current_class_ptr = saved_class_ptr; + cp_function_chain->x_current_class_ref = saved_class_ref; + } + pop_access_scope (fn); /* Make sure the default argument is reasonable. */ @@ -6384,6 +6421,7 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) type = complete_type (type); DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r) = DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t); + type = check_var_type (DECL_NAME (r), type); } else if (DECL_SELF_REFERENCE_P (t)) SET_DECL_SELF_REFERENCE_P (r); @@ -6424,9 +6462,6 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain) register_local_specialization (r, t); TREE_CHAIN (r) = NULL_TREE; - if (TREE_CODE (r) == VAR_DECL && VOID_TYPE_P (type)) - cp_error_at ("instantiation of `%D' as type `%T'", r, type); - /* Compute the size, alignment, etc. of R. */ layout_decl (r, 0); } break; @@ -6618,6 +6653,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) || t == integer_type_node || t == void_type_node || t == char_type_node + || t == unknown_type_node || TREE_CODE (t) == NAMESPACE_DECL) return t; @@ -7446,7 +7482,16 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) ctx = tsubst_aggr_type (DECL_CONTEXT (t), args, complain, in_decl, /*entering_scope=*/1); if (ctx != DECL_CONTEXT (t)) - return lookup_field (ctx, DECL_NAME (t), 0, false); + { + tree r = lookup_field (ctx, DECL_NAME (t), 0, false); + if (!r) + { + if (complain & tf_error) + error ("using invalid field `%D'", t); + return error_mark_node; + } + return r; + } } return t; @@ -8381,7 +8426,11 @@ tsubst_copy_and_build (tree t, lookup finds a non-function, in accordance with the expected resolution of DR 218. */ if (koenig_p - && (is_overloaded_fn (function) + && ((is_overloaded_fn (function) + /* If lookup found a member function, the Koenig lookup is + not appropriate, even if an unqualified-name was used + to denote the function. */ + && !DECL_FUNCTION_MEMBER_P (get_first_fn (function))) || TREE_CODE (function) == IDENTIFIER_NODE)) function = perform_koenig_lookup (function, call_args); @@ -8471,7 +8520,9 @@ tsubst_copy_and_build (tree t, else member = tsubst_copy (member, args, complain, in_decl); - if (!CLASS_TYPE_P (TREE_TYPE (object))) + if (member == error_mark_node) + return error_mark_node; + else if (!CLASS_TYPE_P (TREE_TYPE (object))) { if (TREE_CODE (member) == BIT_NOT_EXPR) return finish_pseudo_destructor_expr (object, @@ -8497,15 +8548,35 @@ tsubst_copy_and_build (tree t, /*is_type_p=*/false, /*complain=*/false); if (BASELINK_P (member)) - BASELINK_FUNCTIONS (member) - = build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member), - args); + { + BASELINK_FUNCTIONS (member) + = build_nt (TEMPLATE_ID_EXPR, BASELINK_FUNCTIONS (member), + args); + member = (adjust_result_of_qualified_name_lookup + (member, BINFO_TYPE (BASELINK_BINFO (member)), + TREE_TYPE (object))); + } else { qualified_name_lookup_error (TREE_TYPE (object), tmpl); return error_mark_node; } } + else if (TREE_CODE (member) == SCOPE_REF + && !CLASS_TYPE_P (TREE_OPERAND (member, 0)) + && TREE_CODE (TREE_OPERAND (member, 0)) != NAMESPACE_DECL) + { + if (complain & tf_error) + { + if (TYPE_P (TREE_OPERAND (member, 0))) + error ("`%T' is not a class or namespace", + TREE_OPERAND (member, 0)); + else + error ("`%D' is not a class or namespace", + TREE_OPERAND (member, 0)); + } + return error_mark_node; + } else if (TREE_CODE (member) == FIELD_DECL) return finish_non_static_data_member (member, object, NULL_TREE); @@ -8574,6 +8645,14 @@ tsubst_copy_and_build (tree t, tsubst_copy (TREE_TYPE (t), args, complain, in_decl)); + case CONST_DECL: + t = tsubst_copy (t, args, complain, in_decl); + /* As in finish_id_expression, we resolve enumeration constants + to their underlying values. */ + if (TREE_CODE (t) == CONST_DECL) + return DECL_INITIAL (t); + return t; + default: return tsubst_copy (t, args, complain, in_decl); } @@ -8813,6 +8892,9 @@ fn_type_unification (tree fn, tree converted_args; bool incomplete; + if (explicit_targs == error_mark_node) + return 1; + converted_args = (coerce_template_parms (DECL_INNERMOST_TEMPLATE_PARMS (fn), explicit_targs, NULL_TREE, tf_none, @@ -9833,7 +9915,10 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) else if ((strict & UNIFY_ALLOW_INTEGER) && (TREE_CODE (tparm) == INTEGER_TYPE || TREE_CODE (tparm) == BOOLEAN_TYPE)) - /* OK */; + /* Convert the ARG to the type of PARM; the deduced non-type + template argument must exactly match the types of the + corresponding parameter. */ + arg = fold (build_nop (TREE_TYPE (parm), arg)); else if (uses_template_parms (tparm)) /* We haven't deduced the type of this parameter yet. Try again later. */ @@ -9913,6 +9998,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) case VECTOR_TYPE: case INTEGER_TYPE: case BOOLEAN_TYPE: + case ENUMERAL_TYPE: case VOID_TYPE: if (TREE_CODE (arg) != TREE_CODE (parm)) return 1; @@ -10108,10 +10194,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) else return 0; } - else - sorry ("use of `%s' in template type unification", - tree_code_name [(int) TREE_CODE (parm)]); - + sorry ("use of `%s' in template type unification", + tree_code_name [(int) TREE_CODE (parm)]); return 1; } } @@ -11927,6 +12011,9 @@ type_dependent_expression_p (tree expression) if (TREE_CODE (expression) == IDENTIFIER_NODE) return false; } + /* SCOPE_REF with non-null TREE_TYPE is always non-dependent. */ + if (TREE_CODE (expression) == SCOPE_REF) + return false; if (TREE_CODE (expression) == BASELINK) expression = BASELINK_FUNCTIONS (expression); @@ -12031,8 +12118,9 @@ dependent_template_p (tree tmpl) if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl) || TREE_CODE (tmpl) == TEMPLATE_TEMPLATE_PARM) return true; - /* So are qualified names that have not been looked up. */ - if (TREE_CODE (tmpl) == SCOPE_REF) + /* So arenames that have not been looked up. */ + if (TREE_CODE (tmpl) == SCOPE_REF + || TREE_CODE (tmpl) == IDENTIFIER_NODE) return true; /* So are member templates of dependent classes. */ if (TYPE_P (CP_DECL_CONTEXT (tmpl))) @@ -12148,7 +12236,8 @@ build_non_dependent_expr (tree expr) if (TREE_CODE (inner_expr) == OVERLOAD || TREE_CODE (inner_expr) == FUNCTION_DECL || TREE_CODE (inner_expr) == TEMPLATE_DECL - || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR) + || TREE_CODE (inner_expr) == TEMPLATE_ID_EXPR + || TREE_CODE (inner_expr) == OFFSET_REF) return expr; /* Preserve string constants; conversions from string constants to "char *" are allowed, even though normally a "const char *" |