blob: 633a040e4abcf1da6289feb93074ffdeed8cc1a4 [file] [log] [blame]
/* Handle parameterized types (templates) for GNU -*- C++ -*-.
Copyright (C) 1992-2022 Free Software Foundation, Inc.
Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing.
Rewritten by Jason Merrill (jason@cygnus.com).
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
/* Known bugs or deficiencies include:
all methods must be provided in header files; can't use a source
file that contains only the method templates and "just win".
Fixed by: C++20 modules. */
#include "config.h"
#define INCLUDE_ALGORITHM // for std::equal
#include "system.h"
#include "coretypes.h"
#include "cp-tree.h"
#include "timevar.h"
#include "stringpool.h"
#include "varasm.h"
#include "attribs.h"
#include "stor-layout.h"
#include "intl.h"
#include "c-family/c-objc.h"
#include "cp-objcp-common.h"
#include "toplev.h"
#include "tree-iterator.h"
#include "type-utils.h"
#include "gimplify.h"
#include "gcc-rich-location.h"
#include "selftest.h"
#include "target.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
typedef int (*tree_fn_t) (tree, void*);
/* The PENDING_TEMPLATES is a list of templates whose instantiations
have been deferred, either because their definitions were not yet
available, or because we were putting off doing the work. */
struct GTY ((chain_next ("%h.next"))) pending_template
{
struct pending_template *next;
struct tinst_level *tinst;
};
static GTY(()) struct pending_template *pending_templates;
static GTY(()) struct pending_template *last_pending_template;
int processing_template_parmlist;
static int template_header_count;
static vec<int> inline_parm_levels;
static GTY(()) struct tinst_level *current_tinst_level;
static GTY(()) vec<tree, va_gc> *saved_access_scope;
/* Live only within one (recursive) call to tsubst_expr. We use
this to pass the statement expression node from the STMT_EXPR
to the EXPR_STMT that is its result. */
static tree cur_stmt_expr;
// -------------------------------------------------------------------------- //
// Local Specialization Stack
//
// Implementation of the RAII helper for creating new local
// specializations.
local_specialization_stack::local_specialization_stack (lss_policy policy)
: saved (local_specializations)
{
if (policy == lss_nop)
;
else if (policy == lss_blank || !saved)
local_specializations = new hash_map<tree, tree>;
else
local_specializations = new hash_map<tree, tree>(*saved);
}
local_specialization_stack::~local_specialization_stack ()
{
if (local_specializations != saved)
{
delete local_specializations;
local_specializations = saved;
}
}
/* True if we've recursed into fn_type_unification too many times. */
static bool excessive_deduction_depth;
struct spec_hasher : ggc_ptr_hash<spec_entry>
{
static hashval_t hash (tree, tree);
static hashval_t hash (spec_entry *);
static bool equal (spec_entry *, spec_entry *);
};
/* The general template is not in these tables. */
typedef hash_table<spec_hasher> spec_hash_table;
static GTY (()) spec_hash_table *decl_specializations;
static GTY (()) spec_hash_table *type_specializations;
/* Contains canonical template parameter types. The vector is indexed by
the TEMPLATE_TYPE_IDX of the template parameter. Each element is a
TREE_LIST, whose TREE_VALUEs contain the canonical template
parameters of various types and levels. */
static GTY(()) vec<tree, va_gc> *canonical_template_parms;
#define UNIFY_ALLOW_NONE 0
#define UNIFY_ALLOW_MORE_CV_QUAL 1
#define UNIFY_ALLOW_LESS_CV_QUAL 2
#define UNIFY_ALLOW_DERIVED 4
#define UNIFY_ALLOW_INTEGER 8
#define UNIFY_ALLOW_OUTER_LEVEL 16
#define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32
#define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64
enum template_base_result {
tbr_incomplete_type,
tbr_ambiguous_baseclass,
tbr_success
};
static bool resolve_overloaded_unification (tree, tree, tree, tree,
unification_kind_t, int,
bool);
static int try_one_overload (tree, tree, tree, tree, tree,
unification_kind_t, int, bool, bool);
static int unify (tree, tree, tree, tree, int, bool);
static void add_pending_template (tree);
static tree reopen_tinst_level (struct tinst_level *);
static tree tsubst_initializer_list (tree, tree);
static tree get_partial_spec_bindings (tree, tree, tree);
static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t,
bool = true);
static void tsubst_enum (tree, tree, tree);
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
static int check_non_deducible_conversion (tree, tree, unification_kind_t, int,
struct conversion **, bool);
static int maybe_adjust_types_for_deduction (tree, unification_kind_t,
tree*, tree*, tree);
static int type_unification_real (tree, tree, tree, const tree *,
unsigned int, int, unification_kind_t,
vec<deferred_access_check, va_gc> **,
bool);
static void note_template_header (int);
static tree convert_nontype_argument_function (tree, tree, tsubst_flags_t);
static tree convert_nontype_argument (tree, tree, tsubst_flags_t);
static tree convert_template_argument (tree, tree, tree,
tsubst_flags_t, int, tree);
static tree for_each_template_parm (tree, tree_fn_t, void*,
hash_set<tree> *, bool, tree_fn_t = NULL);
static tree expand_template_argument_pack (tree);
static tree build_template_parm_index (int, int, int, tree, tree);
static bool inline_needs_template_parms (tree, bool);
static void push_inline_template_parms_recursive (tree, int);
static tree reduce_template_parm_level (tree, tree, int, tree, tsubst_flags_t);
static int mark_template_parm (tree, void *);
static int template_parm_this_level_p (tree, void *);
static tree tsubst_friend_function (tree, tree);
static tree tsubst_friend_class (tree, tree);
static int can_complete_type_without_circularity (tree);
static tree get_bindings (tree, tree, tree, bool);
static int template_decl_level (tree);
static int check_cv_quals_for_unify (int, tree, tree);
static int unify_pack_expansion (tree, tree, tree,
tree, unification_kind_t, bool, bool);
static tree copy_template_args (tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void tsubst_each_template_parm_constraints (tree, tree, tsubst_flags_t);
tree most_specialized_partial_spec (tree, tsubst_flags_t);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
static bool check_specialization_scope (void);
static tree process_partial_specialization (tree);
static enum template_base_result get_template_base (tree, tree, tree, tree,
bool , tree *);
static tree try_class_unification (tree, tree, tree, tree, bool);
static bool class_nttp_const_wrapper_p (tree t);
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
tree, tree);
static bool template_template_parm_bindings_ok_p (tree, tree);
static void tsubst_default_arguments (tree, tsubst_flags_t);
static tree for_each_template_parm_r (tree *, int *, void *);
static tree copy_default_args_to_explicit_spec_1 (tree, tree);
static void copy_default_args_to_explicit_spec (tree);
static bool invalid_nontype_parm_type_p (tree, tsubst_flags_t);
static bool dependent_template_arg_p (tree);
static bool dependent_type_p_r (tree);
static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
static tree tsubst_decl (tree, tree, tsubst_flags_t);
static void perform_instantiation_time_access_checks (tree, tree);
static tree listify (tree);
static tree listify_autos (tree, tree);
static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
static bool complex_alias_template_p (const_tree tmpl);
static tree get_underlying_template (tree);
static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);
static tree canonicalize_expr_argument (tree, tsubst_flags_t);
static tree make_argument_pack (tree);
static tree enclosing_instantiation_of (tree tctx);
static void instantiate_body (tree pattern, tree args, tree d, bool nested);
static tree maybe_dependent_member_ref (tree, tree, tsubst_flags_t, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
template, VAR_DECL for static member variable, or TYPE_DECL for
for a class or alias template (needed by instantiate_decl). */
void
push_access_scope (tree t)
{
gcc_assert (VAR_OR_FUNCTION_DECL_P (t)
|| TREE_CODE (t) == TYPE_DECL);
if (DECL_FRIEND_CONTEXT (t))
push_nested_class (DECL_FRIEND_CONTEXT (t));
else if (DECL_IMPLICIT_TYPEDEF_P (t)
&& CLASS_TYPE_P (TREE_TYPE (t)))
push_nested_class (TREE_TYPE (t));
else if (DECL_CLASS_SCOPE_P (t))
push_nested_class (DECL_CONTEXT (t));
else if (deduction_guide_p (t) && DECL_ARTIFICIAL (t))
/* An artificial deduction guide should have the same access as
the constructor. */
push_nested_class (TREE_TYPE (TREE_TYPE (t)));
else
push_to_top_level ();
if (TREE_CODE (t) == FUNCTION_DECL)
{
vec_safe_push (saved_access_scope, current_function_decl);
current_function_decl = t;
}
}
/* Restore the scope set up by push_access_scope. T is the node we
are processing. */
void
pop_access_scope (tree t)
{
if (TREE_CODE (t) == FUNCTION_DECL)
current_function_decl = saved_access_scope->pop();
if (DECL_FRIEND_CONTEXT (t)
|| (DECL_IMPLICIT_TYPEDEF_P (t)
&& CLASS_TYPE_P (TREE_TYPE (t)))
|| DECL_CLASS_SCOPE_P (t)
|| (deduction_guide_p (t) && DECL_ARTIFICIAL (t)))
pop_nested_class ();
else
pop_from_top_level ();
}
/* Do any processing required when DECL (a member template
declaration) is finished. Returns the TEMPLATE_DECL corresponding
to DECL, unless it is a specialization, in which case the DECL
itself is returned. */
tree
finish_member_template_decl (tree decl)
{
if (decl == error_mark_node)
return error_mark_node;
gcc_assert (DECL_P (decl));
if (TREE_CODE (decl) == TYPE_DECL)
{
tree type;
type = TREE_TYPE (decl);
if (type == error_mark_node)
return error_mark_node;
if (MAYBE_CLASS_TYPE_P (type)
&& CLASSTYPE_TEMPLATE_INFO (type)
&& !CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
{
tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
check_member_template (tmpl);
return tmpl;
}
return NULL_TREE;
}
else if (TREE_CODE (decl) == FIELD_DECL)
error_at (DECL_SOURCE_LOCATION (decl),
"data member %qD cannot be a member template", decl);
else if (DECL_TEMPLATE_INFO (decl))
{
if (!DECL_TEMPLATE_SPECIALIZATION (decl))
{
check_member_template (DECL_TI_TEMPLATE (decl));
return DECL_TI_TEMPLATE (decl);
}
else
return decl;
}
else
error_at (DECL_SOURCE_LOCATION (decl),
"invalid member template declaration %qD", decl);
return error_mark_node;
}
/* Create a template info node. */
tree
build_template_info (tree template_decl, tree template_args)
{
tree result = make_node (TEMPLATE_INFO);
TI_TEMPLATE (result) = template_decl;
TI_ARGS (result) = template_args;
return result;
}
/* Return the template info node corresponding to T, whatever T is. */
tree
get_template_info (const_tree t)
{
tree tinfo = NULL_TREE;
if (!t || t == error_mark_node)
return NULL;
if (TREE_CODE (t) == NAMESPACE_DECL
|| TREE_CODE (t) == PARM_DECL)
return NULL;
if (DECL_P (t) && DECL_LANG_SPECIFIC (t))
tinfo = DECL_TEMPLATE_INFO (t);
if (!tinfo && DECL_IMPLICIT_TYPEDEF_P (t))
t = TREE_TYPE (t);
if (OVERLOAD_TYPE_P (t))
tinfo = TYPE_TEMPLATE_INFO (t);
else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM)
tinfo = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t);
return tinfo;
}
/* Returns the template nesting level of the indicated class TYPE.
For example, in:
template <class T>
struct A
{
template <class U>
struct B {};
};
A<T>::B<U> has depth two, while A<T> has depth one.
Both A<T>::B<int> and A<int>::B<U> have depth one, if
they are instantiations, not specializations.
This function is guaranteed to return 0 if passed NULL_TREE so
that, for example, `template_class_depth (current_class_type)' is
always safe. */
int
template_class_depth (tree type)
{
int depth;
for (depth = 0; type && TREE_CODE (type) != NAMESPACE_DECL; )
{
tree tinfo = get_template_info (type);
if (tinfo
&& TREE_CODE (TI_TEMPLATE (tinfo)) == TEMPLATE_DECL
&& PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo))
&& uses_template_parms (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo))))
++depth;
if (DECL_P (type))
{
if (tree fctx = DECL_FRIEND_CONTEXT (type))
type = fctx;
else
type = CP_DECL_CONTEXT (type);
}
else if (LAMBDA_TYPE_P (type) && LAMBDA_TYPE_EXTRA_SCOPE (type))
type = LAMBDA_TYPE_EXTRA_SCOPE (type);
else
type = CP_TYPE_CONTEXT (type);
}
return depth;
}
/* Return TRUE if NODE instantiates a template that has arguments of
its own, be it directly a primary template or indirectly through a
partial specializations. */
static bool
instantiates_primary_template_p (tree node)
{
tree tinfo = get_template_info (node);
if (!tinfo)
return false;
tree tmpl = TI_TEMPLATE (tinfo);
if (PRIMARY_TEMPLATE_P (tmpl))
return true;
if (!DECL_TEMPLATE_SPECIALIZATION (tmpl))
return false;
/* So now we know we have a specialization, but it could be a full
or a partial specialization. To tell which, compare the depth of
its template arguments with those of its context. */
tree ctxt = DECL_CONTEXT (tmpl);
tree ctinfo = get_template_info (ctxt);
if (!ctinfo)
return true;
return (TMPL_ARGS_DEPTH (TI_ARGS (tinfo))
> TMPL_ARGS_DEPTH (TI_ARGS (ctinfo)));
}
/* Subroutine of maybe_begin_member_template_processing.
Returns true if processing DECL needs us to push template parms. */
static bool
inline_needs_template_parms (tree decl, bool nsdmi)
{
if (!decl || (!nsdmi && ! DECL_TEMPLATE_INFO (decl)))
return false;
return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl)))
> (current_template_depth + DECL_TEMPLATE_SPECIALIZATION (decl)));
}
/* Subroutine of maybe_begin_member_template_processing.
Push the template parms in PARMS, starting from LEVELS steps into the
chain, and ending at the beginning, since template parms are listed
innermost first. */
static void
push_inline_template_parms_recursive (tree parmlist, int levels)
{
tree parms = TREE_VALUE (parmlist);
int i;
if (levels > 1)
push_inline_template_parms_recursive (TREE_CHAIN (parmlist), levels - 1);
++processing_template_decl;
current_template_parms
= tree_cons (size_int (current_template_depth + 1),
parms, current_template_parms);
TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1;
begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec,
NULL);
for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
{
tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
if (error_operand_p (parm))
continue;
gcc_assert (DECL_P (parm));
switch (TREE_CODE (parm))
{
case TYPE_DECL:
case TEMPLATE_DECL:
pushdecl (parm);
break;
case PARM_DECL:
/* Push the CONST_DECL. */
pushdecl (TEMPLATE_PARM_DECL (DECL_INITIAL (parm)));
break;
default:
gcc_unreachable ();
}
}
}
/* Restore the template parameter context for a member template, a
friend template defined in a class definition, or a non-template
member of template class. */
void
maybe_begin_member_template_processing (tree decl)
{
tree parms;
int levels = 0;
bool nsdmi = TREE_CODE (decl) == FIELD_DECL;
if (nsdmi)
{
tree ctx = DECL_CONTEXT (decl);
decl = (CLASSTYPE_TEMPLATE_INFO (ctx)
/* Disregard full specializations (c++/60999). */
&& uses_template_parms (ctx)
? CLASSTYPE_TI_TEMPLATE (ctx) : NULL_TREE);
}
if (inline_needs_template_parms (decl, nsdmi))
{
parms = DECL_TEMPLATE_PARMS (most_general_template (decl));
levels = TMPL_PARMS_DEPTH (parms) - current_template_depth;
if (DECL_TEMPLATE_SPECIALIZATION (decl))
{
--levels;
parms = TREE_CHAIN (parms);
}
push_inline_template_parms_recursive (parms, levels);
}
/* Remember how many levels of template parameters we pushed so that
we can pop them later. */
inline_parm_levels.safe_push (levels);
}
/* Undo the effects of maybe_begin_member_template_processing. */
void
maybe_end_member_template_processing (void)
{
int i;
int last;
if (inline_parm_levels.length () == 0)
return;
last = inline_parm_levels.pop ();
for (i = 0; i < last; ++i)
{
--processing_template_decl;
current_template_parms = TREE_CHAIN (current_template_parms);
poplevel (0, 0, 0);
}
}
/* Return a new template argument vector which contains all of ARGS,
but has as its innermost set of arguments the EXTRA_ARGS. */
tree
add_to_template_args (tree args, tree extra_args)
{
tree new_args;
int extra_depth;
int i;
int j;
if (args == NULL_TREE || extra_args == error_mark_node)
return extra_args;
extra_depth = TMPL_ARGS_DEPTH (extra_args);
new_args = make_tree_vec (TMPL_ARGS_DEPTH (args) + extra_depth);
for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i)
SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i));
for (j = 1; j <= extra_depth; ++j, ++i)
SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j));
return new_args;
}
/* Like add_to_template_args, but only the outermost ARGS are added to
the EXTRA_ARGS. In particular, all but TMPL_ARGS_DEPTH
(EXTRA_ARGS) levels are added. This function is used to combine
the template arguments from a partial instantiation with the
template arguments used to attain the full instantiation from the
partial instantiation.
If ARGS is a TEMPLATE_DECL, use its parameters as args. */
tree
add_outermost_template_args (tree args, tree extra_args)
{
tree new_args;
if (!args)
return extra_args;
if (TREE_CODE (args) == TEMPLATE_DECL)
{
tree ti = get_template_info (DECL_TEMPLATE_RESULT (args));
args = TI_ARGS (ti);
}
/* If there are more levels of EXTRA_ARGS than there are ARGS,
something very fishy is going on. */
gcc_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args));
/* If *all* the new arguments will be the EXTRA_ARGS, just return
them. */
if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args))
return extra_args;
/* For the moment, we make ARGS look like it contains fewer levels. */
TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args);
new_args = add_to_template_args (args, extra_args);
/* Now, we restore ARGS to its full dimensions. */
TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args);
return new_args;
}
/* Return the N levels of innermost template arguments from the ARGS. */
tree
get_innermost_template_args (tree args, int n)
{
tree new_args;
int extra_levels;
int i;
gcc_assert (n >= 0);
/* If N is 1, just return the innermost set of template arguments. */
if (n == 1)
return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args));
/* If we're not removing anything, just return the arguments we were
given. */
extra_levels = TMPL_ARGS_DEPTH (args) - n;
gcc_assert (extra_levels >= 0);
if (extra_levels == 0)
return args;
/* Make a new set of arguments, not containing the outer arguments. */
new_args = make_tree_vec (n);
for (i = 1; i <= n; ++i)
SET_TMPL_ARGS_LEVEL (new_args, i,
TMPL_ARGS_LEVEL (args, i + extra_levels));
return new_args;
}
/* The inverse of get_innermost_template_args: Return all but the innermost
EXTRA_LEVELS levels of template arguments from the ARGS. */
static tree
strip_innermost_template_args (tree args, int extra_levels)
{
tree new_args;
int n = TMPL_ARGS_DEPTH (args) - extra_levels;
int i;
gcc_assert (n >= 0);
/* If N is 1, just return the outermost set of template arguments. */
if (n == 1)
return TMPL_ARGS_LEVEL (args, 1);
/* If we're not removing anything, just return the arguments we were
given. */
gcc_assert (extra_levels >= 0);
if (extra_levels == 0)
return args;
/* Make a new set of arguments, not containing the inner arguments. */
new_args = make_tree_vec (n);
for (i = 1; i <= n; ++i)
SET_TMPL_ARGS_LEVEL (new_args, i,
TMPL_ARGS_LEVEL (args, i));
return new_args;
}
/* We've got a template header coming up; push to a new level for storing
the parms. */
void
begin_template_parm_list (void)
{
/* We use a non-tag-transparent scope here, which causes pushtag to
put tags in this scope, rather than in the enclosing class or
namespace scope. This is the right thing, since we want
TEMPLATE_DECLS, and not TYPE_DECLS for template classes. For a
global template class, push_template_decl handles putting the
TEMPLATE_DECL into top-level scope. For a nested template class,
e.g.:
template <class T> struct S1 {
template <class T> struct S2 {};
};
pushtag contains special code to insert the TEMPLATE_DECL for S2
at the right scope. */
begin_scope (sk_template_parms, NULL);
++processing_template_decl;
++processing_template_parmlist;
note_template_header (0);
/* Add a dummy parameter level while we process the parameter list. */
current_template_parms
= tree_cons (size_int (current_template_depth + 1),
make_tree_vec (0),
current_template_parms);
}
/* This routine is called when a specialization is declared. If it is
invalid to declare a specialization here, an error is reported and
false is returned, otherwise this routine will return true. */
static bool
check_specialization_scope (void)
{
tree scope = current_scope ();
/* [temp.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 (scope && TREE_CODE (scope) != NAMESPACE_DECL)
{
error ("explicit specialization in non-namespace scope %qD", scope);
return false;
}
/* [temp.expl.spec]
In an explicit specialization declaration for a member of a class
template or a member template that appears in namespace scope,
the member template and some of its enclosing class templates may
remain unspecialized, except that the declaration shall not
explicitly specialize a class member template if its enclosing
class templates are not explicitly specialized as well. */
if (current_template_parms)
{
error ("enclosing class templates are not explicitly specialized");
return false;
}
return true;
}
/* We've just seen template <>. */
bool
begin_specialization (void)
{
begin_scope (sk_template_spec, NULL);
note_template_header (1);
return check_specialization_scope ();
}
/* Called at then end of processing a declaration preceded by
template<>. */
void
end_specialization (void)
{
finish_scope ();
reset_specialization ();
}
/* Any template <>'s that we have seen thus far are not referring to a
function specialization. */
void
reset_specialization (void)
{
processing_specialization = 0;
template_header_count = 0;
}
/* We've just seen a template header. If SPECIALIZATION is nonzero,
it was of the form template <>. */
static void
note_template_header (int specialization)
{
processing_specialization = specialization;
template_header_count++;
}
/* We're beginning an explicit instantiation. */
void
begin_explicit_instantiation (void)
{
gcc_assert (!processing_explicit_instantiation);
processing_explicit_instantiation = true;
}
void
end_explicit_instantiation (void)
{
gcc_assert (processing_explicit_instantiation);
processing_explicit_instantiation = false;
}
/* An explicit specialization or partial specialization of 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 a namespace enclosing the
specialized template. An explicit specialization whose declarator-id is
not qualified shall be declared in the nearest enclosing namespace of the
template, or, if the namespace is inline (7.3.1), any namespace from its
enclosing namespace set. */
if (current_scope() != DECL_CONTEXT (tmpl)
&& !at_namespace_scope_p ())
{
error ("specialization of %qD must appear at namespace scope", tmpl);
return false;
}
if (is_nested_namespace (current_namespace, tpl_ns, cxx_dialect < cxx11))
/* Same or enclosing namespace. */
return true;
else
{
auto_diagnostic_group d;
if (permerror (input_location,
"specialization of %qD in different namespace", tmpl))
inform (DECL_SOURCE_LOCATION (tmpl),
" 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_nested_namespace (current_namespace, ns))
permerror (input_location, "explicit instantiation of %qD in namespace %qD "
"(which does not enclose namespace %qD)",
spec, current_namespace, ns);
}
/* Returns true if TYPE is a new partial specialization that needs to be
set up. This may also modify TYPE to point to the correct (new or
existing) constrained partial specialization. */
static bool
maybe_new_partial_specialization (tree& type)
{
/* An implicit instantiation of an incomplete type implies
the definition of a new class template.
template<typename T>
struct S;
template<typename T>
struct S<T*>;
Here, S<T*> is an implicit instantiation of S whose type
is incomplete. */
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type))
return true;
/* It can also be the case that TYPE is a completed specialization.
Continuing the previous example, suppose we also declare:
template<typename T>
requires Integral<T>
struct S<T*>;
Here, S<T*> refers to the specialization S<T*> defined
above. However, we need to differentiate definitions because
we intend to define a new partial specialization. In this case,
we rely on the fact that the constraints are different for
this declaration than that above.
Note that we also get here for injected class names and
late-parsed template definitions. We must ensure that we
do not create new type declarations for those cases. */
if (flag_concepts && CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
{
tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
tree args = CLASSTYPE_TI_ARGS (type);
/* If there are no template parameters, this cannot be a new
partial template specialization? */
if (!current_template_parms)
return false;
/* The injected-class-name is not a new partial specialization. */
if (DECL_SELF_REFERENCE_P (TYPE_NAME (type)))
return false;
/* If the constraints are not the same as those of the primary
then, we can probably create a new specialization. */
tree type_constr = current_template_constraints ();
if (type == TREE_TYPE (tmpl))
{
tree main_constr = get_constraints (tmpl);
if (equivalent_constraints (type_constr, main_constr))
return false;
}
/* Also, if there's a pre-existing specialization with matching
constraints, then this also isn't new. */
tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
while (specs)
{
tree spec_tmpl = TREE_VALUE (specs);
tree spec_args = TREE_PURPOSE (specs);
tree spec_constr = get_constraints (spec_tmpl);
if (comp_template_args (args, spec_args)
&& equivalent_constraints (type_constr, spec_constr))
{
type = TREE_TYPE (spec_tmpl);
return false;
}
specs = TREE_CHAIN (specs);
}
/* Create a new type node (and corresponding type decl)
for the newly declared specialization. */
tree t = make_class_type (TREE_CODE (type));
CLASSTYPE_DECLARED_CLASS (t) = CLASSTYPE_DECLARED_CLASS (type);
SET_TYPE_TEMPLATE_INFO (t, build_template_info (tmpl, args));
/* We only need a separate type node for storing the definition of this
partial specialization; uses of S<T*> are unconstrained, so all are
equivalent. So keep TYPE_CANONICAL the same. */
TYPE_CANONICAL (t) = TYPE_CANONICAL (type);
/* Build the corresponding type decl. */
tree d = create_implicit_typedef (DECL_NAME (tmpl), t);
DECL_CONTEXT (d) = TYPE_CONTEXT (t);
DECL_SOURCE_LOCATION (d) = input_location;
TREE_PRIVATE (d) = (current_access_specifier == access_private_node);
TREE_PROTECTED (d) = (current_access_specifier == access_protected_node);
set_instantiating_module (d);
DECL_MODULE_EXPORT_P (d) = DECL_MODULE_EXPORT_P (tmpl);
type = t;
return true;
}
return false;
}
/* The TYPE is being declared. If it is a template type, that means it
is a partial specialization. Do appropriate error-checking. */
tree
maybe_process_partial_specialization (tree type)
{
tree context;
if (type == error_mark_node)
return error_mark_node;
/* A lambda that appears in specialization context is not itself a
specialization. */
if (CLASS_TYPE_P (type) && CLASSTYPE_LAMBDA_EXPR (type))
return type;
/* An injected-class-name is not a specialization. */
if (DECL_SELF_REFERENCE_P (TYPE_NAME (type)))
return type;
if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
error ("name of class shadows template template parameter %qD",
TYPE_NAME (type));
return error_mark_node;
}
context = TYPE_CONTEXT (type);
if (TYPE_ALIAS_P (type))
{
tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (type);
if (tinfo && DECL_ALIAS_TEMPLATE_P (TI_TEMPLATE (tinfo)))
error ("specialization of alias template %qD",
TI_TEMPLATE (tinfo));
else
error ("explicit specialization of non-template %qT", type);
return error_mark_node;
}
else 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 (maybe_new_partial_specialization (type))
{
if (!check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type))
&& !at_namespace_scope_p ())
return error_mark_node;
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)) = input_location;
if (processing_template_decl)
{
tree decl = push_template_decl (TYPE_MAIN_DECL (type));
if (decl == error_mark_node)
return error_mark_node;
return TREE_TYPE (decl);
}
}
else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type))
error ("specialization of %qT after instantiation", type);
else if (errorcount && !processing_specialization
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (type)
&& !uses_template_parms (CLASSTYPE_TI_ARGS (type)))
/* Trying to define a specialization either without a template<> header
or in an inappropriate place. We've already given an error, so just
bail now so we don't actually define the specialization. */
return error_mark_node;
}
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;
tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
if (current_namespace
!= decl_namespace_context (tmpl))
{
if (permerror (input_location,
"specialization of %qD in different namespace",
type))
inform (DECL_SOURCE_LOCATION (tmpl),
"from definition of %q#D", tmpl);
}
/* 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 (tmpl);
t; t = TREE_CHAIN (t))
{
tree inst = TREE_VALUE (t);
if (CLASSTYPE_TEMPLATE_SPECIALIZATION (inst)
|| !COMPLETE_OR_OPEN_TYPE_P (inst))
{
/* We already have a full specialization of this partial
instantiation, or a full specialization has been
looked up but not instantiated. Reassign it to the
new member specialization template. */
spec_entry elt;
spec_entry *entry;
elt.tmpl = most_general_template (tmpl);
elt.args = CLASSTYPE_TI_ARGS (inst);
elt.spec = inst;
type_specializations->remove_elt (&elt);
elt.tmpl = tmpl;
CLASSTYPE_TI_ARGS (inst)
= elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
spec_entry **slot
= type_specializations->find_slot (&elt, INSERT);
entry = ggc_alloc<spec_entry> ();
*entry = elt;
*slot = entry;
}
else
/* But if we've had an implicit instantiation, that's a
problem ([temp.expl.spec]/6). */
error ("specialization %qT after instantiation %qT",
type, inst);
}
/* 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);
DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)) = input_location;
CLASSTYPE_TI_ARGS (type)
= INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
}
}
else if (processing_specialization)
{
/* Someday C++0x may allow for enum template specialization. */
if (cxx_dialect > cxx98 && TREE_CODE (type) == ENUMERAL_TYPE
&& CLASS_TYPE_P (context) && CLASSTYPE_USE_TEMPLATE (context))
pedwarn (input_location, OPT_Wpedantic, "template specialization "
"of %qD not allowed by ISO C++", type);
else
{
error ("explicit specialization of non-template %qT", type);
return error_mark_node;
}
}
return type;
}
/* Make sure ARGS doesn't use any inappropriate typedefs; we should have
gone through coerce_template_parms by now. */
static void
verify_unstripped_args_1 (tree inner)
{
for (int i = 0; i < TREE_VEC_LENGTH (inner); ++i)
{
tree arg = TREE_VEC_ELT (inner, i);
if (TREE_CODE (arg) == TEMPLATE_DECL)
/* OK */;
else if (TYPE_P (arg))
gcc_assert (strip_typedefs (arg, NULL) == arg);
else if (ARGUMENT_PACK_P (arg))
verify_unstripped_args_1 (ARGUMENT_PACK_ARGS (arg));
else if (strip_typedefs (TREE_TYPE (arg), NULL) != TREE_TYPE (arg))
/* Allow typedefs on the type of a non-type argument, since a
parameter can have them. */;
else
gcc_assert (strip_typedefs_expr (arg, NULL) == arg);
}
}
static void
verify_unstripped_args (tree args)
{
++processing_template_decl;
if (!any_dependent_template_arguments_p (args))
verify_unstripped_args_1 (INNERMOST_TEMPLATE_ARGS (args));
--processing_template_decl;
}
/* Retrieve the specialization (in the sense of [temp.spec] - a
specialization is either an instantiation or an explicit
specialization) of TMPL for the given template ARGS. If there is
no such specialization, return NULL_TREE. The ARGS are a vector of
arguments, or a vector of vectors of arguments, in the case of
templates with more than one level of parameters.
If TMPL is a type template and CLASS_SPECIALIZATIONS_P is true,
then we search for a partial specialization matching ARGS. This
parameter is ignored if TMPL is not a class template.
We can also look up a FIELD_DECL, if it is a lambda capture pack; the
result is a NONTYPE_ARGUMENT_PACK. */
static tree
retrieve_specialization (tree tmpl, tree args, hashval_t hash)
{
if (tmpl == NULL_TREE)
return NULL_TREE;
if (args == error_mark_node)
return NULL_TREE;
gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL
|| TREE_CODE (tmpl) == FIELD_DECL);
/* There should be as many levels of arguments as there are
levels of parameters. */
gcc_assert (TMPL_ARGS_DEPTH (args)
== (TREE_CODE (tmpl) == TEMPLATE_DECL
? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))
: template_class_depth (DECL_CONTEXT (tmpl))));
if (flag_checking)
verify_unstripped_args (args);
/* Lambda functions in templates aren't instantiated normally, but through
tsubst_lambda_expr. */
if (lambda_fn_in_template_p (tmpl))
return NULL_TREE;
spec_entry elt;
elt.tmpl = tmpl;
elt.args = args;
elt.spec = NULL_TREE;
spec_hash_table *specializations;
if (DECL_CLASS_TEMPLATE_P (tmpl))
specializations = type_specializations;
else
specializations = decl_specializations;
if (hash == 0)
hash = spec_hasher::hash (&elt);
if (spec_entry *found = specializations->find_with_hash (&elt, hash))
return found->spec;
return NULL_TREE;
}
/* Like retrieve_specialization, but for local declarations. */
tree
retrieve_local_specialization (tree tmpl)
{
if (local_specializations == NULL)
return NULL_TREE;
tree *slot = local_specializations->get (tmpl);
return slot ? *slot : NULL_TREE;
}
/* Returns nonzero iff DECL is a specialization of TMPL. */
int
is_specialization_of (tree decl, tree tmpl)
{
tree t;
if (TREE_CODE (decl) == FUNCTION_DECL)
{
for (t = decl;
t != NULL_TREE;
t = DECL_TEMPLATE_INFO (t) ? DECL_TI_TEMPLATE (t) : NULL_TREE)
if (t == tmpl)
return 1;
}
else
{
gcc_assert (TREE_CODE (decl) == TYPE_DECL);
for (t = TREE_TYPE (decl);
t != NULL_TREE;
t = CLASSTYPE_USE_TEMPLATE (t)
? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE)
if (same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (tmpl)))
return 1;
}
return 0;
}
/* Returns nonzero iff DECL is a specialization of friend declaration
FRIEND_DECL according to [temp.friend]. */
bool
is_specialization_of_friend (tree decl, tree friend_decl)
{
bool need_template = true;
int template_depth;
gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == TYPE_DECL);
/* For [temp.friend/6] when FRIEND_DECL is an ordinary member function
of a template class, we want to check if DECL is a specialization
if this. */
if (TREE_CODE (friend_decl) == FUNCTION_DECL
&& DECL_TEMPLATE_INFO (friend_decl)
&& !DECL_USE_TEMPLATE (friend_decl))
{
/* We want a TEMPLATE_DECL for `is_specialization_of'. */
friend_decl = DECL_TI_TEMPLATE (friend_decl);
need_template = false;
}
else if (TREE_CODE (friend_decl) == TEMPLATE_DECL
&& !PRIMARY_TEMPLATE_P (friend_decl))
need_template = false;
/* There is nothing to do if this is not a template friend. */
if (TREE_CODE (friend_decl) != TEMPLATE_DECL)
return false;
if (is_specialization_of (decl, friend_decl))
return true;
/* [temp.friend/6]
A member of a class template may be declared to be a friend of a
non-template class. In this case, the corresponding member of
every specialization of the class template is a friend of the
class granting friendship.
For example, given a template friend declaration
template <class T> friend void A<T>::f();
the member function below is considered a friend
template <> struct A<int> {
void f();
};
For this type of template friend, TEMPLATE_DEPTH below will be
nonzero. To determine if DECL is a friend of FRIEND, we first
check if the enclosing class is a specialization of another. */
template_depth = template_class_depth (CP_DECL_CONTEXT (friend_decl));
if (template_depth
&& DECL_CLASS_SCOPE_P (decl)
&& is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)),
CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend_decl))))
{
/* Next, we check the members themselves. In order to handle
a few tricky cases, such as when FRIEND_DECL's are
template <class T> friend void A<T>::g(T t);
template <class T> template <T t> friend void A<T>::h();
and DECL's are
void A<int>::g(int);
template <int> void A<int>::h();
we need to figure out ARGS, the template arguments from
the context of DECL. This is required for template substitution
of `T' in the function parameter of `g' and template parameter
of `h' in the above examples. Here ARGS corresponds to `int'. */
tree context = DECL_CONTEXT (decl);
tree args = NULL_TREE;
int current_depth = 0;
while (current_depth < template_depth)
{
if (CLASSTYPE_TEMPLATE_INFO (context))
{
if (current_depth == 0)
args = TYPE_TI_ARGS (context);
else
args = add_to_template_args (TYPE_TI_ARGS (context), args);
current_depth++;
}
context = TYPE_CONTEXT (context);
}
if (TREE_CODE (decl) == FUNCTION_DECL)
{
bool is_template;
tree friend_type;
tree decl_type;
tree friend_args_type;
tree decl_args_type;
/* Make sure that both DECL and FRIEND_DECL are templates or
non-templates. */
is_template = DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl));
if (need_template ^ is_template)
return false;
else if (is_template)
{
/* If both are templates, check template parameter list. */
tree friend_parms
= tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
args, tf_none);
if (!comp_template_parms
(DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)),
friend_parms))
return false;
decl_type = TREE_TYPE (DECL_TI_TEMPLATE (decl));
}
else
decl_type = TREE_TYPE (decl);
friend_type = tsubst_function_type (TREE_TYPE (friend_decl), args,
tf_none, NULL_TREE);
if (friend_type == error_mark_node)
return false;
/* Check if return types match. */
if (!same_type_p (TREE_TYPE (decl_type), TREE_TYPE (friend_type)))
return false;
/* Check if function parameter types match, ignoring the
`this' parameter. */
friend_args_type = TYPE_ARG_TYPES (friend_type);
decl_args_type = TYPE_ARG_TYPES (decl_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend_decl))
friend_args_type = TREE_CHAIN (friend_args_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_args_type = TREE_CHAIN (decl_args_type);
return compparms (decl_args_type, friend_args_type);
}
else
{
/* DECL is a TYPE_DECL */
bool is_template;
tree decl_type = TREE_TYPE (decl);
/* Make sure that both DECL and FRIEND_DECL are templates or
non-templates. */
is_template
= CLASSTYPE_TEMPLATE_INFO (decl_type)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (decl_type));
if (need_template ^ is_template)
return false;
else if (is_template)
{
tree friend_parms;
/* If both are templates, check the name of the two
TEMPLATE_DECL's first because is_friend didn't. */
if (DECL_NAME (CLASSTYPE_TI_TEMPLATE (decl_type))
!= DECL_NAME (friend_decl))
return false;
/* Now check template parameter list. */
friend_parms
= tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl),
args, tf_none);
return comp_template_parms
(DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (decl_type)),
friend_parms);
}
else
return (DECL_NAME (decl)
== DECL_NAME (friend_decl));
}
}
return false;
}
/* Register the specialization SPEC as a specialization of TMPL with
the indicated ARGS. IS_FRIEND indicates whether the specialization
is actually just a friend declaration. ATTRLIST is the list of
attributes that the specialization is declared with or NULL when
it isn't. Returns SPEC, or an equivalent prior declaration, if
available.
We also store instantiations of field packs in the hash table, even
though they are not themselves templates, to make lookup easier. */
static tree
register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
hashval_t hash)
{
tree fn;
gcc_assert ((TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec))
|| (TREE_CODE (tmpl) == FIELD_DECL
&& TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK));
if (TREE_CODE (spec) == FUNCTION_DECL
&& uses_template_parms (DECL_TI_ARGS (spec)))
/* This is the FUNCTION_DECL for a partial instantiation. Don't
register it; we want the corresponding TEMPLATE_DECL instead.
We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than
the more obvious `uses_template_parms (spec)' to avoid problems
with default function arguments. In particular, given
something like this:
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;
spec_entry elt;
elt.tmpl = tmpl;
elt.args = args;
elt.spec = spec;
if (hash == 0)
hash = spec_hasher::hash (&elt);
spec_entry **slot = decl_specializations->find_slot_with_hash (&elt, hash, INSERT);
if (*slot)
fn = (*slot)->spec;
else
fn = NULL_TREE;
/* We can sometimes try to re-register a specialization that we've
already got. In particular, regenerate_decl_from_template calls
duplicate_decls which will update the specialization list. But,
we'll still get called again here anyhow. It's more convenient
to simply allow this than to try to prevent it. */
if (fn == spec)
return spec;
else if (fn && DECL_TEMPLATE_SPECIALIZATION (spec))
{
if (DECL_TEMPLATE_INSTANTIATION (fn))
{
if (DECL_ODR_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
error ("specialization of %qD after instantiation",
fn);
return error_mark_node;
}
else
{
tree clone;
/* This situation should occur only if the first
specialization is an implicit instantiation, the
second is an explicit specialization, and the
implicit instantiation has not yet been used. That
situation can occur if we have implicitly
instantiated a member function and then specialized
it later.
We can also wind up here if a friend declaration that
looked like an instantiation turns out to be a
specialization:
template <class T> void foo(T);
class S { friend void foo<>(int) };
template <> void foo(int);
We transform the existing DECL in place so that any
pointers to it become pointers to the updated
declaration.
If there was a definition for the template, but not
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, /*hiding=*/is_friend);
/* The call to duplicate_decls will have applied
[temp.expl.spec]:
An explicit specialization of a function template
is inline only if it is explicitly declared to be,
and independently of whether its function template
is.
to the primary function; now copy the inline bits to
the various clones. */
FOR_EACH_CLONE (clone, fn)
{
DECL_DECLARED_INLINE_P (clone)
= DECL_DECLARED_INLINE_P (fn);
DECL_SOURCE_LOCATION (clone)
= DECL_SOURCE_LOCATION (fn);
DECL_DELETED_FN (clone)
= DECL_DELETED_FN (fn);
}
check_specialization_namespace (tmpl);
return fn;
}
}
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
{
tree dd = duplicate_decls (spec, fn, /*hiding=*/is_friend);
if (dd == error_mark_node)
/* We've already complained in duplicate_decls. */
return error_mark_node;
if (dd == NULL_TREE && DECL_INITIAL (spec))
/* Dup decl failed, but this is a new definition. Set the
line number so any errors match this new
definition. */
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec);
return fn;
}
}
else if (fn)
return duplicate_decls (spec, fn, /*hiding=*/is_friend);
/* A specialization must be declared in the same namespace as the
template it is specializing. */
if (DECL_P (spec) && DECL_TEMPLATE_SPECIALIZATION (spec)
&& !check_specialization_namespace (tmpl))
DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
spec_entry *entry = ggc_alloc<spec_entry> ();
gcc_assert (tmpl && args && spec);
*entry = elt;
*slot = entry;
if ((TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
&& PRIMARY_TEMPLATE_P (tmpl)
&& DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
|| variable_template_p (tmpl))
/* If TMPL is a forward declaration of a template function, keep a list
of all specializations in case we need to reassign them to a friend
template later in tsubst_friend_function.
Also keep a list of all variable template instantiations so that
process_partial_specialization can check whether a later partial
specialization would have used it. */
DECL_TEMPLATE_INSTANTIATIONS (tmpl)
= tree_cons (args, spec, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
return spec;
}
/* Restricts tree and type comparisons. */
int comparing_specializations;
int comparing_dependent_aliases;
/* Returns true iff two spec_entry nodes are equivalent. */
bool
spec_hasher::equal (spec_entry *e1, spec_entry *e2)
{
int equal;
++comparing_specializations;
++comparing_dependent_aliases;
++processing_template_decl;
equal = (e1->tmpl == e2->tmpl
&& comp_template_args (e1->args, e2->args));
if (equal && flag_concepts
/* tmpl could be a FIELD_DECL for a capture pack. */
&& TREE_CODE (e1->tmpl) == TEMPLATE_DECL
&& VAR_P (DECL_TEMPLATE_RESULT (e1->tmpl))
&& uses_template_parms (e1->args))
{
/* Partial specializations of a variable template can be distinguished by
constraints. */
tree c1 = e1->spec ? get_constraints (e1->spec) : NULL_TREE;
tree c2 = e2->spec ? get_constraints (e2->spec) : NULL_TREE;
equal = equivalent_constraints (c1, c2);
}
--processing_template_decl;
--comparing_dependent_aliases;
--comparing_specializations;
return equal;
}
/* Returns a hash for a template TMPL and template arguments ARGS. */
static hashval_t
hash_tmpl_and_args (tree tmpl, tree args)
{
hashval_t val = iterative_hash_object (DECL_UID (tmpl), 0);
return iterative_hash_template_arg (args, val);
}
hashval_t
spec_hasher::hash (tree tmpl, tree args)
{
++comparing_specializations;
hashval_t val = hash_tmpl_and_args (tmpl, args);
--comparing_specializations;
return val;
}
/* Returns a hash for a spec_entry node based on the TMPL and ARGS members,
ignoring SPEC. */
hashval_t
spec_hasher::hash (spec_entry *e)
{
return spec_hasher::hash (e->tmpl, e->args);
}
/* Recursively calculate a hash value for a template argument ARG, for use
in the hash tables of template specializations. We must be
careful to (at least) skip the same entities template_args_equal
does. */
hashval_t
iterative_hash_template_arg (tree arg, hashval_t val)
{
if (arg == NULL_TREE)
return iterative_hash_object (arg, val);
if (!TYPE_P (arg))
/* Strip nop-like things, but not the same as STRIP_NOPS. */
while (CONVERT_EXPR_P (arg)
|| TREE_CODE (arg) == NON_LVALUE_EXPR
|| class_nttp_const_wrapper_p (arg))
arg = TREE_OPERAND (arg, 0);
enum tree_code code = TREE_CODE (arg);
val = iterative_hash_object (code, val);
switch (code)
{
case ARGUMENT_PACK_SELECT:
/* Getting here with an ARGUMENT_PACK_SELECT means we're probably
preserving it in a hash table, which is bad because it will change
meaning when gen_elem_of_pack_expansion_instantiation changes the
ARGUMENT_PACK_SELECT_INDEX. */
gcc_unreachable ();
case ERROR_MARK:
return val;
case IDENTIFIER_NODE:
return iterative_hash_object (IDENTIFIER_HASH_VALUE (arg), val);
case TREE_VEC:
for (tree elt : tree_vec_range (arg))
val = iterative_hash_template_arg (elt, val);
return val;
case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION:
val = iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
return iterative_hash_template_arg (PACK_EXPANSION_EXTRA_ARGS (arg), val);
case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK:
return iterative_hash_template_arg (ARGUMENT_PACK_ARGS (arg), val);
case TREE_LIST:
for (; arg; arg = TREE_CHAIN (arg))
val = iterative_hash_template_arg (TREE_VALUE (arg), val);
return val;
case OVERLOAD:
for (lkp_iterator iter (arg); iter; ++iter)
val = iterative_hash_template_arg (*iter, val);
return val;
case CONSTRUCTOR:
{
iterative_hash_template_arg (TREE_TYPE (arg), val);
for (auto &e: CONSTRUCTOR_ELTS (arg))
{
val = iterative_hash_template_arg (e.index, val);
val = iterative_hash_template_arg (e.value, val);
}
return val;
}
case PARM_DECL:
if (!DECL_ARTIFICIAL (arg))
{
val = iterative_hash_object (DECL_PARM_INDEX (arg), val);
val = iterative_hash_object (DECL_PARM_LEVEL (arg), val);
}
return iterative_hash_template_arg (TREE_TYPE (arg), val);
case TARGET_EXPR:
return iterative_hash_template_arg (TARGET_EXPR_INITIAL (arg), val);
case PTRMEM_CST:
val = iterative_hash_template_arg (PTRMEM_CST_CLASS (arg), val);
return iterative_hash_template_arg (PTRMEM_CST_MEMBER (arg), val);
case TEMPLATE_PARM_INDEX:
val = iterative_hash_template_arg
(TREE_TYPE (TEMPLATE_PARM_DECL (arg)), val);
val = iterative_hash_object (TEMPLATE_PARM_LEVEL (arg), val);
return iterative_hash_object (TEMPLATE_PARM_IDX (arg), val);
case TRAIT_EXPR:
val = iterative_hash_object (TRAIT_EXPR_KIND (arg), val);
val = iterative_hash_template_arg (TRAIT_EXPR_TYPE1 (arg), val);
return iterative_hash_template_arg (TRAIT_EXPR_TYPE2 (arg), val);
case BASELINK:
val = iterative_hash_template_arg (BINFO_TYPE (BASELINK_BINFO (arg)),
val);
return iterative_hash_template_arg (DECL_NAME (get_first_fn (arg)),
val);
case MODOP_EXPR:
val = iterative_hash_template_arg (TREE_OPERAND (arg, 0), val);
code = TREE_CODE (TREE_OPERAND (arg, 1));
val = iterative_hash_object (code, val);
return iterative_hash_template_arg (TREE_OPERAND (arg, 2), val);
case LAMBDA_EXPR:
/* [temp.over.link] Two lambda-expressions are never considered
equivalent.
So just hash the closure type. */
return iterative_hash_template_arg (TREE_TYPE (arg), val);
case CAST_EXPR:
case IMPLICIT_CONV_EXPR:
case STATIC_CAST_EXPR:
case REINTERPRET_CAST_EXPR:
case CONST_CAST_EXPR:
case DYNAMIC_CAST_EXPR:
case NEW_EXPR:
val = iterative_hash_template_arg (TREE_TYPE (arg), val);
/* Now hash operands as usual. */
break;
case CALL_EXPR:
{
tree fn = CALL_EXPR_FN (arg);
if (tree name = dependent_name (fn))
{
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
val = iterative_hash_template_arg (TREE_OPERAND (fn, 1), val);
fn = name;
}
val = iterative_hash_template_arg (fn, val);
call_expr_arg_iterator ai;
for (tree x = first_call_expr_arg (arg, &ai); x;
x = next_call_expr_arg (&ai))
val = iterative_hash_template_arg (x, val);
return val;
}
default:
break;
}
char tclass = TREE_CODE_CLASS (code);
switch (tclass)
{
case tcc_type:
if (tree ats = alias_template_specialization_p (arg, nt_transparent))
{
// We want an alias specialization that survived strip_typedefs
// to hash differently from its TYPE_CANONICAL, to avoid hash
// collisions that compare as different in template_args_equal.
// These could be dependent specializations that strip_typedefs
// left alone, or untouched specializations because
// coerce_template_parms returns the unconverted template
// arguments if it sees incomplete argument packs.
tree ti = TYPE_ALIAS_TEMPLATE_INFO (ats);
return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
}
switch (TREE_CODE (arg))
{
case TEMPLATE_TEMPLATE_PARM:
{
tree tpi = TEMPLATE_TYPE_PARM_INDEX (arg);
/* Do not recurse with TPI directly, as that is unbounded
recursion. */
val = iterative_hash_object (TEMPLATE_PARM_LEVEL (tpi), val);
val = iterative_hash_object (TEMPLATE_PARM_IDX (tpi), val);
}
break;
case DECLTYPE_TYPE:
val = iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val);
break;
case TYPENAME_TYPE:
if (comparing_specializations)
{
/* Hash the components that are relevant to TYPENAME_TYPE
equivalence as determined by structural_comptypes. We
can only coherently do this when comparing_specializations
is set, because otherwise structural_comptypes tries
resolving TYPENAME_TYPE via the current instantiation. */
tree context = TYPE_MAIN_VARIANT (TYPE_CONTEXT (arg));
tree fullname = TYPENAME_TYPE_FULLNAME (arg);
val = iterative_hash_template_arg (context, val);
val = iterative_hash_template_arg (fullname, val);
}
break;
default:
if (tree canonical = TYPE_CANONICAL (arg))
val = iterative_hash_object (TYPE_HASH (canonical), val);
break;
}
return val;
case tcc_declaration:
case tcc_constant:
return iterative_hash_expr (arg, val);
default:
gcc_assert (IS_EXPR_CODE_CLASS (tclass));
for (int i = 0, n = cp_tree_operand_length (arg); i < n; ++i)
val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val);
return val;
}
}
/* Unregister the specialization SPEC as a specialization of TMPL.
Replace it with NEW_SPEC, if NEW_SPEC is non-NULL. Returns true
if the SPEC was listed as a specialization of TMPL.
Note that SPEC has been ggc_freed, so we can't look inside it. */
bool
reregister_specialization (tree spec, tree tinfo, tree new_spec)
{
spec_entry *entry;
spec_entry elt;
elt.tmpl = most_general_template (TI_TEMPLATE (tinfo));
elt.args = TI_ARGS (tinfo);
elt.spec = NULL_TREE;
entry = decl_specializations->find (&elt);
if (entry != NULL)
{
gcc_assert (entry->spec == spec || entry->spec == new_spec);
gcc_assert (new_spec != NULL_TREE);
entry->spec = new_spec;
return 1;
}
return 0;
}
/* Like register_specialization, but for local declarations. We are
registering SPEC, an instantiation of TMPL. */
void
register_local_specialization (tree spec, tree tmpl)
{
gcc_assert (tmpl != spec);
local_specializations->put (tmpl, spec);
}
/* Registers T as a specialization of itself. This is used to preserve
the references to already-parsed parameters when instantiating
postconditions. */
void
register_local_identity (tree t)
{
local_specializations->put (t, t);
}
/* TYPE is a class type. Returns true if TYPE is an explicitly
specialized class. */
bool
explicit_class_specialization_p (tree type)
{
if (!CLASSTYPE_TEMPLATE_SPECIALIZATION (type))
return false;
return !uses_template_parms (CLASSTYPE_TI_ARGS (type));
}
/* Print the list of functions at FNS, going through all the overloads
for each element of the list. Alternatively, FNS cannot be a
TREE_LIST, in which case it will be printed together with all the
overloads.
MORE and *STR should respectively be FALSE and NULL when the function
is called from the outside. They are used internally on recursive
calls. print_candidates manages the two parameters and leaves NULL
in *STR when it ends. */
static void
print_candidates_1 (tree fns, char **str, bool more = false)
{
if (TREE_CODE (fns) == TREE_LIST)
for (; fns; fns = TREE_CHAIN (fns))
print_candidates_1 (TREE_VALUE (fns), str, more || TREE_CHAIN (fns));
else
for (lkp_iterator iter (fns); iter;)
{
tree cand = *iter;
++iter;
const char *pfx = *str;
if (!pfx)
{
if (more || iter)
pfx = _("candidates are:");
else
pfx = _("candidate is:");
*str = get_spaces (pfx);
}
inform (DECL_SOURCE_LOCATION (cand), "%s %#qD", pfx, cand);
}
}
/* Print the list of candidate FNS in an error message. FNS can also
be a TREE_LIST of non-functions in the case of an ambiguous lookup. */
void
print_candidates (tree fns)
{
char *str = NULL;
print_candidates_1 (fns, &str);
free (str);
}
/* Get a (possibly) constrained template declaration for the
purpose of ordering candidates. */
static tree
get_template_for_ordering (tree list)
{
gcc_assert (TREE_CODE (list) == TREE_LIST);
tree f = TREE_VALUE (list);
if (tree ti = DECL_TEMPLATE_INFO (f))
return TI_TEMPLATE (ti);
return f;
}
/* Among candidates having the same signature, return the
most constrained or NULL_TREE if there is no best candidate.
If the signatures of candidates vary (e.g., template
specialization vs. member function), then there can be no
most constrained.
Note that we don't compare constraints on the functions
themselves, but rather those of their templates. */
static tree
most_constrained_function (tree candidates)
{
// Try to find the best candidate in a first pass.
tree champ = candidates;
for (tree c = TREE_CHAIN (champ); c; c = TREE_CHAIN (c))
{
int winner = more_constrained (get_template_for_ordering (champ),
get_template_for_ordering (c));
if (winner == -1)
champ = c; // The candidate is more constrained
else if (winner == 0)
return NULL_TREE; // Neither is more constrained
}
// Verify that the champ is better than previous candidates.
for (tree c = candidates; c != champ; c = TREE_CHAIN (c)) {
if (!more_constrained (get_template_for_ordering (champ),
get_template_for_ordering (c)))
return NULL_TREE;
}
return champ;
}
/* Returns the template (one of the functions given by TEMPLATE_ID)
which can be specialized to match the indicated DECL with the
explicit template args given in TEMPLATE_ID. The DECL may be
NULL_TREE if none is available. In that case, the functions in
TEMPLATE_ID are non-members.
If NEED_MEMBER_TEMPLATE is nonzero the function is known to be a
specialization of a member template.
The TEMPLATE_COUNT is the number of references to qualifying
template classes that appeared in the name of the function. See
check_explicit_specialization for a more accurate description.
TSK indicates what kind of template declaration (if any) is being
declared. TSK_TEMPLATE indicates that the declaration given by
DECL, though a FUNCTION_DECL, has template parameters, and is
therefore a template function.
The template args (those explicitly specified and those deduced)
are output in a newly created vector *TARGS_OUT.
If it is impossible to determine the result, an error message is
issued. The error_mark_node is returned to indicate failure. */
static tree
determine_specialization (tree template_id,
tree decl,
tree* targs_out,
int need_member_template,
int template_count,
tmpl_spec_kind tsk)
{
tree fns;
tree targs;
tree explicit_targs;
tree candidates = NULL_TREE;
/* A TREE_LIST of templates of which DECL may be a specialization.
The TREE_VALUE of each node is a TEMPLATE_DECL. The
corresponding TREE_PURPOSE is the set of template arguments that,
when used to instantiate the template, would produce a function
with the signature of DECL. */
tree templates = NULL_TREE;
int header_count;
cp_binding_level *b;
*targs_out = NULL_TREE;
if (template_id == error_mark_node || decl == error_mark_node)
return error_mark_node;
/* We shouldn't be specializing a member template of an
unspecialized class template; we already gave an error in
check_specialization_scope, now avoid crashing. */
if (!VAR_P (decl)
&& template_count && DECL_CLASS_SCOPE_P (decl)
&& template_class_depth (DECL_CONTEXT (decl)) > 0)
{
gcc_assert (errorcount);
return error_mark_node;
}
fns = TREE_OPERAND (template_id, 0);
explicit_targs = TREE_OPERAND (template_id, 1);
if (fns == error_mark_node)
return error_mark_node;
/* Check for baselinks. */
if (BASELINK_P (fns))
fns = BASELINK_FUNCTIONS (fns);
if (TREE_CODE (decl) == FUNCTION_DECL && !is_overloaded_fn (fns))
{
error_at (DECL_SOURCE_LOCATION (decl),
"%qD is not a function template", fns);
return error_mark_node;
}
else if (VAR_P (decl) && !variable_template_p (fns))
{
error ("%qD is not a variable template", fns);
return error_mark_node;
}
/* Count the number of template headers specified for this
specialization. */
header_count = 0;
for (b = current_binding_level;
b->kind == sk_template_parms;
b = b->level_chain)
++header_count;
tree orig_fns = fns;
bool header_mismatch = false;
if (variable_template_p (fns))
{
tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (fns));
targs = coerce_template_parms (parms, explicit_targs, fns,
tf_warning_or_error);
if (targs != error_mark_node
&& constraints_satisfied_p (fns, targs))
templates = tree_cons (targs, fns, templates);
}
else for (lkp_iterator iter (fns); iter; ++iter)
{
tree fn = *iter;
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
tree decl_arg_types;
tree fn_arg_types;
/* In case of explicit specialization, we need to check if
the number of template headers appearing in the specialization
is correct. This is usually done in check_explicit_specialization,
but the check done there cannot be exhaustive when specializing
member functions. Consider the following code:
template <> void A<int>::f(int);
template <> template <> void A<int>::f(int);
Assuming that A<int> is not itself an explicit specialization
already, the first line specializes "f" which is a non-template
member function, whilst the second line specializes "f" which
is a template member function. So both lines are syntactically
correct, and check_explicit_specialization does not reject
them.
Here, we can do better, as we are matching the specialization
against the declarations. We count the number of template
headers, and we check if they match TEMPLATE_COUNT + 1
(TEMPLATE_COUNT is the number of qualifying template classes,
plus there must be another header for the member template
itself).
Notice that if header_count is zero, this is not a
specialization but rather a template instantiation, so there
is no check we can perform here. */
if (header_count && header_count != template_count + 1)
{
header_mismatch = true;
continue;
}
/* Check that the number of template arguments at the
innermost level for DECL is the same as for FN. */
if (current_binding_level->kind == sk_template_parms
&& !current_binding_level->explicit_spec_p
&& (TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (fn))
!= TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
(current_template_parms))))
continue;
/* DECL might be a specialization of FN. */
decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
/* For a non-static member function, we need to make sure
that the const qualification is the same. Since
get_bindings does not try to merge the "this" parameter,
we must do the comparison explicitly. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
{
if (!same_type_p (TREE_VALUE (fn_arg_types),
TREE_VALUE (decl_arg_types)))
continue;
/* And the ref-qualification. */
if (type_memfn_rqual (TREE_TYPE (decl))
!= type_memfn_rqual (TREE_TYPE (fn)))
continue;
}
/* Skip the "this" parameter and, for constructors of
classes with virtual bases, the VTT parameter. A
full specialization of a constructor will have a VTT
parameter, but a template never will. */
decl_arg_types
= skip_artificial_parms_for (decl, decl_arg_types);
fn_arg_types
= skip_artificial_parms_for (fn, fn_arg_types);
/* Function templates cannot be specializations; there are
no partial specializations of functions. Therefore, if
the type of DECL does not match FN, there is no
match.
Note that it should never be the case that we have both
candidates added here, and for regular member functions
below. */
if (tsk == tsk_template)
{
if (!comp_template_parms (DECL_TEMPLATE_PARMS (fn),
current_template_parms))
continue;
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
TREE_TYPE (TREE_TYPE (fn))))
continue;
if (!compparms (fn_arg_types, decl_arg_types))
continue;
tree freq = get_constraints (fn);
tree dreq = get_constraints (decl);
if (!freq != !dreq)
continue;
if (freq)
{
/* C++20 CA104: Substitute directly into the
constraint-expression. */
tree fargs = DECL_TI_ARGS (fn);
tsubst_flags_t complain = tf_none;
freq = tsubst_constraint_info (freq, fargs, complain, fn);
if (!cp_tree_equal (freq, dreq))
continue;
}
candidates = tree_cons (NULL_TREE, fn, candidates);
continue;
}
/* See whether this function might be a specialization of this
template. Suppress access control because we might be trying
to make this specialization a friend, and we have already done
access control for the declaration of the specialization. */
push_deferring_access_checks (dk_no_check);
targs = get_bindings (fn, decl, explicit_targs, /*check_ret=*/true);
pop_deferring_access_checks ();
if (!targs)
/* We cannot deduce template arguments that when used to
specialize TMPL will produce DECL. */
continue;
if (uses_template_parms (targs))
/* We deduced something involving 'auto', which isn't a valid
template argument. */
continue;
/* Save this template, and the arguments deduced. */
templates = tree_cons (targs, fn, templates);
}
else if (need_member_template)
/* FN is an ordinary member function, and we need a
specialization of a member template. */
;
else if (TREE_CODE (fn) != FUNCTION_DECL)
/* We can get IDENTIFIER_NODEs here in certain erroneous
cases. */
;
else if (!DECL_FUNCTION_MEMBER_P (fn))
/* This is just an ordinary non-member function. Nothing can
be a specialization of that. */
;
else if (DECL_ARTIFICIAL (fn))
/* Cannot specialize functions that are created implicitly. */
;
else
{
tree decl_arg_types;
/* This is an ordinary member function. However, since
we're here, we can assume its enclosing class is a
template class. For example,
template <typename T> struct S { void f(); };
template <> void S<int>::f() {}
Here, S<int>::f is a non-template, but S<int> is a
template class. If FN has the same type as DECL, we
might be in business. */
if (!DECL_TEMPLATE_INFO (fn))
/* Its enclosing class is an explicit specialization
of a template class. This is not a candidate. */
continue;
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
TREE_TYPE (TREE_TYPE (fn))))
/* The return types differ. */
continue;
/* Adjust the type of DECL in case FN is a static member. */
decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
if (DECL_STATIC_FUNCTION_P (fn)
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
decl_arg_types = TREE_CHAIN (decl_arg_types);
if (!compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
decl_arg_types))
continue;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
&& (type_memfn_rqual (TREE_TYPE (decl))
!= type_memfn_rqual (TREE_TYPE (fn))))
continue;
// If the deduced arguments do not satisfy the constraints,
// this is not a candidate.
if (flag_concepts && !constraints_satisfied_p (fn))
continue;
// Add the candidate.
candidates = tree_cons (NULL_TREE, fn, candidates);
}
}
if (templates && TREE_CHAIN (templates))
{
/* We have:
[temp.expl.spec]
It is possible for a specialization with a given function
signature to be instantiated from more than one function
template. In such cases, explicit specification of the
template arguments must be used to uniquely identify the
function template specialization being specialized.
Note that here, there's no suggestion that we're supposed to
determine which of the candidate templates is most
specialized. However, we, also have:
[temp.func.order]
Partial ordering of overloaded function template
declarations is used in the following contexts to select
the function template to which a function template
specialization refers:
-- when an explicit specialization refers to a function
template.
So, we do use the partial ordering rules, at least for now.
This extension can only serve to make invalid programs valid,
so it's safe. And, there is strong anecdotal evidence that
the committee intended the partial ordering rules to apply;
the EDG front end has that behavior, and John Spicer claims
that the committee simply forgot to delete the wording in
[temp.expl.spec]. */
tree tmpl = most_specialized_instantiation (templates);
if (tmpl != error_mark_node)
{
templates = tmpl;
TREE_CHAIN (templates) = NULL_TREE;
}
}
// Concepts allows multiple declarations of member functions
// with the same signature. Like above, we need to rely on
// on the partial ordering of those candidates to determine which
// is the best.
if (flag_concepts && candidates && TREE_CHAIN (candidates))
{
if (tree cand = most_constrained_function (candidates))
{
candidates = cand;
TREE_CHAIN (cand) = NULL_TREE;
}
}
if (templates == NULL_TREE && candidates == NULL_TREE)
{
error ("template-id %qD for %q+D does not match any template "
"declaration", template_id, decl);
if (header_mismatch)
inform (DECL_SOURCE_LOCATION (decl),
"saw %d %<template<>%>, need %d for "
"specializing a member function template",
header_count, template_count + 1);
print_candidates (orig_fns);
return error_mark_node;
}
else if ((templates && TREE_CHAIN (templates))
|| (candidates && TREE_CHAIN (candidates))
|| (templates && candidates))
{
error ("ambiguous template specialization %qD for %q+D",
template_id, decl);
candidates = chainon (candidates, templates);
print_candidates (candidates);
return error_mark_node;
}
/* We have one, and exactly one, match. */
if (candidates)
{
tree fn = TREE_VALUE (candidates);
*targs_out = copy_node (DECL_TI_ARGS (fn));
/* Propagate the candidate's constraints to the declaration. */
if (tsk != tsk_template)
set_constraints (decl, get_constraints (fn));
/* DECL is a re-declaration or partial instantiation of a template
function. */
if (TREE_CODE (fn) == TEMPLATE_DECL)
return fn;
/* It was a specialization of an ordinary member function in a
template class. */
return DECL_TI_TEMPLATE (fn);
}
/* It was a specialization of a template. */
targs = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (TREE_VALUE (templates)));
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))
{
*targs_out = copy_node (targs);
SET_TMPL_ARGS_LEVEL (*targs_out,
TMPL_ARGS_DEPTH (*targs_out),
TREE_PURPOSE (templates));
}
else
*targs_out = TREE_PURPOSE (templates);
return TREE_VALUE (templates);
}
/* Returns a chain of parameter types, exactly like the SPEC_TYPES,
but with the default argument values filled in from those in the
TMPL_TYPES. */
static tree
copy_default_args_to_explicit_spec_1 (tree spec_types,
tree tmpl_types)
{
tree new_spec_types;
if (!spec_types)
return NULL_TREE;
if (spec_types == void_list_node)
return void_list_node;
/* Substitute into the rest of the list. */
new_spec_types =
copy_default_args_to_explicit_spec_1 (TREE_CHAIN (spec_types),
TREE_CHAIN (tmpl_types));
/* Add the default argument for this parameter. */
return hash_tree_cons (TREE_PURPOSE (tmpl_types),
TREE_VALUE (spec_types),
new_spec_types);
}
/* DECL is an explicit specialization. Replicate default arguments
from the template it specializes. (That way, code like:
template <class T> void f(T = 3);
template <> void f(double);
void g () { f (); }
works, as required.) An alternative approach would be to look up
the correct default arguments at the call-site, but this approach
is consistent with how implicit instantiations are handled. */
static void
copy_default_args_to_explicit_spec (tree decl)
{
tree tmpl;
tree spec_types;
tree tmpl_types;
tree new_spec_types;
tree old_type;
tree new_type;
tree t;
tree object_type = NULL_TREE;
tree in_charge = NULL_TREE;
tree vtt = NULL_TREE;
/* See if there's anything we need to do. */
tmpl = DECL_TI_TEMPLATE (decl);
tmpl_types = TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (tmpl)));
for (t = tmpl_types; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
break;
if (!t)
return;
old_type = TREE_TYPE (decl);
spec_types = TYPE_ARG_TYPES (old_type);
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
{
/* Remove the this pointer, but remember the object's type for
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;
spec_types = TREE_CHAIN (spec_types);
}
if (DECL_HAS_VTT_PARM_P (decl))
{
vtt = spec_types;
spec_types = TREE_CHAIN (spec_types);
}
}
/* Compute the merged default arguments. */
new_spec_types =
copy_default_args_to_explicit_spec_1 (spec_types, tmpl_types);
/* Compute the new FUNCTION_TYPE. */
if (object_type)
{
if (vtt)
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);
new_type = build_method_type_directly (object_type,
TREE_TYPE (old_type),
new_spec_types);
}
else
new_type = build_function_type (TREE_TYPE (old_type),
new_spec_types);
new_type = cp_build_type_attribute_variant (new_type,
TYPE_ATTRIBUTES (old_type));
new_type = cxx_copy_lang_qualifiers (new_type, old_type);
TREE_TYPE (decl) = new_type;
}
/* Return the number of template headers we expect to see for a definition
or specialization of CTYPE or one of its non-template members. */
int
num_template_headers_for_class (tree ctype)
{
int num_templates = 0;
while (ctype && CLASS_TYPE_P (ctype))
{
/* You're supposed to have one `template <...>' for every
template class, but you don't need one for a full
specialization. For example:
template <class T> struct S{};
template <> struct S<int> { void f(); };
void S<int>::f () {}
is correct; there shouldn't be a `template <>' for the
definition of `S<int>::f'. */
if (!CLASSTYPE_TEMPLATE_INFO (ctype))
/* If CTYPE does not have template information of any
kind, then it is not a template, nor is it nested
within a template. */
break;
if (explicit_class_specialization_p (ctype))
break;
if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (ctype)))
++num_templates;
ctype = TYPE_CONTEXT (ctype);
}
return num_templates;
}
/* Do a simple sanity check on the template headers that precede the
variable declaration DECL. */
void
check_template_variable (tree decl)
{
tree ctx = CP_DECL_CONTEXT (decl);
int wanted = num_template_headers_for_class (ctx);
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)))
{
if (cxx_dialect < cxx14)
pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wc__14_extensions,
"variable templates only available with "
"%<-std=c++14%> or %<-std=gnu++14%>");
// Namespace-scope variable templates should have a template header.
++wanted;
}
if (template_header_count > wanted)
{
auto_diagnostic_group d;
bool warned = pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"too many template headers for %qD "
"(should be %d)",
decl, wanted);
if (warned && CLASS_TYPE_P (ctx)
&& CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx))
inform (DECL_SOURCE_LOCATION (decl),
"members of an explicitly specialized class are defined "
"without a template header");
}
}
/* An explicit specialization whose declarator-id or class-head-name is not
qualified shall be declared in the nearest enclosing namespace of the
template, or, if the namespace is inline (7.3.1), any namespace from its
enclosing namespace set.
If the name declared in the explicit instantiation is an unqualified name,
the explicit instantiation shall appear in the namespace where its template
is declared or, if that namespace is inline (7.3.1), any namespace from its
enclosing namespace set. */
void
check_unqualified_spec_or_inst (tree t, location_t loc)
{
tree tmpl = most_general_template (t);
if (DECL_NAMESPACE_SCOPE_P (tmpl)
&& !is_nested_namespace (current_namespace,
CP_DECL_CONTEXT (tmpl), true))
{
if (processing_specialization)
permerror (loc, "explicit specialization of %qD outside its "
"namespace must use a nested-name-specifier", tmpl);
else if (processing_explicit_instantiation
&& cxx_dialect >= cxx11)
/* This was allowed in C++98, so only pedwarn. */
pedwarn (loc, OPT_Wpedantic, "explicit instantiation of %qD "
"outside its namespace must use a nested-name-"
"specifier", tmpl);
}
}
/* Warn for a template specialization SPEC that is missing some of a set
of function or type attributes that the template TEMPL is declared with.
ATTRLIST is a list of additional attributes that SPEC should be taken
to ultimately be declared with. */
static void
warn_spec_missing_attributes (tree tmpl, tree spec, tree attrlist)
{
if (DECL_FUNCTION_TEMPLATE_P (tmpl))
tmpl = DECL_TEMPLATE_RESULT (tmpl);
/* Avoid warning if the difference between the primary and
the specialization is not in one of the attributes below. */
const char* const blacklist[] = {
"alloc_align", "alloc_size", "assume_aligned", "format",
"format_arg", "malloc", "nonnull", NULL
};
/* Put together a list of the black listed attributes that the primary
template is declared with that the specialization is not, in case
it's not apparent from the most recent declaration of the primary. */
pretty_printer str;
unsigned nattrs = decls_mismatched_attributes (tmpl, spec, attrlist,
blacklist, &str);
if (!nattrs)
return;
auto_diagnostic_group d;
if (warning_at (DECL_SOURCE_LOCATION (spec), OPT_Wmissing_attributes,
"explicit specialization %q#D may be missing attributes",
spec))
inform (DECL_SOURCE_LOCATION (tmpl),
nattrs > 1
? G_("missing primary template attributes %s")
: G_("missing primary template attribute %s"),
pp_formatted_text (&str));
}
/* Check to see if the function just declared, as indicated in
DECLARATOR, and in DECL, is a specialization of a function
template. We may also discover that the declaration is an explicit
instantiation at this point.
Returns DECL, or an equivalent declaration that should be used
instead if all goes well. Issues an error message if something is
amiss. Returns error_mark_node if the error is not easily
recoverable.
FLAGS is a bitmask consisting of the following flags:
2: The function has a definition.
4: The function is a friend.
The TEMPLATE_COUNT is the number of references to qualifying
template classes that appeared in the name of the function. For
example, in
template <class T> struct S { void f(); };
void S<int>::f();
the TEMPLATE_COUNT would be 1. However, explicitly specialized
classes are not counted in the TEMPLATE_COUNT, so that in
template <class T> struct S {};
template <> struct S<int> { void f(); }
template <> void S<int>::f();
the TEMPLATE_COUNT would be 0. (Note that this declaration is
invalid; there should be no template <>.)
If the function is a specialization, it is marked as such via
DECL_TEMPLATE_SPECIALIZATION. Furthermore, its DECL_TEMPLATE_INFO
is set up correctly, and it is added to the list of specializations
for that template. */
tree
check_explicit_specialization (tree declarator,
tree decl,
int template_count,
int flags,
tree attrlist)
{
int have_def = flags & 2;
int is_friend = flags & 4;
bool is_concept = flags & 8;
int specialization = 0;
int explicit_instantiation = 0;
int member_specialization = 0;
tree ctype = DECL_CLASS_CONTEXT (decl);
tree dname = DECL_NAME (decl);
tmpl_spec_kind tsk;
if (is_friend)
{
if (!processing_specialization)
tsk = tsk_none;
else
tsk = tsk_excessive_parms;
}
else
tsk = current_tmpl_spec_kind (template_count);
switch (tsk)
{
case tsk_none:
if (processing_specialization && !VAR_P (decl))
{
specialization = 1;
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
}
else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
|| (DECL_LANG_SPECIFIC (decl)
&& DECL_IMPLICIT_INSTANTIATION (decl)))
{
if (is_friend)
/* This could be something like:
template <class T> void f(T);
class S { friend void f<>(int); } */
specialization = 1;
else
{
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
error_at (cp_expr_loc_or_input_loc (declarator),
"template-id %qE in declaration of primary template",
declarator);
return decl;
}
}
break;
case tsk_invalid_member_spec:
/* The error has already been reported in
check_specialization_scope. */
return error_mark_node;
case tsk_invalid_expl_inst:
error ("template parameter list used in explicit instantiation");
/* Fall through. */
case tsk_expl_inst:
if (have_def)
error ("definition provided for explicit instantiation");
explicit_instantiation = 1;
break;
case tsk_excessive_parms:
case tsk_insufficient_parms:
if (tsk == tsk_excessive_parms)
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);
else
error("explicit specialization of %qD must be introduced by "
"%<template <>%>", decl);
/* Fall through. */
case tsk_expl_spec:
if (is_concept)
error ("explicit specialization declared %<concept%>");
if (VAR_P (decl) && TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
/* In cases like template<> constexpr bool v = true;
We'll give an error in check_template_variable. */
break;
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
if (ctype)
member_specialization = 1;
else
specialization = 1;
break;
case tsk_template:
if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
{
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
if (!uses_template_parms (TREE_OPERAND (declarator, 1)))
error_at (cp_expr_loc_or_input_loc (declarator),
"template-id %qE in declaration of primary template",
declarator);
else if (variable_template_p (TREE_OPERAND (declarator, 0)))
{
/* Partial specialization of variable template. */
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
specialization = 1;
goto ok;
}
else if (cxx_dialect < cxx14)
error_at (cp_expr_loc_or_input_loc (declarator),
"non-type partial specialization %qE "
"is not allowed", declarator);
else
error_at (cp_expr_loc_or_input_loc (declarator),
"non-class, non-variable partial specialization %qE "
"is not allowed", declarator);
return decl;
ok:;
}
if (ctype && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
/* This is a specialization of a member template, without
specialization the containing class. Something like:
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. */
specialization = 1;
break;
default:
gcc_unreachable ();
}
if ((specialization || member_specialization)
/* This doesn't apply to variable templates. */
&& FUNC_OR_METHOD_TYPE_P (TREE_TYPE (decl)))
{
tree t = TYPE_ARG_TYPES (TREE_TYPE (decl));
for (; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t))
{
permerror (input_location,
"default argument specified in explicit specialization");
break;
}
}
if (specialization || member_specialization || explicit_instantiation)
{
tree tmpl = NULL_TREE;
tree targs = NULL_TREE;
bool was_template_id = (TREE_CODE (declarator) == TEMPLATE_ID_EXPR);
bool found_hidden = false;
/* Make sure that the declarator is a TEMPLATE_ID_EXPR. */
if (!was_template_id)
{
tree fns;
gcc_assert (identifier_p (declarator));
if (ctype)
fns = dname;
else
{
/* If there is no class context, the explicit instantiation
must be at namespace scope. */
gcc_assert (DECL_NAMESPACE_SCOPE_P (decl));
/* Find the namespace binding, using the declaration
context. */
fns = lookup_qualified_name (CP_DECL_CONTEXT (decl), dname,
LOOK_want::NORMAL, true);
if (fns == error_mark_node)
{
/* If lookup fails, look for a friend declaration so we can
give a better diagnostic. */
fns = (lookup_qualified_name
(CP_DECL_CONTEXT (decl), dname,
LOOK_want::NORMAL | LOOK_want::HIDDEN_FRIEND,
/*complain*/true));
found_hidden = true;
}
if (fns == error_mark_node || !is_overloaded_fn (fns))
{
error ("%qD is not a template function", dname);
fns = error_mark_node;
}
}
declarator = lookup_template_function (fns, NULL_TREE);
}
if (declarator == error_mark_node)
return error_mark_node;
if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype))
{
if (!explicit_instantiation)
/* A specialization in class scope. This is invalid,
but the error will already have been flagged by
check_specialization_scope. */
return error_mark_node;
else
{
/* It's not valid to write an explicit instantiation in
class scope, e.g.:
class C { template void f(); }
This case is caught by the parser. However, on
something like:
template class C { void f(); };
(which is invalid) we can get here. The error will be
issued later. */
;
}
return decl;
}
else if (ctype != NULL_TREE
&& (identifier_p (TREE_OPERAND (declarator, 0))))
{
// We'll match variable templates in start_decl.
if (VAR_P (decl))
return decl;
/* Find the list of functions in ctype that have the same
name as the declared function. */
tree name = TREE_OPERAND (declarator, 0);
if (constructor_name_p (name, ctype))
{
if (DECL_CONSTRUCTOR_P (decl)
? !TYPE_HAS_USER_CONSTRUCTOR (ctype)
: !CLASSTYPE_DESTRUCTOR (ctype))
{
/* From [temp.expl.spec]:
If such an explicit specialization for the member
of a class template names an implicitly-declared
special member function (clause _special_), the
program is ill-formed.
Similar language is found in [temp.explicit]. */
error ("specialization of implicitly-declared special member function");
return error_mark_node;
}
name = DECL_NAME (decl);
}
/* For a type-conversion operator, We might be looking for
`operator int' which will be a specialization of
`operator T'. Grab all the conversion operators, and
then select from them. */
tree fns = get_class_binding (ctype, IDENTIFIER_CONV_OP_P (name)
? conv_op_identifier : name);
if (fns == NULL_TREE)
{
error ("no member function %qD declared in %qT", name, ctype);
return error_mark_node;
}
else
TREE_OPERAND (declarator, 0) = fns;
}
/* Figure out what exactly is being specialized at this point.
Note that for an explicit instantiation, even one for a
member function, we cannot tell a priori whether the
instantiation is for a member template, or just a member
function of a template class. Even if a member template is
being instantiated, the member template arguments may be
elided if they can be deduced from the rest of the
declaration. */
tmpl = determine_specialization (declarator, decl,
&targs,
member_specialization,
template_count,
tsk);
if (!tmpl || tmpl == error_mark_node)
/* We couldn't figure out what this declaration was
specializing. */
return error_mark_node;
else
{
if (found_hidden && TREE_CODE (decl) == FUNCTION_DECL)
{
auto_diagnostic_group d;
if (pedwarn (DECL_SOURCE_LOCATION (decl), 0,
"friend declaration %qD is not visible to "
"explicit specialization", tmpl))
inform (DECL_SOURCE_LOCATION (tmpl),
"friend declaration here");
}
if (!ctype && !is_friend
&& CP_DECL_CONTEXT (decl) == current_namespace)
check_unqualified_spec_or_inst (tmpl, DECL_SOURCE_LOCATION (decl));
tree gen_tmpl = most_general_template (tmpl);
if (explicit_instantiation)
{
/* We don't set DECL_EXPLICIT_INSTANTIATION here; that
is done by do_decl_instantiation later. */
int arg_depth = TMPL_ARGS_DEPTH (targs);
int parm_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl));
if (arg_depth > parm_depth)
{
/* If TMPL is not the most general template (for
example, if TMPL is a friend template that is
injected into namespace scope), then there will
be too many levels of TARGS. Remove some of them
here. */
int i;
tree new_targs;
new_targs = make_tree_vec (parm_depth);
for (i = arg_depth - parm_depth; i < arg_depth; ++i)
TREE_VEC_ELT (new_targs, i - (arg_depth - parm_depth))
= TREE_VEC_ELT (targs, i);
targs = new_targs;
}
return instantiate_template (tmpl, targs, tf_error);
}
/* If we thought that the DECL was a member function, but it
turns out to be specializing a static member function,
make DECL a static member function as well. */
if (DECL_FUNCTION_TEMPLATE_P (tmpl)
&& DECL_STATIC_FUNCTION_P (tmpl)
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
revert_static_member_fn (decl);
/* If this is a specialization of a member template of a
template class, we want to return the TEMPLATE_DECL, not
the specialization of it. */
if (tsk == tsk_template && !was_template_id)
{
tree result = DECL_TEMPLATE_RESULT (tmpl);
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
DECL_INITIAL (result) = NULL_TREE;
if (have_def)
{
tree parm;
DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
DECL_SOURCE_LOCATION (result)
= DECL_SOURCE_LOCATION (decl);
/* We want to use the argument list specified in the
definition, not in the original declaration. */
DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl);
for (parm = DECL_ARGUMENTS (result); parm;
parm = DECL_CHAIN (parm))
DECL_CONTEXT (parm) = result;
}
decl = register_specialization (tmpl, gen_tmpl, targs,
is_friend, 0);
remove_contract_attributes (result);
return decl;
}
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = build_template_info (tmpl, targs);
if (was_template_id)
TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl)) = true;
/* Inherit default function arguments from the template
DECL is specializing. */
if (DECL_FUNCTION_TEMPLATE_P (tmpl))
copy_default_args_to_explicit_spec (decl);
/* This specialization has the same protection as the
template it specializes. */
TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
/* 7.1.1-1 [dcl.stc]
A storage-class-specifier shall not be specified in an
explicit specialization...
The parser rejects these, so unless action is taken here,
explicit function specializations will always appear with
global linkage.
The action recommended by the C++ CWG in response to C++
defect report 605 is to make the storage class and linkage
of the explicit specialization match the templated function:
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#605
*/
if (tsk == tsk_expl_spec && DECL_FUNCTION_TEMPLATE_P (gen_tmpl))
{
tree tmpl_func = DECL_TEMPLATE_RESULT (gen_tmpl);
gcc_assert (TREE_CODE (tmpl_func) == FUNCTION_DECL);
/* A concept cannot be specialized. */
if (DECL_DECLARED_CONCEPT_P (tmpl_func))
{
error ("explicit specialization of function concept %qD",
gen_tmpl);
return error_mark_node;
}
/* This specialization has the same linkage and visibility as
the function template it specializes. */
TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func);
if (! TREE_PUBLIC (decl))
{
DECL_INTERFACE_KNOWN (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func);
if (DECL_VISIBILITY_SPECIFIED (tmpl_func))
{
DECL_VISIBILITY_SPECIFIED (decl) = 1;
DECL_VISIBILITY (decl) = DECL_VISIBILITY (tmpl_func);
}
}
/* 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.
It's just the name of an instantiation. But, it's not
a request for an instantiation, either. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
else if (TREE_CODE (decl) == FUNCTION_DECL)
/* A specialization is not necessarily COMDAT. */
DECL_COMDAT (decl) = (TREE_PUBLIC (decl)
&& DECL_DECLARED_INLINE_P (decl));
else if (VAR_P (decl))
DECL_COMDAT (decl) = false;
/* If this is a full specialization, register it so that we can find
it again. Partial specializations will be registered in
process_partial_specialization. */
if (!processing_template_decl)
{
warn_spec_missing_attributes (gen_tmpl, decl, attrlist);
decl = register_specialization (decl, gen_tmpl, targs,
is_friend, 0);
}
/* If this is a specialization, splice any contracts that may have
been inherited from the template, removing them. */
if (decl != error_mark_node && DECL_TEMPLATE_SPECIALIZATION (decl))
remove_contract_attributes (decl);
/* A 'structor should already have clones. */
gcc_assert (decl == error_mark_node
|| variable_template_p (tmpl)
|| !(DECL_CONSTRUCTOR_P (decl)
|| DECL_DESTRUCTOR_P (decl))
|| DECL_CLONED_FUNCTION_P (DECL_CHAIN (decl)));
}
}
return decl;
}
/* Returns 1 iff PARMS1 and PARMS2 are identical sets of template
parameters. These are represented in the same format used for
DECL_TEMPLATE_PARMS. */
int
comp_template_parms (const_tree parms1, const_tree parms2)
{
const_tree p1;
const_tree p2;
if (parms1 == parms2)
return 1;
for (p1 = parms1, p2 = parms2;
p1 != NULL_TREE && p2 != NULL_TREE;
p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2))
{
tree t1 = TREE_VALUE (p1);
tree t2 = TREE_VALUE (p2);
int i;
gcc_assert (TREE_CODE (t1) == TREE_VEC);
gcc_assert (TREE_CODE (t2) == TREE_VEC);
if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2))
return 0;
for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
{
tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
/* If either of the template parameters are invalid, assume
they match for the sake of error recovery. */
if (error_operand_p (parm1) || error_operand_p (parm2))
return 1;
if (TREE_CODE (parm1) != TREE_CODE (parm2))
return 0;
if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM
&& (TEMPLATE_TYPE_PARAMETER_PACK (parm1)
== TEMPLATE_TYPE_PARAMETER_PACK (parm2)))
continue;
else if (!same_type_p (TREE_TYPE (parm1), TREE_TYPE (parm2)))
return 0;
}
}
if ((p1 != NULL_TREE) != (p2 != NULL_TREE))
/* One set of parameters has more parameters lists than the
other. */
return 0;
return 1;
}
/* Returns true if two template parameters are declared with
equivalent constraints. */