aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c313
1 files changed, 246 insertions, 67 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fa3caac01dc..d14ece4f8fc 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -66,6 +66,8 @@ static size_t inline_parm_levels_used;
static GTY(()) tree current_tinst_level;
+static GTY(()) tree saved_access_scope;
+
/* A map from local variable declarations in the body of the template
presently being instantiated to the corresponding instantiated
local variables. */
@@ -87,6 +89,9 @@ static htab_t local_specializations;
#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current
type with the desired type. */
+static void push_access_scope_real PARAMS ((tree, tree, tree));
+static void push_access_scope PARAMS ((tree));
+static void pop_access_scope PARAMS ((tree));
static int resolve_overloaded_unification PARAMS ((tree, tree, tree, tree,
unification_kind_t, int));
static int try_one_overload PARAMS ((tree, tree, tree, tree, tree,
@@ -166,6 +171,87 @@ static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
+/* Make the current scope suitable for access checking when we are
+ processing T. T can be FUNCTION_DECL for instantiated function
+ template, TEMPLATE_DECL for uninstantiated one, or VAR_DECL for
+ static member variable (need by instantiate_decl). ARGS is the
+ template argument for TEMPLATE_DECL. If CONTEXT is not NULL_TREE,
+ this is used instead of the context of T. */
+
+void
+push_access_scope_real (t, args, context)
+ tree t, args, context;
+{
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ /* When we are processing specialization `foo<Outer>' for code like
+
+ template <class U> typename U::Inner foo ();
+ class Outer {
+ struct Inner {};
+ friend Outer::Inner foo<Outer> ();
+ };
+
+ `T' is a TEMPLATE_DECL, but `Outer' is only a friend of one of
+ its specialization. We can get the FUNCTION_DECL with the right
+ information because this specialization has already been
+ registered by the friend declaration above. */
+
+ if (DECL_FUNCTION_TEMPLATE_P (t) && args)
+ {
+ tree full_args = tsubst_template_arg_vector
+ (DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t)), args, tf_none);
+ tree spec = NULL_TREE;
+ if (full_args != error_mark_node)
+ spec = retrieve_specialization (t, full_args);
+ if (spec)
+ t = spec;
+ }
+ }
+
+ if (!context)
+ context = DECL_CONTEXT (t);
+ if (context && TYPE_P (context))
+ push_nested_class (context, 2);
+ else
+ push_to_top_level ();
+
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ saved_access_scope = tree_cons
+ (NULL_TREE, current_function_decl, saved_access_scope);
+ current_function_decl = t;
+ }
+}
+
+/* Like push_access_scope_real, but always uses DECL_CONTEXT. */
+
+void
+push_access_scope (t)
+ tree t;
+{
+ push_access_scope_real (t, NULL_TREE, NULL_TREE);
+}
+
+/* Restore the scope set up by push_access_scope. T is the node we
+ are processing. */
+
+void
+pop_access_scope (t)
+ tree t;
+{
+ if (TREE_CODE (t) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (t))
+ {
+ current_function_decl = TREE_VALUE (saved_access_scope);
+ saved_access_scope = TREE_CHAIN (saved_access_scope);
+ }
+
+ if (DECL_CLASS_SCOPE_P (t))
+ pop_nested_class ();
+ else
+ pop_from_top_level ();
+}
+
/* Do any processing required when DECL (a member template declaration
using TEMPLATE_PARAMETERS as its innermost parameter list) is
finished. Returns the TEMPLATE_DECL corresponding to DECL, unless
@@ -681,8 +767,22 @@ void
maybe_process_partial_specialization (type)
tree type;
{
- if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type))
+ /* TYPE maybe an ERROR_MARK_NODE. */
+ tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE;
+
+ if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type))
{
+ /* This is for ordinary explicit specialization and partial
+ specialization of a template class such as:
+
+ template <> class C<int>;
+
+ or:
+
+ template <class T> class C<T*>;
+
+ Make sure that `C<int>' and `C<T*>' are implicit instantiations. */
+
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
@@ -700,6 +800,62 @@ maybe_process_partial_specialization (type)
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of `%T' after instantiation", type);
}
+ else if (CLASS_TYPE_P (type)
+ && !CLASSTYPE_USE_TEMPLATE (type)
+ && CLASSTYPE_TEMPLATE_INFO (type)
+ && context && CLASS_TYPE_P (context)
+ && CLASSTYPE_TEMPLATE_INFO (context))
+ {
+ /* This is for an explicit specialization of member class
+ template according to [temp.expl.spec/18]:
+
+ template <> template <class U> class C<int>::D;
+
+ The context `C<int>' must be an implicit instantiation.
+ Otherwise this is just a member class template declared
+ earlier like:
+
+ template <> class C<int> { template <class U> class D; };
+ template <> template <class U> class C<int>::D;
+
+ In the first case, `C<int>::D' is a specialization of `C<T>::D'
+ while in the second case, `C<int>::D' is a primary template
+ and `C<T>::D' may not exist. */
+
+ if (CLASSTYPE_IMPLICIT_INSTANTIATION (context)
+ && !COMPLETE_TYPE_P (type))
+ {
+ tree t;
+
+ if (current_namespace
+ != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
+ {
+ pedwarn ("specializing `%#T' in different namespace", type);
+ cp_pedwarn_at (" from definition of `%#D'",
+ CLASSTYPE_TI_TEMPLATE (type));
+ }
+
+ /* Check for invalid specialization after instantiation:
+
+ template <> template <> class C<int>::D<int>;
+ template <> template <class U> class C<int>::D; */
+
+ for (t = DECL_TEMPLATE_INSTANTIATIONS
+ (most_general_template (CLASSTYPE_TI_TEMPLATE (type)));
+ t; t = TREE_CHAIN (t))
+ if (TREE_VALUE (t) != type
+ && TYPE_CONTEXT (TREE_VALUE (t)) == context)
+ error ("specialization `%T' after instantiation `%T'",
+ type, TREE_VALUE (t));
+
+ /* Mark TYPE as a specialization. And as a result, we only
+ have one level of template argument for the innermost
+ class template. */
+ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
+ CLASSTYPE_TI_ARGS (type)
+ = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
+ }
+ }
else if (processing_specialization)
error ("explicit specialization of non-template `%T'", type);
}
@@ -3341,17 +3497,12 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
&& TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
- else if (CLASSTYPE_TEMPLATE_INFO (arg) && !CLASSTYPE_USE_TEMPLATE (arg)
- && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (arg)))
- {
- if (is_base_of_enclosing_class (arg, current_class_type))
- /* This is a template name used within the scope of the
- template. It could be the template, or it could be the
- instantiation. Choose whichever makes sense. */
- is_tmpl_type = requires_tmpl_type;
- else
- is_tmpl_type = 1;
- }
+ else if (CLASSTYPE_IS_TEMPLATE (arg)
+ && is_base_of_enclosing_class (arg, current_class_type))
+ /* This is a template name used within the scope of the
+ template. It could be the template, or it could be the
+ instantiation. Choose whichever makes sense. */
+ is_tmpl_type = requires_tmpl_type;
else
/* It is a non-template class, or a specialization of a template
class, or a non-template member of a template class. */
@@ -3916,6 +4067,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
tree template = NULL_TREE, parmlist;
tree t;
+ timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (d1) == IDENTIFIER_NODE)
{
if (IDENTIFIER_VALUE (d1)
@@ -3971,7 +4123,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
{
if (complain & tf_error)
error ("`%T' is not a template", d1);
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (TREE_CODE (template) != TEMPLATE_DECL
@@ -3987,7 +4139,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
if (in_decl)
cp_error_at ("for template declaration `%D'", in_decl);
}
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
@@ -4022,10 +4174,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
arglist2 = coerce_template_parms (parmlist, arglist, template,
complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node)
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
- return parm;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
}
else
{
@@ -4112,7 +4264,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
- return error_mark_node;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
/* In the scope of a template class, explicit references to the
template class refer to the type of the template, not any
@@ -4149,7 +4301,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
}
}
if (found)
- return found;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
for (tp = &DECL_TEMPLATE_INSTANTIATIONS (template);
*tp;
@@ -4165,7 +4317,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
= DECL_TEMPLATE_INSTANTIATIONS (template);
DECL_TEMPLATE_INSTANTIATIONS (template) = found;
- return TREE_VALUE (found);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (found));
}
/* This type is a "partial instantiation" if any of the template
@@ -4181,7 +4333,7 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
found = xref_tag_from_type (TREE_TYPE (template),
DECL_NAME (template),
/*globalize=*/1);
- return found;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
}
context = tsubst (DECL_CONTEXT (template), arglist,
@@ -4233,6 +4385,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
else
type_decl = TYPE_NAME (t);
+ TREE_PRIVATE (type_decl)
+ = TREE_PRIVATE (TYPE_STUB_DECL (template_type));
+ TREE_PROTECTED (type_decl)
+ = TREE_PROTECTED (TYPE_STUB_DECL (template_type));
+
/* Set up the template information. We have to figure out which
template is the immediate parent if this is a full
instantiation. */
@@ -4332,8 +4489,9 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
code that generates debugging information will crash. */
DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
- return t;
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
+ timevar_pop (TV_NAME_LOOKUP);
}
struct pair_fn_data
@@ -5415,12 +5573,8 @@ instantiate_class_template (type)
--processing_template_decl;
}
else
- {
- /* Build new DECL_FRIENDLIST. */
-
- add_friend (type,
- tsubst_friend_function (t, args));
- }
+ /* Build new DECL_FRIENDLIST. */
+ add_friend (type, tsubst_friend_function (t, args));
}
}
@@ -5456,6 +5610,9 @@ instantiate_class_template (type)
pop_from_top_level ();
pop_tinst_level ();
+ if (TYPE_CONTAINS_VPTR_P (type))
+ keyed_classes = tree_cons (NULL_TREE, type, keyed_classes);
+
return type;
}
@@ -5691,14 +5848,14 @@ tsubst_default_argument (fn, type, arg)
??? current_class_type affects a lot more than name lookup. This is
very fragile. Fortunately, it will go away when we do 2-phase name
binding properly. */
- if (DECL_CLASS_SCOPE_P (fn))
- pushclass (DECL_CONTEXT (fn), 2);
+
+ /* FN is already the desired FUNCTION_DECL. */
+ push_access_scope (fn);
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_error | tf_warning, NULL_TREE);
- if (DECL_CLASS_SCOPE_P (fn))
- popclass ();
+ pop_access_scope (fn);
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
@@ -6793,7 +6950,7 @@ tsubst (t, args, complain, in_decl)
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
- if (complain)
+ if (complain & tf_error)
error ("creating pointer to member reference type `%T'", type);
return error_mark_node;
@@ -7795,17 +7952,17 @@ instantiate_template (tmpl, targ_ptr)
}
/* Make sure that we can see identifiers, and compute access
- correctly. */
- if (DECL_CLASS_SCOPE_P (gen_tmpl))
- pushclass (tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr, tf_error,
- gen_tmpl), 1);
+ correctly. The desired FUNCTION_DECL for FNDECL may or may not be
+ created earlier. Let push_access_scope_real figure that out. */
+ push_access_scope_real
+ (gen_tmpl, targ_ptr, tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
+ tf_error, gen_tmpl));
/* substitute template parameters */
fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
targ_ptr, tf_error, gen_tmpl);
- if (DECL_CLASS_SCOPE_P (gen_tmpl))
- popclass ();
+ pop_access_scope (gen_tmpl);
/* The DECL_TI_TEMPLATE should always be the immediate parent
template, not the most general template. */
@@ -7877,7 +8034,7 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
int result;
my_friendly_assert (TREE_CODE (fn) == TEMPLATE_DECL, 0);
-
+
fntype = TREE_TYPE (fn);
if (explicit_targs)
{
@@ -8055,6 +8212,12 @@ maybe_adjust_types_for_deduction (strict, parm, arg)
*parm = TREE_TYPE (*parm);
result |= UNIFY_ALLOW_OUTER_MORE_CV_QUAL;
}
+
+ /* DR 322. For conversion deduction, remove a reference type on parm
+ too (which has been swapped into ARG). */
+ if (strict == DEDUCE_CONV && TREE_CODE (*arg) == REFERENCE_TYPE)
+ *arg = TREE_TYPE (*arg);
+
return result;
}
@@ -8292,7 +8455,8 @@ resolve_overloaded_unification (tparms, targs, parm, arg, strict,
}
}
}
- else if (TREE_CODE (arg) == OVERLOAD)
+ else if (TREE_CODE (arg) == OVERLOAD
+ || TREE_CODE (arg) == FUNCTION_DECL)
{
for (; arg; arg = OVL_NEXT (arg))
{
@@ -8833,6 +8997,12 @@ unify (tparms, targs, parm, arg, strict)
}
else
{
+ /* If ARG is an offset type, we're trying to unify '*T' with
+ 'U C::*', which is ill-formed. See the comment in the
+ POINTER_TYPE case about this ugliness. */
+ if (TREE_CODE (arg) == OFFSET_TYPE)
+ return 1;
+
/* If PARM is `const T' and ARG is only `int', we don't have
a match unless we are allowing additional qualification.
If ARG is `const int' and PARM is just `T' that's OK;
@@ -9508,6 +9678,10 @@ most_general_template (decl)
if (TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
break;
+ if (CLASS_TYPE_P (TREE_TYPE (decl))
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ break;
+
/* Stop if we run into an explicitly specialized class template. */
if (!DECL_NAMESPACE_SCOPE_P (decl)
&& DECL_CONTEXT (decl)
@@ -9897,6 +10071,7 @@ regenerate_decl_from_template (decl, tmpl)
instantiation of a specialization, which it isn't: it's a full
instantiation. */
gen_tmpl = most_general_template (tmpl);
+ push_access_scope_real (gen_tmpl, args, DECL_CONTEXT (decl));
unregistered = unregister_specialization (decl, gen_tmpl);
/* If the DECL was not unregistered then something peculiar is
@@ -9904,11 +10079,6 @@ regenerate_decl_from_template (decl, tmpl)
register_specialization for it. */
my_friendly_assert (unregistered, 0);
- if (DECL_CLASS_SCOPE_P (decl))
- /* Make sure that we can see identifiers, and compute access
- correctly, for the class members used in the declaration of
- this static variable or function. */
- pushclass (DECL_CONTEXT (decl), 2);
/* Do the substitution to get the new declaration. */
new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
@@ -9930,9 +10100,7 @@ regenerate_decl_from_template (decl, tmpl)
DECL_INITIAL (decl) = NULL_TREE;
}
- /* Pop the class context we pushed above. */
- if (DECL_CLASS_SCOPE_P (decl))
- popclass ();
+ pop_access_scope (decl);
/* The immediate parent of the new template is still whatever it was
before, even though tsubst sets DECL_TI_TEMPLATE up as the most
@@ -9979,6 +10147,9 @@ instantiate_decl (d, defer_ok)
my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
|| TREE_CODE (d) == VAR_DECL, 0);
+ if (TREE_CODE (d) == VAR_DECL)
+ defer_ok = 0;
+
/* Don't instantiate cloned functions. Instead, instantiate the
functions they cloned. */
if (TREE_CODE (d) == FUNCTION_DECL && DECL_CLONED_FUNCTION_P (d))
@@ -10060,12 +10231,14 @@ instantiate_decl (d, defer_ok)
code_pattern = DECL_TEMPLATE_RESULT (td);
- /* In the case of a friend template whose definition is provided
- outside the class, we may have too many arguments. Drop the ones
- we don't need. */
- args = get_innermost_template_args (gen_args,
- TMPL_PARMS_DEPTH
- (DECL_TEMPLATE_PARMS (td)));
+ if (DECL_NAMESPACE_SCOPE_P (d) && !DECL_INITIALIZED_IN_CLASS_P (d))
+ /* In the case of a friend template whose definition is provided
+ outside the class, we may have too many arguments. Drop the
+ ones we don't need. */
+ args = get_innermost_template_args
+ (gen_args, TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (td)));
+ else
+ args = gen_args;
if (TREE_CODE (d) == FUNCTION_DECL)
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
@@ -10125,9 +10298,9 @@ instantiate_decl (d, defer_ok)
tree type = TREE_TYPE (gen);
/* Make sure that we can see identifiers, and compute access
- correctly. */
- if (DECL_CLASS_SCOPE_P (d))
- pushclass (DECL_CONTEXT (d), 1);
+ correctly. D is already the target FUNCTION_DECL with the
+ right context. */
+ push_access_scope (d);
if (TREE_CODE (gen) == FUNCTION_DECL)
{
@@ -10142,8 +10315,7 @@ instantiate_decl (d, defer_ok)
}
tsubst (type, gen_args, tf_error | tf_warning, d);
- if (DECL_CLASS_SCOPE_P (d))
- popclass ();
+ pop_access_scope (d);
}
if (TREE_CODE (d) == VAR_DECL && DECL_INITIALIZED_IN_CLASS_P (d)
@@ -10192,7 +10364,7 @@ instantiate_decl (d, defer_ok)
/* Regenerate the declaration in case the template has been modified
by a subsequent redeclaration. */
regenerate_decl_from_template (d, td);
-
+
/* We already set the file and line above. Reset them now in case
they changed as a result of calling regenerate_decl_from_template. */
lineno = DECL_SOURCE_LINE (d);
@@ -10200,6 +10372,10 @@ instantiate_decl (d, defer_ok)
if (TREE_CODE (d) == VAR_DECL)
{
+ /* Clear out DECL_RTL; whatever was there before may not be right
+ since we've reset the type of the declaration. */
+ SET_DECL_RTL (d, NULL_RTX);
+
DECL_IN_AGGR_P (d) = 0;
if (DECL_INTERFACE_KNOWN (d))
DECL_EXTERNAL (d) = ! DECL_NOT_REALLY_EXTERN (d);
@@ -10365,9 +10541,12 @@ tsubst_initializer_list (t, argvec)
decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
NULL_TREE);
+ decl = expand_member_init (decl);
+ if (decl && !DECL_P (decl))
+ in_base_initializer = 1;
+
init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
NULL_TREE);
-
if (!init)
;
else if (TREE_CODE (init) == TREE_LIST)
@@ -10376,9 +10555,11 @@ tsubst_initializer_list (t, argvec)
else if (init != void_type_node)
init = convert_from_reference (init);
- init = expand_member_init (decl, init);
- if (init)
+ in_base_initializer = 0;
+
+ if (decl)
{
+ init = build_tree_list (decl, init);
TREE_CHAIN (init) = inits;
inits = init;
}
@@ -10483,8 +10664,7 @@ get_mostly_instantiated_function_type (decl)
partial substitution here. It depends only on outer template
parameters, regardless of whether the innermost level is
specialized or not. */
- if (DECL_CLASS_SCOPE_P (decl))
- pushclass (DECL_CONTEXT (decl), 1);
+ push_access_scope (decl);
/* Now, do the (partial) substitution to figure out the
appropriate function type. */
@@ -10497,8 +10677,7 @@ get_mostly_instantiated_function_type (decl)
TREE_VEC_LENGTH (partial_args)--;
tparms = tsubst_template_parms (tparms, partial_args, tf_error);
- if (DECL_CLASS_SCOPE_P (decl))
- popclass ();
+ pop_access_scope (decl);
}
return fn_type;