pt.c (copy_default_args_to_explicit_spec_1): New function.

* pt.c (copy_default_args_to_explicit_spec_1): New function.
	(copy_default_args_to_explicit_spec): Likewise.
	(check_explicit_specialization): Use it.

From-SVN: r38893
This commit is contained in:
Mark Mitchell 2001-01-11 03:10:12 +00:00 committed by Mark Mitchell
parent 7e1376a14c
commit 8afa707fab
3 changed files with 128 additions and 25 deletions

View File

@ -1,5 +1,9 @@
2001-01-10 Mark Mitchell <mark@codesourcery.com>
* pt.c (copy_default_args_to_explicit_spec_1): New function.
(copy_default_args_to_explicit_spec): Likewise.
(check_explicit_specialization): Use it.
* class.c (finish_struct_1): Remove last argument in call to
make_decl_rtl; use make_function_rtl instead of make_decl_rtl.
* decl.c (builtin_function): Likewise.

View File

@ -167,6 +167,8 @@ static int template_args_equal PARAMS ((tree, tree));
static void tsubst_default_arguments PARAMS ((tree));
static tree for_each_template_parm_r PARAMS ((tree *, int *, void *));
static tree instantiate_clone PARAMS ((tree, tree));
static tree copy_default_args_to_explicit_spec_1 PARAMS ((tree, tree));
static void copy_default_args_to_explicit_spec PARAMS ((tree));
/* Called once to initialize pt.c. */
@ -1151,7 +1153,112 @@ determine_specialization (template_id, decl, targs_out,
*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 (spec_types,
tmpl_types)
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 (decl)
tree decl;
{
tree tmpl;
tree spec_types;
tree tmpl_types;
tree new_spec_types;
tree old_type;
tree new_type;
tree t;
/* 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);
/* DECL may contain more parameters than TMPL due to the extra
in-charge parameter in constructors and destructors. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
{
spec_types = TREE_CHAIN (spec_types);
tmpl_types = TREE_CHAIN (tmpl_types);
if (DECL_HAS_IN_CHARGE_PARM_P (decl))
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);
/* Put the extra parameters back together -- but note that
build_cplus_method_type will automatically add the `this'
pointer. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
&& DECL_HAS_IN_CHARGE_PARM_P (decl))
{
tree t = TREE_CHAIN (TYPE_ARG_TYPES (old_type));
new_spec_types = hash_tree_cons (TREE_PURPOSE (t),
TREE_VALUE (t),
new_spec_types);
}
/* Compute the new FUNCTION_TYPE. */
if (TREE_CODE (old_type) == METHOD_TYPE)
new_type = build_cplus_method_type (TYPE_METHOD_BASETYPE (old_type),
TREE_TYPE (old_type),
new_spec_types);
else
new_type = build_function_type (TREE_TYPE (old_type),
new_spec_types);
new_type = build_type_attribute_variant (new_type,
TYPE_ATTRIBUTES (old_type));
new_type = build_exception_variant (new_type,
TYPE_RAISES_EXCEPTIONS (old_type));
TREE_TYPE (decl) = new_type;
}
/* 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
@ -1542,34 +1649,13 @@ check_explicit_specialization (declarator, decl, template_count, flags)
last_function_parms = TREE_CHAIN (last_function_parms);
}
/* Inherit default function arguments from the template
DECL is specializing. */
{
tree t1 = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree t2 = TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (tmpl)));
/* DECL may contain more parameters than TMPL due to the extra
in-charge parameter in constructors and destructors. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
if (DECL_HAS_IN_CHARGE_PARM_P (decl))
t1 = TREE_CHAIN (t1);
/* Note that we do not need to reparse default arguments,
since explicit specialization cannot be declared in
class scope as in [temp.expl.spec]. */
for (; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
{
if (TREE_PURPOSE (t2))
TREE_PURPOSE (t1) = TREE_PURPOSE (t2);
}
my_friendly_assert (t1 == NULL_TREE && t2 == NULL_TREE, 20001211);
}
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = tree_cons (tmpl, targs, NULL_TREE);
/* Inherit default function arguments from the template
DECL is specializing. */
copy_default_args_to_explicit_spec (decl);
/* Mangle the function name appropriately. Note that we do
not mangle specializations of non-template member
functions of template classes, e.g. with

View File

@ -0,0 +1,13 @@
// Build don't link:
// Origin: Gerald Pfeifer <pfeifer@dbai.tuwien.ac.at>
#include <vector>
#include <fstream>
class STACK {
public:
std::vector<int> data;
STACK() : data()
{ }
};