You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Known bugs or deficiencies include:
TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec,
- NULL);
+ NULL);
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
e.g.:
template <class T> struct S1 {
- template <class T> struct S2 {};
+ template <class T> struct S2 {};
};
pushtag contains special code to call pushdecl_with_scope on the
processing_explicit_instantiation = false;
}
-/* A explicit specialization or partial specialization TMPL is being
+/* An 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. */
else
{
pedwarn ("specialization of %qD in different namespace", tmpl);
- cp_pedwarn_at (" from definition of %q#D", tmpl);
+ pedwarn (" from definition of %q+#D", tmpl);
return false;
}
}
+/* SPEC is an explicit instantiation. Check that it is valid to
+ perform this explicit instantiation in the current namespace. */
+
+static void
+check_explicit_instantiation_namespace (tree spec)
+{
+ tree ns;
+
+ /* DR 275: An explicit instantiation shall appear in an enclosing
+ namespace of its template. */
+ ns = decl_namespace_context (spec);
+ if (!is_ancestor (current_namespace, ns))
+ pedwarn ("explicit instantiation of %qD in namespace %qD "
+ "(which does not enclose namespace %qD)",
+ spec, current_namespace, ns);
+}
+
/* The TYPE is being declared. If it is a template type, that means it
is a partial specialization. Do appropriate error-checking. */
!= decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type)))
{
pedwarn ("specializing %q#T in different namespace", type);
- cp_pedwarn_at (" from definition of %q#D",
- CLASSTYPE_TI_TEMPLATE (type));
+ pedwarn (" from definition of %q+#D",
+ CLASSTYPE_TI_TEMPLATE (type));
}
/* Check for invalid specialization after instantiation:
}
/* Register the specialization SPEC as a specialization of TMPL with
- the indicated ARGS. Returns SPEC, or an equivalent prior
- declaration, if available. */
+ the indicated ARGS. IS_FRIEND indicates whether the specialization
+ is actually just a friend declaration. Returns SPEC, or an
+ equivalent prior declaration, if available. */
static tree
-register_specialization (tree spec, tree tmpl, tree args)
+register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
{
tree fn;
with default function arguments. In particular, given
something like this:
- template <class T> void f(T t1, T t = T())
+ template <class T> void f(T t1, T t = T())
the default argument expression is not substituted for in an
instantiation unless and until it is actually needed. */
return spec;
- /* There should be as many levels of arguments as there are
- levels of parameters. */
- gcc_assert (TMPL_ARGS_DEPTH (args)
- == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)));
-
fn = retrieve_specialization (tmpl, args,
/*class_specializations_p=*/false);
/* We can sometimes try to re-register a specialization that we've
for the specialization, we want this to look as if
there were no definition, and vice versa. */
DECL_INITIAL (fn) = NULL_TREE;
- duplicate_decls (spec, fn);
+ duplicate_decls (spec, fn, is_friend);
+ check_specialization_namespace (fn);
return fn;
}
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
- if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec))
+ if (!duplicate_decls (spec, fn, is_friend) && DECL_INITIAL (spec))
/* Dup decl failed, but this is a new definition. Set the
line number so any errors match this new
definition. */
tree f;
for (f = TREE_VALUE (fn); f; f = OVL_NEXT (f))
- cp_error_at ("%s %+#D", str, OVL_CURRENT (f));
+ error ("%s %+#D", str, OVL_CURRENT (f));
str = " ";
}
}
static tree
determine_specialization (tree template_id,
- tree decl,
- tree* targs_out,
+ tree decl,
+ tree* targs_out,
int need_member_template,
int template_count)
{
the function template to which a function template
specialization refers:
- -- when an explicit specialization refers to a function
+ -- when an explicit specialization refers to a function
template.
So, we do use the partial ordering rules, at least for now.
if (templates == NULL_TREE && candidates == NULL_TREE)
{
- cp_error_at ("template-id %qD for %q+D does not match any template "
- "declaration",
- template_id, decl);
+ error ("template-id %qD for %q+D does not match any template "
+ "declaration", template_id, decl);
return error_mark_node;
}
else if ((templates && TREE_CHAIN (templates))
|| (candidates && TREE_CHAIN (candidates))
|| (templates && candidates))
{
- cp_error_at ("ambiguous template specialization %qD for %q+D",
- template_id, decl);
+ error ("ambiguous template specialization %qD for %q+D",
+ template_id, decl);
chainon (candidates, templates);
print_candidates (candidates);
return error_mark_node;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
{
/* Remove the this pointer, but remember the object's type for
- CV quals. */
+ CV quals. */
object_type = TREE_TYPE (TREE_VALUE (spec_types));
spec_types = TREE_CHAIN (spec_types);
tmpl_types = TREE_CHAIN (tmpl_types);
if (DECL_HAS_IN_CHARGE_PARM_P (decl))
- {
- /* DECL may contain more parameters than TMPL due to the extra
- in-charge parameter in constructors and destructors. */
- in_charge = spec_types;
+ {
+ /* DECL may contain more parameters than TMPL due to the extra
+ in-charge parameter in constructors and destructors. */
+ in_charge = spec_types;
spec_types = TREE_CHAIN (spec_types);
}
if (DECL_HAS_VTT_PARM_P (decl))
if (object_type)
{
if (vtt)
- new_spec_types = hash_tree_cons (TREE_PURPOSE (vtt),
- TREE_VALUE (vtt),
- new_spec_types);
+ new_spec_types = hash_tree_cons (TREE_PURPOSE (vtt),
+ TREE_VALUE (vtt),
+ new_spec_types);
if (in_charge)
- /* Put the in-charge parameter back. */
- new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge),
- TREE_VALUE (in_charge),
- new_spec_types);
+ /* Put the in-charge parameter back. */
+ new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge),
+ TREE_VALUE (in_charge),
+ new_spec_types);
new_type = build_method_type_directly (object_type,
TREE_TYPE (old_type),
tree
check_explicit_specialization (tree declarator,
- tree decl,
- int template_count,
- int flags)
+ tree decl,
+ int template_count,
+ int flags)
{
int have_def = flags & 2;
int is_friend = flags & 4;
template <class T> void f<int>(); */
error ("template-id %qD in declaration of primary template",
- declarator);
+ declarator);
return decl;
}
}
case tsk_excessive_parms:
case tsk_insufficient_parms:
if (tsk == tsk_excessive_parms)
- error ("too many template parameter lists in declaration of %qD",
+ error ("too many template parameter lists in declaration of %qD",
decl);
else if (template_header_count)
error("too few template parameter lists in declaration of %qD", decl);
"is not allowed", declarator);
else
error ("template-id %qD in declaration of primary template",
- declarator);
+ declarator);
return decl;
}
template <class T> struct S {
template <class U> void f (U);
- };
+ };
template <> template <class U> void S<int>::f(U) {}
That's a specialization -- but of the entire template. */
else
{
/* If there is no class context, the explicit instantiation
- must be at namespace scope. */
+ must be at namespace scope. */
gcc_assert (DECL_NAMESPACE_SCOPE_P (decl));
/* Find the namespace binding, using the declaration
- context. */
+ context. */
fns = namespace_binding (dname, CP_DECL_CONTEXT (decl));
if (!fns || !is_overloaded_fn (fns))
{
/* It's not valid to write an explicit instantiation in
class scope, e.g.:
- class C { template void f(); }
+ class C { template void f(); }
This case is caught by the parser. However, on
something like:
template it specializes. */
TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
+ /* The specialization has the same visibility as the
+ template it specializes. */
+ if (DECL_VISIBILITY_SPECIFIED (gen_tmpl))
+ {
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ DECL_VISIBILITY (decl) = DECL_VISIBILITY (gen_tmpl);
+ }
+ /* If DECL is a friend declaration, declared using an
+ unqualified name, the namespace associated with DECL may
+ have been set incorrectly. For example, in:
+
+ template <typename T> void f(T);
+ namespace N {
+ struct S { friend void f<int>(int); }
+ }
+
+ we will have set the DECL_CONTEXT for the friend
+ declaration to N, rather than to the global namespace. */
+ if (DECL_NAMESPACE_SCOPE_P (decl))
+ DECL_CONTEXT (decl) = DECL_CONTEXT (tmpl);
if (is_friend && !have_def)
/* This is not really a declaration of a specialization.
/* Register this specialization so that we can find it
again. */
- decl = register_specialization (decl, gen_tmpl, targs);
+ decl = register_specialization (decl, gen_tmpl, targs, is_friend);
}
}
|| TEMPLATE_PARMS_FOR_INLINE (current_template_parms))
return;
- cp_error_at ("declaration of %q#D", decl);
- cp_error_at (" shadows template parm %q#D", olddecl);
+ error ("declaration of %q+#D", decl);
+ error (" shadows template parm %q+#D", olddecl);
}
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
static tree
build_template_parm_index (int index,
- int level,
- int orig_level,
- tree decl,
- tree type)
+ int level,
+ int orig_level,
+ tree decl,
+ tree type)
{
tree t = make_node (TEMPLATE_PARM_INDEX);
TEMPLATE_PARM_IDX (t) = index;
decl, type);
TEMPLATE_PARM_DESCENDANTS (index) = t;
- /* Template template parameters need this. */
- DECL_TEMPLATE_PARMS (decl)
- = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
+ /* Template template parameters need this. */
+ if (TREE_CODE (decl) != CONST_DECL)
+ DECL_TEMPLATE_PARMS (decl)
+ = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
}
return TEMPLATE_PARM_DESCENDANTS (index);
TREE_INVARIANT (parm) = 1;
TREE_READONLY (parm) = 1;
if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
- TREE_TYPE (parm) = void_type_node;
+ TREE_TYPE (parm) = void_type_node;
decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
TREE_CONSTANT (decl) = 1;
TREE_INVARIANT (decl) = 1;
&& tpd.arg_uses_template_parms [j])
{
error ("type %qT of template argument %qE depends "
- "on template parameter(s)",
- type,
- arg);
+ "on template parameter(s)",
+ type,
+ arg);
break;
}
}
if (TREE_CODE (decl) != TYPE_DECL || is_partial || !is_primary)
/* For an ordinary class template, default template arguments are
allowed at the innermost level, e.g.:
- template <class T = int>
+ template <class T = int>
struct S {};
but, in a partial specialization, they're not allowed even
there, as we have in [temp.class.spec]:
examine the parameters to the class itself. On the one
hand, they will be checked when the class is defined, and,
on the other, default arguments are valid in things like:
- template <class T = double>
- struct S { template <class U> void f(U); };
+ template <class T = double>
+ struct S { template <class U> void f(U); };
Here the default argument for `S' has no bearing on the
declaration of `f'. */
last_level_to_check = template_class_depth (current_class_type) + 1;
previously existing one, if appropriate. Returns the DECL, or an
equivalent one, if it is replaced via a call to duplicate_decls.
- If IS_FRIEND is nonzero, DECL is a friend declaration. */
+ If IS_FRIEND is true, DECL is a friend declaration. */
tree
-push_template_decl_real (tree decl, int is_friend)
+push_template_decl_real (tree decl, bool is_friend)
{
tree tmpl;
tree args;
&& TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
- is_friend |= (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl));
+ if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl))
+ is_friend = true;
if (is_friend)
/* For a friend, we want the context of the friend function, not
{
/* [temp.mem]
- A destructor shall not be a member template. */
+ A destructor shall not be a member template. */
error ("destructor %qD declared as member template", decl);
return error_mark_node;
}
{
/* [basic.stc.dynamic.allocation]
- An allocation function can be a function
+ An allocation function can be a function
template. ... Template allocation functions shall
have two or more parameters. */
error ("invalid template declaration of %qD", decl);
register_specialization (new_tmpl,
most_general_template (tmpl),
- args);
+ args,
+ is_friend);
return decl;
}
if (TMPL_ARGS_DEPTH (args) != i)
{
error ("expected %d levels of template parms for %q#D, got %d",
- i, decl, TMPL_ARGS_DEPTH (args));
+ i, decl, TMPL_ARGS_DEPTH (args));
}
else
for (current = decl; i > 0; --i, parms = TREE_CHAIN (parms))
{
if (current == decl)
error ("got %d template parameters for %q#D",
- TREE_VEC_LENGTH (a), decl);
+ TREE_VEC_LENGTH (a), decl);
else
error ("got %d template parameters for %q#T",
- TREE_VEC_LENGTH (a), current);
+ TREE_VEC_LENGTH (a), current);
error (" but %d required", TREE_VEC_LENGTH (t));
+ return error_mark_node;
}
/* Perhaps we should also check that the parms are used in the
- appropriate qualifying scopes in the declarator? */
+ appropriate qualifying scopes in the declarator? */
if (current == decl)
current = ctx;
if (new_template_p && !ctx
&& !(is_friend && template_class_depth (current_class_type) > 0))
{
- tmpl = pushdecl_namespace_level (tmpl);
+ tmpl = pushdecl_namespace_level (tmpl, is_friend);
if (tmpl == error_mark_node)
return error_mark_node;
tree
push_template_decl (tree decl)
{
- return push_template_decl_real (decl, 0);
+ return push_template_decl_real (decl, false);
}
/* Called when a class template TYPE is redeclared with the indicated
if (TREE_VEC_LENGTH (parms) != TREE_VEC_LENGTH (tmpl_parms))
{
- cp_error_at ("previous declaration %qD", tmpl);
+ error ("previous declaration %q+D", tmpl);
error ("used %d template parameter(s) instead of %d",
TREE_VEC_LENGTH (tmpl_parms),
TREE_VEC_LENGTH (parms));
|| (TREE_CODE (tmpl_parm) != TYPE_DECL
&& !same_type_p (TREE_TYPE (tmpl_parm), TREE_TYPE (parm))))
{
- cp_error_at ("template parameter %q#D", tmpl_parm);
+ error ("template parameter %q+#D", tmpl_parm);
error ("redeclared here as %q#D", parm);
return;
}
if (!real_lvalue_p (expr))
{
error ("%qE is not a valid template argument for type %qT "
- "because it is not a lvalue", expr, type);
+ "because it is not a lvalue", expr, type);
return NULL_TREE;
}
else if (TYPE_PTRFN_P (type))
{
/* If the argument is a template-id, we might not have enough
- context information to decay the pointer.
- ??? Why static5.C requires decay and subst1.C works fine
- even without it? */
+ context information to decay the pointer. */
if (!type_unknown_p (expr_type))
{
expr = decay_conversion (expr);
static int
coerce_template_template_parms (tree parm_parms,
- tree arg_parms,
- tsubst_flags_t complain,
+ tree arg_parms,
+ tsubst_flags_t complain,
tree in_decl,
- tree outer_args)
+ tree outer_args)
{
int nparms, nargs, i;
tree parm, arg;
arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
if (arg == NULL_TREE || arg == error_mark_node
- || parm == NULL_TREE || parm == error_mark_node)
+ || parm == NULL_TREE || parm == error_mark_node)
return 0;
if (TREE_CODE (arg) != TREE_CODE (parm))
- return 0;
+ return 0;
switch (TREE_CODE (parm))
{
static tree
convert_template_argument (tree parm,
- tree arg,
- tree args,
- tsubst_flags_t complain,
- int i,
- tree in_decl)
+ tree arg,
+ tree args,
+ tsubst_flags_t complain,
+ int i,
+ tree in_decl)
{
tree val;
tree inner_args;
&& TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
{
pedwarn ("to refer to a type member of a template parameter, "
- "use %<typename %E%>", arg);
+ "use %<typename %E%>", arg);
arg = make_typename_type (TREE_OPERAND (arg, 0),
TREE_OPERAND (arg, 1),
if (complain & tf_error)
{
error ("type/value mismatch at argument %d in template "
- "parameter list for %qD",
- i + 1, in_decl);
+ "parameter list for %qD",
+ i + 1, in_decl);
if (is_type)
error (" expected a constant of type %qT, got %qT",
- TREE_TYPE (parm),
- (is_tmpl_type ? DECL_NAME (arg) : arg));
+ TREE_TYPE (parm),
+ (is_tmpl_type ? DECL_NAME (arg) : arg));
else if (requires_tmpl_type)
error (" expected a class template, got %qE", arg);
else
if (in_decl && (complain & tf_error))
{
error ("type/value mismatch at argument %d in template "
- "parameter list for %qD",
- i + 1, in_decl);
+ "parameter list for %qD",
+ i + 1, in_decl);
if (is_tmpl_type)
error (" expected a type, got %qT", DECL_NAME (arg));
else
if (in_decl && (complain & tf_error))
{
error ("type/value mismatch at argument %d in "
- "template parameter list for %qD",
- i + 1, in_decl);
+ "template parameter list for %qD",
+ i + 1, in_decl);
error (" expected a template of type %qD, got %qD",
- parm, arg);
+ parm, arg);
}
val = error_mark_node;
tree t = tsubst (TREE_TYPE (parm), args, complain, in_decl);
if (invalid_nontype_parm_type_p (t, complain))
- return error_mark_node;
+ return error_mark_node;
if (!uses_template_parms (arg) && !uses_template_parms (t))
/* We used to call digest_init here. However, digest_init
static tree
coerce_template_parms (tree parms,
- tree args,
- tree in_decl,
+ tree args,
+ tree in_decl,
tsubst_flags_t complain,
int require_all_arguments)
{
if (complain & tf_error)
{
error ("wrong number of template arguments (%d, should be %d)",
- nargs, nparms);
+ nargs, nparms);
if (in_decl)
- cp_error_at ("provided for %qD", in_decl);
+ error ("provided for %q+D", in_decl);
}
return error_mark_node;
{
/* Already substituted with real template. Just output
the template name here */
- tree context = DECL_CONTEXT (arg);
- if (context)
- {
- /* The template may be defined in a namespace, or
- may be a member template. */
- gcc_assert (TREE_CODE (context) == NAMESPACE_DECL
+ tree context = DECL_CONTEXT (arg);
+ if (context)
+ {
+ /* The template may be defined in a namespace, or
+ may be a member template. */
+ gcc_assert (TREE_CODE (context) == NAMESPACE_DECL
|| CLASS_TYPE_P (context));
cat (decl_as_string (DECL_CONTEXT (arg),
TFF_PLAIN_IDENTIFIER));
tree
lookup_template_class (tree d1,
- tree arglist,
- tree in_decl,
- tree context,
- int entering_scope,
- tsubst_flags_t complain)
+ tree arglist,
+ tree in_decl,
+ tree context,
+ int entering_scope,
+ tsubst_flags_t complain)
{
tree template = NULL_TREE, parmlist;
tree t;
if (! template)
{
if (complain & tf_error)
- error ("%qT is not a template", d1);
+ error ("%qT is not a template", d1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (TREE_CODE (template) != TEMPLATE_DECL
- /* Make sure it's a user visible template, if it was named by
+ /* Make sure it's a user visible template, if it was named by
the user. */
|| ((complain & tf_user) && !DECL_TEMPLATE_PARM_P (template)
&& !PRIMARY_TEMPLATE_P (template)))
{
if (complain & tf_error)
- {
- error ("non-template type %qT used as a template", d1);
- if (in_decl)
- cp_error_at ("for template declaration %qD", in_decl);
+ {
+ error ("non-template type %qT used as a template", d1);
+ if (in_decl)
+ error ("for template declaration %q+D", in_decl);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
if (DECL_TEMPLATE_TEMPLATE_PARM_P (template))
{
/* Create a new TEMPLATE_DECL and TEMPLATE_TEMPLATE_PARM node to store
- template arguments */
+ template arguments */
tree parm;
tree arglist2;
arglist = add_to_template_args (current_template_args (), arglist);
arglist2 = coerce_template_parms (parmlist, arglist, template,
- complain, /*require_all_args=*/1);
+ complain, /*require_all_args=*/1);
if (arglist2 == error_mark_node
|| (!uses_template_parms (arglist2)
&& check_instantiated_args (template, arglist2, complain)))
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, parm);
For example, given:
template <class T> struct S1 {
- template <class U> struct S2 {};
+ template <class U> struct S2 {};
template <class U> struct S2<U*> {};
- };
+ };
we will be called with an ARGLIST of `U*', but the
TEMPLATE will be `template <class T> template
{
tree a = coerce_template_parms (TREE_VALUE (t),
arglist, template,
- complain, /*require_all_args=*/1);
+ complain, /*require_all_args=*/1);
/* Don't process further if one of the levels fails. */
if (a == error_mark_node)
= coerce_template_parms (INNERMOST_TEMPLATE_PARMS (parmlist),
INNERMOST_TEMPLATE_ARGS (arglist),
template,
- complain, /*require_all_args=*/1);
+ complain, /*require_all_args=*/1);
if (arglist == error_mark_node)
/* We were unable to bind the arguments. */
}
}
if (found)
- POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
+ POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, found);
/* If we already have this specialization, return it. */
found = retrieve_specialization (template, arglist,
= TREE_PROTECTED (TYPE_STUB_DECL (template_type));
DECL_IN_SYSTEM_HEADER (type_decl)
= DECL_IN_SYSTEM_HEADER (template);
+ if (CLASSTYPE_VISIBILITY_SPECIFIED (template_type))
+ {
+ DECL_VISIBILITY_SPECIFIED (type_decl) = 1;
+ DECL_VISIBILITY (type_decl) = CLASSTYPE_VISIBILITY (template_type);
+ }
/* Set up the template information. We have to figure out which
template is the immediate parent if this is a full
if (!found)
{
/* There was no partial instantiation. This happens
- where C<T> is a member template of A<T> and it's used
- in something like
+ where C<T> is a member template of A<T> and it's used
+ in something like
- template <typename T> struct B { A<T>::C<int> m; };
- B<float>;
+ template <typename T> struct B { A<T>::C<int> m; };
+ B<float>;
- Create the partial instantiation.
- */
- TREE_VEC_LENGTH (arglist)--;
- found = tsubst (template, arglist, complain, NULL_TREE);
- TREE_VEC_LENGTH (arglist)++;
- }
+ Create the partial instantiation.
+ */
+ TREE_VEC_LENGTH (arglist)--;
+ found = tsubst (template, arglist, complain, NULL_TREE);
+ TREE_VEC_LENGTH (arglist)++;
+ }
}
SET_TYPE_TEMPLATE_INFO (t, tree_cons (found, arglist, NULL_TREE));
|| TREE_CODE (t) == TEMPLATE_PARM_INDEX
|| TREE_CODE (t) == OVERLOAD
|| TREE_CODE (t) == BASELINK
+ || TREE_CODE (t) == IDENTIFIER_NODE
|| CONSTANT_CLASS_P (t))
dependent_p = (type_dependent_expression_p (t)
|| value_dependent_expression_p (t));
{
/* If the instantiation in question still has unbound template parms,
we don't really care if we can't instantiate it, so just return.
- This happens with base instantiation for implicit `typename'. */
+ This happens with base instantiation for implicit `typename'. */
if (uses_template_parms (d))
return 0;
last_template_error_tick = tinst_level_tick;
error ("template instantiation depth exceeds maximum of %d (use "
- "-ftemplate-depth-NN to increase the maximum) instantiating %qD",
+ "-ftemplate-depth-NN to increase the maximum) instantiating %qD",
max_tinst_depth, d);
print_instantiation_context ();
tree ns = decl_namespace_context (TYPE_MAIN_DECL (current_class_type));
/* Friend functions are looked up in the containing namespace scope.
- We must enter that scope, to avoid finding member functions of the
- current cless with same name. */
+ We must enter that scope, to avoid finding member functions of the
+ current cless with same name. */
push_nested_namespace (ns);
fns = tsubst_expr (DECL_TI_TEMPLATE (decl), args,
- tf_error | tf_warning, NULL_TREE);
+ tf_error | tf_warning, NULL_TREE);
pop_nested_namespace (ns);
arglist = tsubst (DECL_TI_ARGS (decl), args,
- tf_error | tf_warning, NULL_TREE);
+ tf_error | tf_warning, NULL_TREE);
template_id = lookup_template_function (fns, arglist);
new_friend = tsubst (decl, args, tf_error | tf_warning, NULL_TREE);
into the namespace of the template. */
ns = decl_namespace_context (new_friend);
push_nested_namespace (ns);
- old_decl = pushdecl_namespace_level (new_friend);
+ old_decl = pushdecl_namespace_level (new_friend, /*is_friend=*/true);
pop_nested_namespace (ns);
if (old_decl != new_friend)
friend void f(int);
template <class T> class C {
- friend void f(T) {}
- };
+ friend void f(T) {}
+ };
when `C<int>' is instantiated. Now, `f(int)' is defined
in the class. */
tmpl = tsubst (friend_tmpl, args, tf_error | tf_warning, NULL_TREE);
/* The new TMPL is not an instantiation of anything, so we
- forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
+ forget its origins. We don't reset CLASSTYPE_TI_TEMPLATE for
the new type because that is supposed to be the corresponding
template decl, i.e., TMPL. */
DECL_USE_TEMPLATE (tmpl) = 0;
= INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE (tmpl)));
/* Inject this template into the global scope. */
- friend_type = TREE_TYPE (pushdecl_top_level (tmpl));
+ friend_type = TREE_TYPE (pushdecl_top_level_maybe_friend (tmpl, true));
}
if (context)
{
if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
{
- cp_error_at ("%s %+#T", str, TREE_TYPE (t));
+ error ("%s %+#T", str, TREE_TYPE (t));
str = " ";
}
}
TYPE_FOR_JAVA (type) = TYPE_FOR_JAVA (pattern); /* For libjava's JArray<T> */
if (ANON_AGGR_TYPE_P (pattern))
SET_ANON_AGGR_TYPE_P (type);
+ if (CLASSTYPE_VISIBILITY_SPECIFIED (pattern))
+ {
+ CLASSTYPE_VISIBILITY_SPECIFIED (type) = 1;
+ CLASSTYPE_VISIBILITY (type) = CLASSTYPE_VISIBILITY (pattern);
+ }
pbinfo = TYPE_BINFO (pattern);
--processing_template_decl;
if (TREE_CODE (r) == VAR_DECL)
{
- tree init;
-
- if (DECL_INITIALIZED_IN_CLASS_P (r))
- init = tsubst_expr (DECL_INITIAL (t), args,
- tf_error | tf_warning, NULL_TREE);
- else
- init = NULL_TREE;
-
- finish_static_data_member_decl
- (r, init, /*asmspec_tree=*/NULL_TREE, /*flags=*/0);
-
+ /* In [temp.inst]:
+
+ [t]he initialization (and any associated
+ side-effects) of a static data member does
+ not occur unless the static data member is
+ itself used in a way that requires the
+ definition of the static data member to
+ exist.
+
+ Therefore, we do not substitute into the
+ initialized for the static data member here. */
+ finish_static_data_member_decl
+ (r,
+ /*init=*/NULL_TREE,
+ /*asmspec_tree=*/NULL_TREE,
+ /*flags=*/0);
if (DECL_INITIALIZED_IN_CLASS_P (r))
check_static_variable_definition (r, TREE_TYPE (r));
}
if (!COMPLETE_TYPE_P (rtype))
{
cxx_incomplete_type_error (r, rtype);
- r = error_mark_node;
+ r = error_mark_node;
}
}
set_current_access_from_decl (r);
finish_member_declaration (r);
}
- }
+ }
}
}
else
{
/* template <class T> friend class C; */
friend_type = tsubst_friend_class (friend_type, args);
- adjust_processing_template_decl = true;
+ adjust_processing_template_decl = true;
}
else if (TREE_CODE (friend_type) == UNBOUND_CLASS_TEMPLATE)
{
tf_error | tf_warning, NULL_TREE);
if (TREE_CODE (friend_type) == TEMPLATE_DECL)
friend_type = TREE_TYPE (friend_type);
- adjust_processing_template_decl = true;
+ adjust_processing_template_decl = true;
}
else if (TREE_CODE (friend_type) == TYPENAME_TYPE)
{
friend class C<int>;
- We don't have to do anything in these cases. */
+ We don't have to do anything in these cases. */
if (adjust_processing_template_decl)
/* Trick make_friend_class into realizing that the friend
++processing_template_decl;
if (friend_type != error_mark_node)
- make_friend_class (type, friend_type, /*complain=*/false);
+ make_friend_class (type, friend_type, /*complain=*/false);
if (adjust_processing_template_decl)
--processing_template_decl;
else
{
r = tsubst_expr (t, args, complain, in_decl);
-
- if (!uses_template_parms (r))
- {
- /* Sometimes, one of the args was an expression involving a
- template constant parameter, like N - 1. Now that we've
- tsubst'd, we might have something like 2 - 1. This will
- confuse lookup_template_class, so we do constant folding
- here. We have to unset processing_template_decl, to fool
- tsubst_copy_and_build() into building an actual tree. */
-
- /* If the TREE_TYPE of ARG is not NULL_TREE, ARG is already
- as simple as it's going to get, and trying to reprocess
- the trees will break. Once tsubst_expr et al DTRT for
- non-dependent exprs, this code can go away, as the type
- will always be set. */
- if (!TREE_TYPE (r))
- {
- int saved_processing_template_decl = processing_template_decl;
- processing_template_decl = 0;
- r = tsubst_copy_and_build (r, /*args=*/NULL_TREE,
- tf_error, /*in_decl=*/NULL_TREE,
- /*function_p=*/false);
- processing_template_decl = saved_processing_template_decl;
- }
- r = fold (r);
- }
+ r = fold_non_dependent_expr (r);
}
return r;
}
tree parm_decl = TREE_VALUE (tuple);
parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
+ if (TREE_CODE (parm_decl) == PARM_DECL
+ && invalid_nontype_parm_type_p (TREE_TYPE (parm_decl), complain))
+ parm_decl = error_mark_node;
default_value = tsubst_template_arg (default_value, args,
complain, NULL_TREE);
static tree
tsubst_aggr_type (tree t,
- tree args,
- tsubst_flags_t complain,
- tree in_decl,
- int entering_scope)
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl,
+ int entering_scope)
{
if (t == NULL_TREE)
return NULL_TREE;
tree argvec;
tree context;
tree r;
+ bool saved_skip_evaluation;
+
+ /* In "sizeof(X<I>)" we need to evaluate "I". */
+ saved_skip_evaluation = skip_evaluation;
+ skip_evaluation = false;
/* First, determine the context for the type we are looking
up. */
argvec = tsubst_template_args (TYPE_TI_ARGS (t), args,
complain, in_decl);
if (argvec == error_mark_node)
- return error_mark_node;
-
- r = lookup_template_class (t, argvec, in_decl, context,
- entering_scope, complain);
+ r = error_mark_node;
+ else
+ {
+ r = lookup_template_class (t, argvec, in_decl, context,
+ entering_scope, complain);
+ r = cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
+ }
+
+ skip_evaluation = saved_skip_evaluation;
- return cp_build_qualified_type_real (r, TYPE_QUALS (t), complain);
+ return r;
}
else
/* This is not a template type, so there's nothing to do. */
we must be careful to do name lookup in the scope of S<T>,
rather than in the current class. */
push_access_scope (fn);
- /* The default argument expression should not be considered to be
- 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)
{
: DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
full_args = tsubst_template_args (tmpl_args, args,
complain, in_decl);
+ if (full_args == error_mark_node)
+ return error_mark_node;
/* tsubst_template_args doesn't copy the vector if
nothing changed. But, *something* should have
if (TREE_CODE (decl) != TYPE_DECL)
/* Record this non-type partial instantiation. */
register_specialization (r, t,
- DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)));
+ DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
+ false);
}
break;
there was a specialization of a member template, like
this:
- template <class T> struct S { template <class U> void f(); }
+ template <class T> struct S { template <class U> void f(); }
template <> template <class U> void S<int>::f(U);
Here, we'll be substituting into the specialization,
{
/* This special case arises when we have something like this:
- template <class T> struct S {
+ template <class T> struct S {
friend void f<int>(int, double);
};
return error_mark_node;
/* We do NOT check for matching decls pushed separately at this
- point, as they may not represent instantiations of this
- template, and in any case are considered separate under the
- discrete model. */
+ point, as they may not represent instantiations of this
+ template, and in any case are considered separate under the
+ discrete model. */
r = copy_decl (t);
DECL_USE_TEMPLATE (r) = 0;
TREE_TYPE (r) = type;
DECL_TEMPLATE_INFO (r)
= tree_cons (gen_tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
- register_specialization (r, gen_tmpl, argvec);
+ register_specialization (r, gen_tmpl, argvec, false);
/* We're not supposed to instantiate default arguments
until they are called, for a template. But, for a
declaration like:
- template <class T> void f ()
- { extern void g(int i = T()); }
+ template <class T> void f ()
+ { extern void g(int i = T()); }
we should do the substitution when the template is
instantiated. We handle the member function case in
&& !uses_template_parms (argvec))
tsubst_default_arguments (r);
}
+ else
+ DECL_TEMPLATE_INFO (r) = NULL_TREE;
/* Copy the list of befriending classes. */
for (friends = &DECL_BEFRIENDING_CLASSES (r);
complain, in_decl);
TREE_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type))
- cp_error_at ("instantiation of %qD as type %qT", r, type);
+ error ("instantiation of %q+D as type %qT", r, type);
}
break;
r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL)
{
+ /* Even if the original location is out of scope, the
+ newly substituted one is not. */
+ DECL_DEAD_FOR_LOCAL (r) = 0;
+ DECL_INITIALIZED_P (r) = 0;
+ DECL_TEMPLATE_INSTANTIATED (r) = 0;
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
if (type == error_mark_node)
return error_mark_node;
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
type = check_var_type (DECL_NAME (r), type);
+
+ if (DECL_HAS_VALUE_EXPR_P (t))
+ {
+ tree ve = DECL_VALUE_EXPR (t);
+ ve = tsubst_expr (ve, args, complain, in_decl);
+ SET_DECL_VALUE_EXPR (r, ve);
+ }
}
else if (DECL_SELF_REFERENCE_P (t))
SET_DECL_SELF_REFERENCE_P (r);
DECL_CONTEXT (r) = ctx;
/* Clear out the mangled name and RTL for the instantiation. */
SET_DECL_ASSEMBLER_NAME (r, NULL_TREE);
- SET_DECL_RTL (r, NULL_RTX);
-
- /* Don't try to expand the initializer until someone tries to use
- this variable; otherwise we run into circular dependencies. */
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
+ SET_DECL_RTL (r, NULL_RTX);
+ /* The initializer must not be expanded until it is required;
+ see [temp.inst]. */
DECL_INITIAL (r) = NULL_TREE;
- SET_DECL_RTL (r, NULL_RTX);
+ if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
+ SET_DECL_RTL (r, NULL_RTX);
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
- /* Even if the original location is out of scope, the newly
- substituted one is not. */
- if (TREE_CODE (r) == VAR_DECL)
- {
- DECL_DEAD_FOR_LOCAL (r) = 0;
- DECL_INITIALIZED_P (r) = 0;
- }
-
if (!local_p)
{
/* A static data member declaration is always marked
processing here. */
DECL_EXTERNAL (r) = 1;
- register_specialization (r, gen_tmpl, argvec);
+ register_specialization (r, gen_tmpl, argvec, false);
DECL_TEMPLATE_INFO (r) = tree_cons (tmpl, argvec, NULL_TREE);
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
static tree
tsubst_arg_types (tree arg_types,
- tree args,
- tsubst_flags_t complain,
- tree in_decl)
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl)
{
tree remaining_arg_types;
tree type;
if (VOID_TYPE_P (type))
{
if (complain & tf_error)
- {
- error ("invalid parameter type %qT", type);
- if (in_decl)
- cp_error_at ("in declaration %qD", in_decl);
- }
+ {
+ error ("invalid parameter type %qT", type);
+ if (in_decl)
+ error ("in declaration %q+D", in_decl);
+ }
return error_mark_node;
}
if (default_arg && TREE_CODE (default_arg) == DEFAULT_ARG)
{
/* We've instantiated a template before its default arguments
- have been parsed. This can happen for a nested template
- class, and is not an error unless we require the default
- argument in a call of this function. */
+ have been parsed. This can happen for a nested template
+ class, and is not an error unless we require the default
+ argument in a call of this function. */
result = tree_cons (default_arg, type, remaining_arg_types);
VEC_safe_push (tree, gc, DEFARG_INSTANTIATIONS (default_arg), result);
}
static tree
tsubst_function_type (tree t,
- tree args,
- tsubst_flags_t complain,
- tree in_decl)
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl)
{
tree return_type;
tree arg_types;
static tree
tsubst_call_declarator_parms (tree parms,
- tree args,
- tsubst_flags_t complain,
- tree in_decl)
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl)
{
tree new_parms;
tree type;
if (cp_type_quals (t))
{
r = tsubst (TYPE_MAIN_VARIANT (t), args, complain, in_decl);
- r = cp_build_qualified_type_real
- (r, cp_type_quals (t),
+ r = cp_build_qualified_type_real
+ (r, cp_type_quals (t),
complain | (TREE_CODE (t) == TEMPLATE_TYPE_PARM
? tf_ignore_bad_quals : 0));
}
error ("forming reference to void");
else
error ("forming %s to reference type %qT",
- (code == POINTER_TYPE) ? "pointer" : "reference",
- type);
+ (code == POINTER_TYPE) ? "pointer" : "reference",
+ type);
last_loc = input_location;
}
reasons:
-- Attempting to create "pointer to member of T" when T
- is not a class type. */
+ is not a class type. */
if (complain & tf_error)
error ("creating pointer to member of non-class type %qT", r);
return error_mark_node;
gcc_assert (TREE_CODE (type) != METHOD_TYPE);
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- /* The type of the implicit object parameter gets its
- cv-qualifiers from the FUNCTION_TYPE. */
+ /* The type of the implicit object parameter gets its
+ cv-qualifiers from the FUNCTION_TYPE. */
tree method_type;
- tree this_type = cp_build_qualified_type (TYPE_MAIN_VARIANT (r),
- cp_type_quals (type));
- tree memptr;
- method_type = build_method_type_directly (this_type,
+ tree this_type = cp_build_qualified_type (TYPE_MAIN_VARIANT (r),
+ cp_type_quals (type));
+ tree memptr;
+ method_type = build_method_type_directly (this_type,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
- memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
- return cp_build_qualified_type_real (memptr, cp_type_quals (t),
- complain);
+ memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
+ return cp_build_qualified_type_real (memptr, cp_type_quals (t),
+ complain);
}
else
return cp_build_qualified_type_real (build_ptrmem_type (r, type),
/* Substitute the exception specification. */
specs = tsubst_exception_specification (t, args, complain,
in_decl);
+ if (specs == error_mark_node)
+ return error_mark_node;
if (specs)
fntype = build_exception_variant (fntype, specs);
return fntype;
/* Normally, make_typename_type does not require that the CTX
have complete type in order to allow things like:
- template <class T> struct S { typename S<T>::X Y; };
+ template <class T> struct S { typename S<T>::X Y; };
But, such constructs have already been resolved by this
point, so here CTX really should have complete type, unless
(complain & tf_error) | tf_keep_type_decl);
if (f == error_mark_node)
return f;
- if (TREE_CODE (f) == TYPE_DECL)
- {
+ if (TREE_CODE (f) == TYPE_DECL)
+ {
complain |= tf_ignore_bad_quals;
- f = TREE_TYPE (f);
- }
+ f = TREE_TYPE (f);
+ }
if (TREE_CODE (f) != TYPENAME_TYPE)
{
t, f);
}
- return cp_build_qualified_type_real
- (f, cp_type_quals (f) | cp_type_quals (t), complain);
+ return cp_build_qualified_type_real
+ (f, cp_type_quals (f) | cp_type_quals (t), complain);
}
case UNBOUND_CLASS_TEMPLATE:
expr = finish_qualified_id_expr (scope, expr, done, address_p);
}
- expr = convert_from_reference (expr);
+ if (TREE_CODE (expr) != SCOPE_REF)
+ expr = convert_from_reference (expr);
return expr;
}
template <template <class> class TT> struct C {};
template <class T> struct D {
template <class U> struct E {};
- C<E> c; // #1
+ C<E> c; // #1
};
D<int> d; // #2
case TEMPLATE_ID_EXPR:
{
- /* Substituted template arguments */
+ /* Substituted template arguments */
tree fn = TREE_OPERAND (t, 0);
tree targs = TREE_OPERAND (t, 1);
return t;
case CONSTRUCTOR:
- {
- r = build_constructor
- (tsubst (TREE_TYPE (t), args, complain, in_decl),
- tsubst_copy (CONSTRUCTOR_ELTS (t), args, complain, in_decl));
- TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
- return r;
- }
+ /* This is handled by tsubst_copy_and_build. */
+ gcc_unreachable ();
case VA_ARG_EXPR:
return build_x_va_arg (tsubst_copy (TREE_OPERAND (t, 0), args, complain,
decl = tsubst (decl, args, complain, in_decl);
if (decl != error_mark_node)
{
- if (init)
- DECL_INITIAL (decl) = error_mark_node;
- /* By marking the declaration as instantiated, we avoid
- trying to instantiate it. Since instantiate_decl can't
- handle local variables, and since we've already done
- all that needs to be done, that's the right thing to
- do. */
- if (TREE_CODE (decl) == VAR_DECL)
- DECL_TEMPLATE_INSTANTIATED (decl) = 1;
+ if (init)
+ DECL_INITIAL (decl) = error_mark_node;
+ /* By marking the declaration as instantiated, we avoid
+ trying to instantiate it. Since instantiate_decl can't
+ handle local variables, and since we've already done
+ all that needs to be done, that's the right thing to
+ do. */
+ if (TREE_CODE (decl) == VAR_DECL)
+ DECL_TEMPLATE_INSTANTIATED (decl) = 1;
if (TREE_CODE (decl) == VAR_DECL
&& ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
/* Anonymous aggregates are a special case. */
tree
tsubst_copy_and_build (tree t,
- tree args,
- tsubst_flags_t complain,
- tree in_decl,
+ tree args,
+ tsubst_flags_t complain,
+ tree in_decl,
bool function_p)
{
#define RECUR(NODE) \
case CONSTRUCTOR:
{
+ VEC(constructor_elt,gc) *n;
+ constructor_elt *ce;
+ unsigned HOST_WIDE_INT idx;
tree r;
- tree elts;
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
- bool purpose_p;
+ bool process_index_p;
/* digest_init will do the wrong thing if we let it. */
if (type && TYPE_PTRMEMFUNC_P (type))
return t;
- r = NULL_TREE;
- /* We do not want to process the purpose of aggregate
+ /* We do not want to process the index of aggregate
initializers as they are identifier nodes which will be
looked up by digest_init. */
- purpose_p = !(type && IS_AGGR_TYPE (type));
- for (elts = CONSTRUCTOR_ELTS (t);
- elts;
- elts = TREE_CHAIN (elts))
- {
- tree purpose = TREE_PURPOSE (elts);
- tree value = TREE_VALUE (elts);
+ process_index_p = !(type && IS_AGGR_TYPE (type));
- if (purpose && purpose_p)
- purpose = RECUR (purpose);
- value = RECUR (value);
- r = tree_cons (purpose, value, r);
+ n = VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
+ for (idx = 0; VEC_iterate (constructor_elt, n, idx, ce); idx++)
+ {
+ if (ce->index && process_index_p)
+ ce->index = RECUR (ce->index);
+ ce->value = RECUR (ce->value);
}
- r = build_constructor (NULL_TREE, nreverse (r));
+ r = build_constructor (NULL_TREE, n);
TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
if (type)
- return digest_init (type, r, 0);
+ return digest_init (type, r);
return r;
}
{
int ix, len = DECL_NTPARMS (tmpl);
bool result = false;
- bool error_p = complain & tf_error;
for (ix = 0; ix != len; ix++)
{
if (nt)
{
- if (TYPE_ANONYMOUS_P (nt))
- error ("%qT is/uses anonymous type", t);
- else
- error ("%qT uses local type %qT", t, nt);
+ /* DR 488 makes use of a type with no linkage causes
+ type deduction to fail. */
+ if (complain & tf_error)
+ {
+ if (TYPE_ANONYMOUS_P (nt))
+ error ("%qT is/uses anonymous type", t);
+ else
+ error ("%qT uses local type %qT", t, nt);
+ }
result = true;
- error_p = true;
}
/* In order to avoid all sorts of complications, we do not
allow variably-modified types as template arguments. */
result = true;
}
}
- if (result && error_p)
+ if (result && (complain & tf_error))
error (" trying to instantiate %qD", tmpl);
return result;
}
int
fn_type_unification (tree fn,
- tree explicit_targs,
- tree targs,
- tree args,
- tree return_type,
- unification_kind_t strict)
+ tree explicit_targs,
+ tree targs,
+ tree args,
+ tree return_type,
+ unification_kind_t strict,
+ int flags)
{
tree parms;
tree fntype;
return 1;
/* Substitute the explicit args into the function type. This is
- necessary so that, for instance, explicitly declared function
- arguments can match null pointed constants. If we were given
- an incomplete set of explicit args, we must not do semantic
- processing during substitution as we could create partial
- instantiations. */
+ necessary so that, for instance, explicitly declared function
+ arguments can match null pointed constants. If we were given
+ an incomplete set of explicit args, we must not do semantic
+ processing during substitution as we could create partial
+ instantiations. */
incomplete = NUM_TMPL_ARGS (explicit_targs) != NUM_TMPL_ARGS (targs);
processing_template_decl += incomplete;
fntype = tsubst (fntype, converted_args, tf_none, NULL_TREE);
if (return_type)
{
- /* We've been given a return type to match, prepend it. */
parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
args = tree_cons (NULL_TREE, return_type, args);
}
event. */
result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
targs, parms, args, /*subr=*/0,
- strict, /*allow_incomplete*/1);
+ strict, flags);
if (result == 0)
/* All is well so far. Now, check:
static int
maybe_adjust_types_for_deduction (unification_kind_t strict,
- tree* parm,
- tree* arg)
+ tree* parm,
+ tree* arg)
{
int result = 0;
If SUBR is 1, we're being called recursively (to unify the
arguments of a function or method parameter of a function
- template). */
+ template). */
static int
type_unification_real (tree tparms,
- tree targs,
- tree xparms,
- tree xargs,
- int subr,
+ tree targs,
+ tree xparms,
+ tree xargs,
+ int subr,
unification_kind_t strict,
- int allow_incomplete)
+ int flags)
{
tree parm, arg;
int i;
{
case DEDUCE_CALL:
sub_strict = (UNIFY_ALLOW_OUTER_LEVEL | UNIFY_ALLOW_MORE_CV_QUAL
- | UNIFY_ALLOW_DERIVED);
+ | UNIFY_ALLOW_DERIVED);
break;
case DEDUCE_CONV:
else
type = arg;
- if (strict == DEDUCE_EXACT)
- {
- if (same_type_p (parm, type))
- continue;
- }
- else
- /* It might work; we shouldn't check now, because we might
- get into infinite recursion. Overload resolution will
- handle it. */
+ if (same_type_p (parm, type))
continue;
-
+ if (strict != DEDUCE_EXACT
+ && can_convert_arg (parm, type, TYPE_P (arg) ? NULL_TREE : arg,
+ flags))
+ continue;
+
return 1;
}
}
{
- int arg_strict = sub_strict;
+ int arg_strict = sub_strict;
- if (!subr)
+ if (!subr)
arg_strict |= maybe_adjust_types_for_deduction (strict, &parm, &arg);
- if (unify (tparms, targs, parm, arg, arg_strict))
- return 1;
+ if (unify (tparms, targs, parm, arg, arg_strict))
+ return 1;
}
}
&& !saw_undeduced++)
goto again;
- if (!allow_incomplete)
- error ("incomplete type unification");
return 2;
}
static int
resolve_overloaded_unification (tree tparms,
- tree targs,
- tree parm,
- tree arg,
- unification_kind_t strict,
+ tree targs,
+ tree parm,
+ tree arg,
+ unification_kind_t strict,
int sub_strict)
{
tree tempargs = copy_node (targs);
static int
try_one_overload (tree tparms,
- tree orig_targs,
- tree targs,
- tree parm,
- tree arg,
- unification_kind_t strict,
+ tree orig_targs,
+ tree targs,
+ tree parm,
+ tree arg,
+ unification_kind_t strict,
int sub_strict,
bool addr_p)
{
verify_class_unification (tree targs, tree parms, tree args)
{
parms = tsubst (parms, add_outermost_template_args (args, targs),
- tf_none, NULL_TREE);
+ tf_none, NULL_TREE);
if (parms == error_mark_node)
return 1;
void f(S<I, J, K>, S<I, I, I>);
void g() {
- S<0, 0, 0> s0;
- S<0, 1, 2> s2;
+ S<0, 0, 0> s0;
+ S<0, 1, 2> s2;
- f(s0, s2);
+ f(s0, s2);
}
Now, by the time we consider the unification involving `s2', we
&& !(strict & UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
{
/* Although a CVR qualifier is ignored when being applied to a
- substituted template parameter ([8.3.2]/1 for example), that
- does not apply during deduction [14.8.2.4]/1, (even though
- that is not explicitly mentioned, [14.8.2.4]/9 indicates
- this). Except when we're allowing additional CV qualifiers
- at the outer level [14.8.2.1]/3,1st bullet. */
+ substituted template parameter ([8.3.2]/1 for example), that
+ does not apply during deduction [14.8.2.4]/1, (even though
+ that is not explicitly mentioned, [14.8.2.4]/9 indicates
+ this). Except when we're allowing additional CV qualifiers
+ at the outer level [14.8.2.1]/3,1st bullet. */
if ((TREE_CODE (arg) == REFERENCE_TYPE
|| TREE_CODE (arg) == FUNCTION_TYPE
|| TREE_CODE (arg) == METHOD_TYPE)
if (TREE_CODE (arg) == TREE_CODE (parm)
&& TYPE_P (arg)
/* It is the elements of the array which hold the cv quals of an array
- type, and the elements might be template type parms. We'll check
- when we recurse. */
+ type, and the elements might be template type parms. We'll check
+ when we recurse. */
&& TREE_CODE (arg) != ARRAY_TYPE
/* We check the cv-qualifiers when unifying with template type
parameters below. We want to allow ARG `const T' to unify with
class vector. */
if (coerce_template_parms (argtmplvec, parmvec, parmtmpl, 0, 1)
- == error_mark_node)
+ == error_mark_node)
return 1;
/* Deduce arguments T, i from TT<T> or TT<i>.
for (i = 0; i < TREE_VEC_LENGTH (parmvec); ++i)
{
- if (unify (tparms, targs,
+ if (unify (tparms, targs,
TREE_VEC_ELT (parmvec, i),
TREE_VEC_ELT (argvec, i),
UNIFY_ALLOW_NONE))
case PTRMEM_CST:
{
- /* A pointer-to-member constant can be unified only with
- another constant. */
+ /* A pointer-to-member constant can be unified only with
+ another constant. */
if (TREE_CODE (arg) != PTRMEM_CST)
- return 1;
+ return 1;
/* Just unify the class member. It would be useless (and possibly
- wrong, depending on the strict flags) to unify also
- PTRMEM_CST_CLASS, because we want to be sure that both parm and
- arg refer to the same variable, even if through different
- classes. For instance:
+ wrong, depending on the strict flags) to unify also
+ PTRMEM_CST_CLASS, because we want to be sure that both parm and
+ arg refer to the same variable, even if through different
+ classes. For instance:
- struct A { int x; };
- struct B : A { };
+ struct A { int x; };
+ struct B : A { };
- Unification of &A::x and &B::x must succeed. */
+ Unification of &A::x and &B::x must succeed. */
return unify (tparms, targs, PTRMEM_CST_MEMBER (parm),
- PTRMEM_CST_MEMBER (arg), strict);
+ PTRMEM_CST_MEMBER (arg), strict);
}
case POINTER_TYPE:
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
+ /* CV qualifications for methods can never be deduced, they must
+ match exactly. We need to check them explicitly here,
+ because type_unification_real treats them as any other
+ cvqualified parameter. */
+ if (TREE_CODE (parm) == METHOD_TYPE
+ && (!check_cv_quals_for_unify
+ (UNIFY_ALLOW_NONE,
+ TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
+ TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
+ return 1;
+
if (unify (tparms, targs, TREE_TYPE (parm),
TREE_TYPE (arg), UNIFY_ALLOW_NONE))
return 1;
return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
- TYPE_ARG_TYPES (arg), 1,
- DEDUCE_EXACT, 0);
+ TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT,
+ LOOKUP_NORMAL);
case OFFSET_TYPE:
/* Unify a pointer to member with a pointer to member function, which
- deduces the type of the member as a function type. */
+ deduces the type of the member as a function type. */
if (TYPE_PTRMEMFUNC_P (arg))
- {
- tree method_type;
- tree fntype;
- cp_cv_quals cv_quals;
-
- /* Check top-level cv qualifiers */
- if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
- return 1;
-
- if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
- TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
-
- /* Determine the type of the function we are unifying against. */
- method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg));
- fntype =
- build_function_type (TREE_TYPE (method_type),
- TREE_CHAIN (TYPE_ARG_TYPES (method_type)));
-
- /* Extract the cv-qualifiers of the member function from the
- implicit object parameter and place them on the function
- type to be restored later. */
- cv_quals =
- cp_type_quals(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (method_type))));
- fntype = build_qualified_type (fntype, cv_quals);
- return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
- }
+ {
+ tree method_type;
+ tree fntype;
+ cp_cv_quals cv_quals;
+
+ /* Check top-level cv qualifiers */
+ if (!check_cv_quals_for_unify (UNIFY_ALLOW_NONE, arg, parm))
+ return 1;
+
+ if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm),
+ TYPE_PTRMEMFUNC_OBJECT_TYPE (arg), UNIFY_ALLOW_NONE))
+ return 1;
+
+ /* Determine the type of the function we are unifying against. */
+ method_type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (arg));
+ fntype =
+ build_function_type (TREE_TYPE (method_type),
+ TREE_CHAIN (TYPE_ARG_TYPES (method_type)));
+
+ /* Extract the cv-qualifiers of the member function from the
+ implicit object parameter and place them on the function
+ type to be restored later. */
+ cv_quals =
+ cp_type_quals(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (method_type))));
+ fntype = build_qualified_type (fntype, cv_quals);
+ return unify (tparms, targs, TREE_TYPE (parm), fntype, strict);
+ }
if (TREE_CODE (arg) != OFFSET_TYPE)
return 1;
tree args2 = TYPE_ARG_TYPES (TREE_TYPE (decl2));
int better1 = 0;
int better2 = 0;
-
- /* If only one is a member function, they are unordered. */
- if (DECL_FUNCTION_MEMBER_P (decl1) != DECL_FUNCTION_MEMBER_P (decl2))
- return 0;
-
- /* Don't consider 'this' parameter. */
+
+ /* Remove the this parameter from non-static member functions. If
+ one is a non-static member function and the other is not a static
+ member function, remove the first parameter from that function
+ also. This situation occurs for operator functions where we
+ locate both a member function (with this pointer) and non-member
+ operator (with explicit first operand). */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl1))
- args1 = TREE_CHAIN (args1);
- if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2))
- args2 = TREE_CHAIN (args2);
-
+ {
+ len--; /* LEN is the number of significant arguments for DECL1 */
+ args1 = TREE_CHAIN (args1);
+ if (!DECL_STATIC_FUNCTION_P (decl2))
+ args2 = TREE_CHAIN (args2);
+ }
+ else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl2))
+ {
+ args2 = TREE_CHAIN (args2);
+ if (!DECL_STATIC_FUNCTION_P (decl1))
+ {
+ len--;
+ args1 = TREE_CHAIN (args1);
+ }
+ }
+
/* If only one is a conversion operator, they are unordered. */
if (DECL_CONV_FN_P (decl1) != DECL_CONV_FN_P (decl2))
return 0;
if (fn_type_unification (fn, explicit_args, targs,
decl_arg_types,
(check_rettype || DECL_CONV_FN_P (fn)
- ? TREE_TYPE (decl_type) : NULL_TREE),
- DEDUCE_EXACT))
+ ? TREE_TYPE (decl_type) : NULL_TREE),
+ DEDUCE_EXACT, LOOKUP_NORMAL))
return NULL_TREE;
return targs;
tree vec = make_tree_vec (ntparms);
if (unify (tparms, vec, parms, INNERMOST_TEMPLATE_ARGS (args),
- UNIFY_ALLOW_NONE))
+ UNIFY_ALLOW_NONE))
return NULL_TREE;
for (i = 0; i < ntparms; ++i)
{
if (pedantic && !in_system_header)
pedwarn ("ISO C++ forbids the use of %<extern%> on explicit "
- "instantiations");
+ "instantiations");
extern_p = 1;
}
else
error ("storage class %qD applied to template instantiation", storage);
-
+
+ check_explicit_instantiation_namespace (result);
mark_decl_instantiated (result, extern_p);
if (! extern_p)
- instantiate_decl (result, /*defer_ok=*/1, /*undefined_ok=*/0);
+ instantiate_decl (result, /*defer_ok=*/1,
+ /*expl_inst_class_mem_p=*/false);
}
void
{
mark_decl_instantiated (decl, extern_p);
if (! extern_p)
- instantiate_decl (decl, /*defer_ok=*/1, /* undefined_ok=*/1);
+ instantiate_decl (decl, /*defer_ok=*/1,
+ /*expl_inst_class_mem_p=*/true);
}
/* Perform an explicit instantiation of template class T. STORAGE, if
{
if (complain & tf_error)
error ("explicit instantiation of %q#T before definition of template",
- t);
+ t);
return;
}
{
if (pedantic && !in_system_header)
pedwarn("ISO C++ forbids the use of %qE on explicit instantiations",
- storage);
+ storage);
if (storage == ridpointers[(int) RID_INLINE])
nomem_p = 1;
else
{
error ("storage class %qD applied to template instantiation",
- storage);
+ storage);
extern_p = 0;
}
}
No program shall explicitly instantiate any template more
than once.
- If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
+ If PREVIOUS_INSTANTIATION_EXTERN_P, then the first explicit
instantiation was `extern'. If EXTERN_P then the second is.
These cases are OK. */
previous_instantiation_extern_p = CLASSTYPE_INTERFACE_ONLY (t);
return;
}
+ check_explicit_instantiation_namespace (TYPE_NAME (t));
mark_class_instantiated (t, extern_p);
if (nomem_p)
declarations, and not the definitions, of members are
instantiated, we have here:
- [temp.explicit]
+ [temp.explicit]
The explicit instantiation of a class template specialization
implies the instantiation of all of its members not
if (CLASSTYPE_NESTED_UTDS (t))
binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
- bt_instantiate_type_proc, &storage);
+ bt_instantiate_type_proc, &storage);
}
}
DECL_INLINE (decl) = 1;
}
else if (TREE_CODE (decl) == VAR_DECL)
- {
- if (!DECL_INITIALIZED_IN_CLASS_P (decl)
- && DECL_INITIAL (code_pattern))
- DECL_INITIAL (decl) =
- tsubst_expr (DECL_INITIAL (code_pattern), args,
- tf_error, DECL_TI_TEMPLATE (decl));
- }
+ DECL_INITIAL (decl) =
+ tsubst_expr (DECL_INITIAL (code_pattern), args,
+ tf_error, DECL_TI_TEMPLATE (decl));
else
gcc_unreachable ();
for the instantiation. This is not always the most general
template. Consider, for example:
- template <class T>
+ template <class T>
struct S { template <class U> void f();
- template <> void f<int>(); };
+ template <> void f<int>(); };
and an instantiation of S<double>::f<int>. We want TD to be the
specialization S<T>::f<int>, not the more general S<T>::f<U>. */
DEFER_OK is nonzero, then we don't have to actually do the
instantiation now; we just have to do it sometime. Normally it is
an error if this is an explicit instantiation but D is undefined.
- If UNDEFINED_OK is nonzero, then instead we treat it as an implicit
- instantiation. UNDEFINED_OK is nonzero only if we are being used
- to instantiate the members of an explicitly instantiated class
- template. */
-
+ EXPL_INST_CLASS_MEM_P is true iff D is a member of an
+ explicitly instantiated class template. */
tree
-instantiate_decl (tree d, int defer_ok, int undefined_ok)
+instantiate_decl (tree d, int defer_ok,
+ bool expl_inst_class_mem_p)
{
tree tmpl = DECL_TI_TEMPLATE (d);
tree gen_args;
tree code_pattern;
tree spec;
tree gen_tmpl;
- int pattern_defined;
+ bool pattern_defined;
int need_push;
location_t saved_loc = input_location;
+ bool external_p;
/* This function should only be used to instantiate templates for
functions and static member variables. */
timevar_push (TV_PARSE);
- /* We may be in the middle of deferred access check. Disable it now. */
- push_deferring_access_checks (dk_no_deferred);
-
/* Set TD to the template whose DECL_TEMPLATE_RESULT is the pattern
for the instantiation. */
td = template_for_substitution (d);
pattern_defined = (DECL_SAVED_TREE (code_pattern) != NULL_TREE);
else
pattern_defined = ! DECL_IN_AGGR_P (code_pattern);
+
+ /* We may be in the middle of deferred access check. Disable it now. */
+ push_deferring_access_checks (dk_no_deferred);
+
/* Unless an explicit instantiation directive has already determined
the linkage of D, remember that a definition is available for
this entity. */
input_location = DECL_SOURCE_LOCATION (d);
- if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
+ /* If D is a member of an explicitly instantiated class template,
+ and no definition is available, treat it like an implicit
+ instantiation. */
+ if (!pattern_defined && expl_inst_class_mem_p
+ && DECL_EXPLICIT_INSTANTIATION (d))
{
DECL_NOT_REALLY_EXTERN (d) = 0;
+ DECL_INTERFACE_KNOWN (d) = 0;
SET_DECL_IMPLICIT_INSTANTIATION (d);
}
pop_access_scope (d);
}
- /* We should have set up DECL_INITIAL in instantiate_class_template
- for in-class definitions of static data members. */
- gcc_assert (!(TREE_CODE (d) == VAR_DECL
- && DECL_INITIALIZED_IN_CLASS_P (d)
- && DECL_INITIAL (d) == NULL_TREE));
-
- /* Do not instantiate templates that we know will be defined
- elsewhere. */
- if (DECL_INTERFACE_KNOWN (d)
- && DECL_REALLY_EXTERN (d)
- && ! (TREE_CODE (d) == FUNCTION_DECL
- && DECL_INLINE (d)))
+ /* Check to see whether we know that this template will be
+ instantiated in some other file, as with "extern template"
+ extension. */
+ external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
+ /* In general, we do not instantiate such templates... */
+ if (external_p
+ /* ... but we instantiate inline functions so that we can inline
+ them and ... */
+ && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d))
+ /* ... we instantiate static data members whose values are
+ needed in integral constant expressions. */
+ && ! (TREE_CODE (d) == VAR_DECL
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (d)))
goto out;
/* Defer all other templates, unless we have been explicitly
- forbidden from doing so. We restore the source position here
- because it's used by add_pending_template. */
- else if (! pattern_defined || defer_ok)
- {
+ forbidden from doing so. */
+ if (/* If there is no definition, we cannot instantiate the
+ template. */
+ ! pattern_defined
+ /* If it's OK to postpone instantiation, do so. */
+ || defer_ok
+ /* If this is a static data member that will be defined
+ elsewhere, we don't want to instantiate the entire data
+ member, but we do want to instantiate the initializer so that
+ we can substitute that elsewhere. */
+ || (external_p && TREE_CODE (d) == VAR_DECL))
+ {
+ /* The definition of the static data member is now required so
+ we must substitute the initializer. */
+ if (TREE_CODE (d) == VAR_DECL
+ && !DECL_INITIAL (d)
+ && DECL_INITIAL (code_pattern))
+ {
+ tree ns;
+ tree init;
+
+ ns = decl_namespace_context (d);
+ push_nested_namespace (ns);
+ push_nested_class (DECL_CONTEXT (d));
+ init = tsubst_expr (DECL_INITIAL (code_pattern),
+ args,
+ tf_error | tf_warning, NULL_TREE);
+ DECL_INITIAL (d) = NULL_TREE;
+ finish_static_data_member_decl (d, init,
+ /*asmspec_tree=*/NULL_TREE,
+ LOOKUP_ONLYCONVERTING);
+ pop_nested_class ();
+ pop_nested_namespace (ns);
+ }
+
+ /* We restore the source position here because it's used by
+ add_pending_template. */
input_location = saved_loc;
if (at_eof && !pattern_defined
pedwarn
("explicit instantiation of %qD but no definition available", d);
- add_pending_template (d);
+ /* ??? Historically, we have instantiated inline functions, even
+ when marked as "extern template". */
+ if (!(external_p && TREE_CODE (d) == VAR_DECL))
+ add_pending_template (d);
goto out;
}
/* Tell the repository that D is available in this translation unit
/* Enter the scope of D so that access-checking works correctly. */
push_nested_class (DECL_CONTEXT (d));
- cp_finish_decl (d,
- (!DECL_INITIALIZED_IN_CLASS_P (d)
- ? DECL_INITIAL (d) : NULL_TREE),
- NULL_TREE, 0);
+ cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
pop_nested_class ();
}
else if (TREE_CODE (d) == FUNCTION_DECL)
to avoid infinite loop. */
if (pending_templates && retries >= max_tinst_depth)
{
- cp_error_at ("template instantiation depth exceeds maximum of %d"
- " (use -ftemplate-depth-NN to increase the maximum)"
- " instantiating %q+D, possibly from virtual table"
- " generation",
- max_tinst_depth, TREE_VALUE (pending_templates));
+ error ("template instantiation depth exceeds maximum of %d"
+ " instantiating %q+D, possibly from virtual table generation"
+ " (use -ftemplate-depth-NN to increase the maximum)",
+ max_tinst_depth, TREE_VALUE (pending_templates));
return;
}
fn;
fn = TREE_CHAIN (fn))
if (! DECL_ARTIFICIAL (fn))
- instantiate_decl (fn, /*defer_ok=*/0,
- /*undefined_ok=*/0);
+ instantiate_decl (fn,
+ /*defer_ok=*/0,
+ /*expl_inst_class_mem_p=*/false);
if (COMPLETE_TYPE_P (instantiation))
reconsider = 1;
}
if (!DECL_TEMPLATE_SPECIALIZATION (instantiation)
&& !DECL_TEMPLATE_INSTANTIATED (instantiation))
{
- instantiation = instantiate_decl (instantiation,
- /*defer_ok=*/0,
- /*undefined_ok=*/0);
+ instantiation
+ = instantiate_decl (instantiation,
+ /*defer_ok=*/0,
+ /*expl_inst_class_mem_p=*/false);
if (DECL_TEMPLATE_INSTANTIATED (instantiation))
reconsider = 1;
}
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
return true;
/* -- a qualified-id with a nested-name-specifier which contains a
- class-name that names a dependent type or whose unqualified-id
+ class-name that names a dependent type or whose unqualified-id
names a dependent type. */
if (TREE_CODE (type) == TYPENAME_TYPE)
return true;
/* -- a cv-qualified type where the cv-unqualified type is
- dependent. */
+ dependent. */
type = TYPE_MAIN_VARIANT (type);
/* -- a compound type constructed from any dependent type. */
if (TYPE_PTR_TO_MEMBER_P (type))
return false;
}
/* -- an array type constructed from any dependent type or whose
- size is specified by a constant expression that is
+ size is specified by a constant expression that is
value-dependent. */
if (TREE_CODE (type) == ARRAY_TYPE)
{
considered dependent too. For example:
template <int I> void f() {
- enum E { a = I };
+ enum E { a = I };
S<sizeof (E)> s;
}
case VAR_DECL:
/* A constant with integral or enumeration type and is initialized
- with an expression that is value-dependent. */
+ with an expression that is value-dependent. */
if (DECL_INITIAL (expression)
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (expression))
&& value_dependent_expression_p (DECL_INITIAL (expression)))
case REINTERPRET_CAST_EXPR:
case CAST_EXPR:
/* These expressions are value-dependent if the type to which
- the cast occurs is dependent or the expression being casted
- is value-dependent. */
+ the cast occurs is dependent or the expression being casted
+ is value-dependent. */
{
tree type = TREE_TYPE (expression);
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
/* A `sizeof' expression is value-dependent if the operand is
- type-dependent. */
+ type-dependent. */
expression = TREE_OPERAND (expression, 0);
if (TYPE_P (expression))
return dependent_type_p (expression);
case CALL_EXPR:
/* A CALL_EXPR is value-dependent if any argument is
- value-dependent. Why do we have to handle CALL_EXPRs in this
- function at all? First, some function calls, those for which
- value_dependent_expression_p is true, man appear in constant
- expressions. Second, there appear to be bugs which result in
- other CALL_EXPRs reaching this point. */
+ value-dependent. Why do we have to handle CALL_EXPRs in this
+ function at all? First, some function calls, those for which
+ value_dependent_expression_p is true, man appear in constant
+ expressions. Second, there appear to be bugs which result in
+ other CALL_EXPRs reaching this point. */
{
tree function = TREE_OPERAND (expression, 0);
tree args = TREE_OPERAND (expression, 1);
default:
/* A constant expression is value-dependent if any subexpression is
- value-dependent. */
+ value-dependent. */
switch (TREE_CODE_CLASS (TREE_CODE (expression)))
{
case tcc_reference:
return true;
expression = TREE_OPERAND (expression, 0);
}
- gcc_assert (TREE_CODE (expression) == OVERLOAD);
+ gcc_assert (TREE_CODE (expression) == OVERLOAD
+ || TREE_CODE (expression) == FUNCTION_DECL);
while (expression)
{