summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/pt.c
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2005-06-03 03:28:44 +0000
committerkan <kan@FreeBSD.org>2005-06-03 03:28:44 +0000
commit2156e40a831a8e0ab68e4bc091c2940bf46ca6df (patch)
treef0dc8ad34f9fcaf27052e24e893a4284b5fee6e9 /contrib/gcc/cp/pt.c
parent0a20abcc95340c9d2bb59421bac84eca4fb43b0c (diff)
downloadFreeBSD-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.c261
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 *"
OpenPOWER on IntegriCloud