static void perform_typedefs_access_check (tree tmpl, tree targs);
static void append_type_to_template_for_access_check_1 (tree, tree, tree);
static hashval_t iterative_hash_template_arg (tree arg, hashval_t val);
+static bool primary_template_instantiation_p (const_tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
/* Return the template info node corresponding to T, whatever T is. */
tree
-get_template_info (tree t)
+get_template_info (const_tree t)
{
tree tinfo = NULL_TREE;
{
if (DECL_TEMPLATE_INSTANTIATION (fn))
{
- if (TREE_USED (fn)
+ if (DECL_ODR_USED (fn)
|| DECL_EXPLICIT_INSTANTIATION (fn))
{
error ("specialization of %qD after instantiation",
make_ith_pack_parameter_name (tree name, int i)
{
/* Munge the name to include the parameter index. */
- char numbuf[128];
+#define NUMBUF_LEN 128
+ char numbuf[NUMBUF_LEN];
char* newname;
-
- sprintf(numbuf, "%i", i);
- newname = (char*)alloca (IDENTIFIER_LENGTH (name) + strlen(numbuf) + 2);
- sprintf(newname, "%s#%i", IDENTIFIER_POINTER (name), i);
+ int newname_len;
+
+ snprintf (numbuf, NUMBUF_LEN, "%i", i);
+ newname_len = IDENTIFIER_LENGTH (name)
+ + strlen (numbuf) + 2;
+ newname = (char*)alloca (newname_len);
+ snprintf (newname, newname_len,
+ "%s#%i", IDENTIFIER_POINTER (name), i);
return get_identifier (newname);
}
+/* Return true if T is a primary function
+ or class template instantiation. */
+
+static bool
+primary_template_instantiation_p (const_tree t)
+{
+ if (!t)
+ return false;
+
+ if (TREE_CODE (t) == FUNCTION_DECL)
+ return DECL_LANG_SPECIFIC (t)
+ && DECL_TEMPLATE_INSTANTIATION (t)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t));
+ else if (CLASS_TYPE_P (t))
+ return CLASSTYPE_TEMPLATE_INSTANTIATION (t)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t));
+ return false;
+}
+
+/* Return true if PARM is a template template parameter. */
+
+bool
+template_template_parameter_p (const_tree parm)
+{
+ return DECL_TEMPLATE_TEMPLATE_PARM_P (parm);
+}
+
+/* Return the template parameters of T if T is a
+ primary template instantiation, NULL otherwise. */
+
+tree
+get_primary_template_innermost_parameters (const_tree t)
+{
+ tree parms = NULL, template_info = NULL;
+
+ if ((template_info = get_template_info (t))
+ && primary_template_instantiation_p (t))
+ parms = INNERMOST_TEMPLATE_PARMS
+ (DECL_TEMPLATE_PARMS (TI_TEMPLATE (template_info)));
+
+ return parms;
+}
+
+/* Returns the template arguments of T if T is a template instantiation,
+ NULL otherwise. */
+
+tree
+get_template_innermost_arguments (const_tree t)
+{
+ tree args = NULL, template_info = NULL;
+
+ if ((template_info = get_template_info (t))
+ && TI_ARGS (template_info))
+ args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (template_info));
+
+ return args;
+}
+
+/* Return the arguments pack of T if T is a template, NULL otherwise. */
+
+tree
+get_template_argument_pack_elems (const_tree t)
+{
+ if (TREE_CODE (t) != TYPE_ARGUMENT_PACK
+ && TREE_CODE (t) != NONTYPE_ARGUMENT_PACK)
+ return NULL;
+
+ return ARGUMENT_PACK_ARGS (t);
+}
+
/* Structure used to track the progress of find_parameter_packs_r. */
struct find_parameter_pack_data
{
A template-parameter may not be given default arguments
by two different declarations in the same scope. */
- error ("redefinition of default argument for %q#D", parm);
- inform (input_location, "%Joriginal definition appeared here", tmpl_parm);
+ error_at (input_location, "redefinition of default argument for %q#D", parm);
+ inform (DECL_SOURCE_LOCATION (tmpl_parm),
+ "original definition appeared here");
return false;
}
tree t;
if (!tmpl
- || (TREE_CODE (tmpl) != RECORD_TYPE
+ || (!CLASS_TYPE_P (tmpl)
&& TREE_CODE (tmpl) != FUNCTION_DECL))
return;
cp_function_chain->x_current_class_ref = saved_class_ref;
}
- pop_access_scope (fn);
-
/* Make sure the default argument is reasonable. */
arg = check_default_argument (type, arg);
+ pop_access_scope (fn);
+
return arg;
}
case TEMPLATE_DECL:
{
/* We can get here when processing a member function template,
- member class template, and template template parameter of
- a template class. */
+ member class template, or template template parameter. */
tree decl = DECL_TEMPLATE_RESULT (t);
tree spec;
tree tmpl_args;
if (full_args == error_mark_node)
return error_mark_node;
- /* tsubst_template_args doesn't copy the vector if
- nothing changed. But, *something* should have
- changed. */
- gcc_assert (full_args != tmpl_args);
+ /* If this is a default template template argument,
+ tsubst might not have changed anything. */
+ if (full_args == tmpl_args)
+ return t;
hash = hash_tmpl_and_args (t, full_args);
spec = retrieve_specialization (t, full_args, hash);
if (e1 == error_mark_node || e2 == error_mark_node)
return error_mark_node;
- return fold_build2 (TREE_CODE (t), TREE_TYPE (t), e1, e2);
+ return fold_build2_loc (input_location,
+ TREE_CODE (t), TREE_TYPE (t), e1, e2);
}
case NEGATE_EXPR:
if (e == error_mark_node)
return error_mark_node;
- return fold_build1 (TREE_CODE (t), TREE_TYPE (t), e);
+ return fold_build1_loc (input_location, TREE_CODE (t), TREE_TYPE (t), e);
}
case TYPENAME_TYPE:
But, such constructs have already been resolved by this
point, so here CTX really should have complete type, unless
it's a partial instantiation. */
- ctx = complete_type (ctx);
+ if (!(complain & tf_no_class_instantiations))
+ ctx = complete_type (ctx);
if (!COMPLETE_TYPE_P (ctx))
{
if (complain & tf_error)
if (purpose)
purpose = RECUR (purpose);
value = TREE_VALUE (t);
- if (value)
+ if (value && TREE_CODE (value) != LABEL_DECL)
value = RECUR (value);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
RECUR (ASM_STRING (t)),
tsubst_copy_asm_operands (ASM_OUTPUTS (t), args, complain, in_decl),
tsubst_copy_asm_operands (ASM_INPUTS (t), args, complain, in_decl),
- tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl));
+ tsubst_copy_asm_operands (ASM_CLOBBERS (t), args, complain, in_decl),
+ tsubst_copy_asm_operands (ASM_LABELS (t), args, complain, in_decl));
{
tree asm_expr = tmp;
if (TREE_CODE (asm_expr) == CLEANUP_POINT_EXPR)
}
/* Verify that the instantiated ARGS are valid. For type arguments,
- make sure that the type's linkage is ok. For non-type arguments,
+ make sure that the type is not variably modified. For non-type arguments,
make sure they are constants if they are integral or enumerations.
Emit an error under control of COMPLAIN, and return TRUE on error. */
}
else if (TYPE_P (t))
{
- /* [basic.link]: A name with no linkage (notably, the name
- of a class or enumeration declared in a local scope)
- shall not be used to declare an entity with linkage.
- This implies that names with no linkage cannot be used as
- template arguments. */
- tree nt = no_linkage_check (t, /*relaxed_p=*/false);
-
- if (nt)
- {
- /* DR 488 makes use of a type with no linkage cause
- type deduction to fail. */
- if (complain & tf_error)
- {
- if (TYPE_ANONYMOUS_P (nt))
- error ("%qT is/uses anonymous type", t);
- else
- error ("template argument for %qD uses local type %qT",
- tmpl, t);
- }
- return true;
- }
- /* In order to avoid all sorts of complications, we do not
- allow variably-modified types as template arguments. */
- else if (variably_modified_type_p (t, NULL_TREE))
+ if (variably_modified_type_p (t, NULL_TREE))
{
if (complain & tf_error)
error ("%qT is a variably modified type", t);
to explicitly check cxx_dialect here. */
if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
{
- tree arg = tsubst (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)),
- targs, tf_none, NULL_TREE);
+ tree arg = tsubst_template_arg
+ (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)),
+ targs, tf_none, NULL_TREE);
if (arg == error_mark_node)
return 1;
else
/* If only one of the bounds used a MINUS_EXPR, compensate
by adding one to the other bound. */
if (parm_cst && !arg_cst)
- parm_max = fold_build2 (PLUS_EXPR,
+ parm_max = fold_build2_loc (input_location, PLUS_EXPR,
integer_type_node,
parm_max,
integer_one_node);
else if (arg_cst && !parm_cst)
- arg_max = fold_build2 (PLUS_EXPR,
+ arg_max = fold_build2_loc (input_location, PLUS_EXPR,
integer_type_node,
arg_max,
integer_one_node);
return tmpl;
}
+/* Returns true if we need to instantiate this template instance even if we
+ know we aren't going to emit it.. */
+
+bool
+always_instantiate_p (tree decl)
+{
+ /* We always instantiate inline functions so that we can inline them. An
+ explicit instantiation declaration prohibits implicit instantiation of
+ non-inline functions. With high levels of optimization, we would
+ normally inline non-inline functions -- but we're not allowed to do
+ that for "extern template" functions. Therefore, we check
+ DECL_DECLARED_INLINE_P, rather than possibly_inlined_p. */
+ return ((TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl))
+ /* And we need to instantiate static data members so that
+ their initializers are available in integral constant
+ expressions. */
+ || (TREE_CODE (decl) == VAR_DECL
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)));
+}
+
/* Produce the definition of D, a _DECL generated from a template. If
DEFER_OK is nonzero, then we don't have to actually do the
instantiation now; we just have to do it sometime. Normally it is
the instantiation. */
return d;
+ /* Check to see whether we know that this template will be
+ instantiated in some other file, as with "extern template"
+ extension. */
+ external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
+
+ /* In general, we do not instantiate such templates. */
+ if (external_p && !always_instantiate_p (d))
+ return d;
+
gen_tmpl = most_general_template (tmpl);
gen_args = DECL_TI_ARGS (d);
pop_access_scope (d);
}
- /* Check to see whether we know that this template will be
- instantiated in some other file, as with "extern template"
- extension. */
- external_p = (DECL_INTERFACE_KNOWN (d) && DECL_REALLY_EXTERN (d));
- /* In general, we do not instantiate such templates... */
- if (external_p
- /* ... but we instantiate inline functions so that we can inline
- them. An explicit instantiation declaration prohibits implicit
- instantiation of non-inline functions. With high levels of
- optimization, we would normally inline non-inline functions
- -- but we're not allowed to do that for "extern template" functions.
- Therefore, we check DECL_DECLARED_INLINE_P, rather than
- possibly_inlined_p. And ... */
- && ! (TREE_CODE (d) == FUNCTION_DECL
- && DECL_DECLARED_INLINE_P (d))
- /* ... we instantiate static data members whose values are
- needed in integral constant expressions. */
- && ! (TREE_CODE (d) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (d)))
- goto out;
/* Defer all other templates, unless we have been explicitly
forbidden from doing so. */
if (/* If there is no definition, we cannot instantiate the
if (!(ti = get_template_info (t)))
return NULL_TREE;
- if (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == FUNCTION_DECL)
+ if (CLASS_TYPE_P (t)
+ || TREE_CODE (t) == FUNCTION_DECL)
{
if (!TI_TEMPLATE (ti))
return NULL_TREE;
return;
gcc_assert ((TREE_CODE (t) == FUNCTION_DECL
- || TREE_CODE (t) == RECORD_TYPE)
+ || CLASS_TYPE_P (t))
&& type_decl
&& TREE_CODE (type_decl) == TYPE_DECL
&& scope);