aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/cp-tree.h11
-rw-r--r--gcc/cp/module.cc2
-rw-r--r--gcc/cp/parser.cc6
-rw-r--r--gcc/cp/pt.cc75
-rw-r--r--gcc/cp/ptree.cc3
5 files changed, 66 insertions, 31 deletions
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index fbeff33..2faf6fa 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1564,6 +1564,7 @@ struct GTY(()) tree_template_info {
struct tree_base base;
tree tmpl;
tree args;
+ tree partial;
vec<deferred_access_check, va_gc> *deferred_access_checks;
};
@@ -3755,6 +3756,14 @@ struct GTY(()) lang_decl {
((struct tree_template_info*)TEMPLATE_INFO_CHECK (NODE))->args
#define TI_PENDING_TEMPLATE_FLAG(NODE) \
TREE_LANG_FLAG_1 (TEMPLATE_INFO_CHECK (NODE))
+
+/* For a class or variable template specialization, this contains the
+ TEMPLATE_INFO result of most_specialized_partial_spec, i.e. the selected
+ partial template specialization and arguments relative to it. */
+#define TI_PARTIAL_INFO(NODE) \
+ (gcc_checking_assert (PRIMARY_TEMPLATE_P (TI_TEMPLATE (NODE))), \
+ ((struct tree_template_info*)NODE)->partial)
+
/* For a given TREE_VEC containing a template argument list,
this property contains the number of arguments that are not
defaulted. */
@@ -7398,7 +7407,7 @@ extern bool comp_template_args (tree, tree, tree * = NULL,
extern int template_args_equal (tree, tree, bool = false);
extern tree maybe_process_partial_specialization (tree);
extern tree most_specialized_instantiation (tree);
-extern tree most_specialized_partial_spec (tree, tsubst_flags_t);
+extern tree most_specialized_partial_spec (tree, tsubst_flags_t, bool = false);
extern void print_candidates (tree);
extern void instantiate_pending_templates (int);
extern tree tsubst_default_argument (tree, int, tree, tree,
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index ecde98d..ea362bd 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -6364,6 +6364,7 @@ trees_out::core_vals (tree t)
{
WT (((lang_tree_node *)t)->template_info.tmpl);
WT (((lang_tree_node *)t)->template_info.args);
+ WT (((lang_tree_node *)t)->template_info.partial);
const auto *ac = (((lang_tree_node *)t)
->template_info.deferred_access_checks);
@@ -6851,6 +6852,7 @@ trees_in::core_vals (tree t)
case TEMPLATE_INFO:
RT (((lang_tree_node *)t)->template_info.tmpl);
RT (((lang_tree_node *)t)->template_info.args);
+ RT (((lang_tree_node *)t)->template_info.partial);
if (unsigned len = u ())
{
auto &ac = (((lang_tree_node *)t)
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 9501050..5e2b5cb 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -34352,9 +34352,9 @@ specialization_of (tree type)
/* Determine the template or its partial specialization to which TYPE
corresponds. */
- if (tree spec = most_specialized_partial_spec (type, tf_none))
- if (spec != error_mark_node)
- ret = TREE_TYPE (TREE_VALUE (spec));
+ if (tree ti = most_specialized_partial_spec (type, tf_none))
+ if (ti != error_mark_node)
+ ret = TREE_TYPE (TI_TEMPLATE (ti));
if (ret == type)
ret = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (type);
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index ec2753e..2b2c598 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -5410,6 +5410,9 @@ process_partial_specialization (tree decl)
= tree_cons (specargs, tmpl,
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+ /* Link the DECL_TEMPLATE_RESULT back to the partial TEMPLATE_DECL. */
+ gcc_checking_assert (!TI_PARTIAL_INFO (tinfo));
+ TI_PARTIAL_INFO (tinfo) = build_template_info (tmpl, NULL_TREE);
for (inst = DECL_TEMPLATE_INSTANTIATIONS (maintmpl); inst;
inst = TREE_CHAIN (inst))
@@ -5420,16 +5423,17 @@ process_partial_specialization (tree decl)
&& CLASSTYPE_IMPLICIT_INSTANTIATION (instance))
: DECL_TEMPLATE_INSTANTIATION (instance))
{
- tree spec = most_specialized_partial_spec (instance, tf_none);
+ tree partial_ti = most_specialized_partial_spec (instance, tf_none,
+ /*rechecking=*/true);
tree inst_decl = (DECL_P (instance)
? instance : TYPE_NAME (instance));
- if (!spec)
+ if (!partial_ti)
/* OK */;
- else if (spec == error_mark_node)
+ else if (partial_ti == error_mark_node)
permerror (input_location,
"declaration of %qD ambiguates earlier template "
"instantiation for %qD", decl, inst_decl);
- else if (TREE_VALUE (spec) == tmpl)
+ else if (TI_TEMPLATE (partial_ti) == tmpl)
permerror (input_location,
"partial specialization of %qD after instantiation "
"of %qD", decl, inst_decl);
@@ -12107,8 +12111,8 @@ instantiate_class_template (tree type)
and supposing that we are instantiating S<int*>, ARGS will
presently be {int*} -- but we need {int}. */
- pattern = TREE_TYPE (t);
- args = TREE_PURPOSE (t);
+ pattern = TREE_TYPE (TI_TEMPLATE (t));
+ args = TI_ARGS (t);
}
else
{
@@ -22080,6 +22084,7 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
tree pattern = DECL_TEMPLATE_RESULT (gen_tmpl);
+ tree partial_ti = NULL_TREE;
fndecl = NULL_TREE;
if (VAR_P (pattern))
{
@@ -22087,13 +22092,13 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
specialization now, because the type of the variable could be
different. */
tree tid = build2 (TEMPLATE_ID_EXPR, NULL_TREE, tmpl, targ_ptr);
- tree elt = most_specialized_partial_spec (tid, complain);
- if (elt == error_mark_node)
+ partial_ti = most_specialized_partial_spec (tid, complain);
+ if (partial_ti == error_mark_node)
pattern = error_mark_node;
- else if (elt)
+ else if (partial_ti)
{
- tree partial_tmpl = TREE_VALUE (elt);
- tree partial_args = TREE_PURPOSE (elt);
+ tree partial_tmpl = TI_TEMPLATE (partial_ti);
+ tree partial_args = TI_ARGS (partial_ti);
tree partial_pat = DECL_TEMPLATE_RESULT (partial_tmpl);
fndecl = tsubst (partial_pat, partial_args, complain, gen_tmpl);
}
@@ -22116,6 +22121,10 @@ instantiate_template (tree tmpl, tree orig_args, tsubst_flags_t complain)
template, not the most general template. */
DECL_TI_TEMPLATE (fndecl) = tmpl;
DECL_TI_ARGS (fndecl) = targ_ptr;
+ if (VAR_P (pattern))
+ /* Now that we we've formed this variable template specialization,
+ remember the result of most_specialized_partial_spec for it. */
+ TI_PARTIAL_INFO (DECL_TEMPLATE_INFO (fndecl)) = partial_ti;
set_instantiating_module (fndecl);
@@ -25982,10 +25991,12 @@ most_general_template (tree decl)
/* Return the most specialized of the template partial specializations
which can produce TARGET, a specialization of some class or variable
- template. The value returned is actually a TREE_LIST; the TREE_VALUE is
- a TEMPLATE_DECL node corresponding to the partial specialization, while
- the TREE_PURPOSE is the set of template arguments that must be
- substituted into the template pattern in order to generate TARGET.
+ template. The value returned is a TEMPLATE_INFO; the TI_TEMPLATE is a
+ TEMPLATE_DECL node corresponding to the partial specialization, while
+ the TI_ARGS is the set of template arguments that must be substituted
+ into the template pattern in order to generate TARGET. The result is
+ cached in the TI_PARTIAL_INFO of the corresponding TEMPLATE_INFO unless
+ RECHECKING is true.
If the choice of partial specialization is ambiguous, a diagnostic
is issued, and the error_mark_node is returned. If there are no
@@ -25993,12 +26004,14 @@ most_general_template (tree decl)
returned, indicating that the primary template should be used. */
tree
-most_specialized_partial_spec (tree target, tsubst_flags_t complain)
+most_specialized_partial_spec (tree target, tsubst_flags_t complain,
+ bool rechecking /* = false */)
{
+ tree tinfo = NULL_TREE;
tree tmpl, args, decl;
if (TYPE_P (target))
{
- tree tinfo = CLASSTYPE_TEMPLATE_INFO (target);
+ tinfo = CLASSTYPE_TEMPLATE_INFO (target);
tmpl = TI_TEMPLATE (tinfo);
args = TI_ARGS (tinfo);
decl = TYPE_NAME (target);
@@ -26011,7 +26024,7 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain)
}
else if (VAR_P (target))
{
- tree tinfo = DECL_TEMPLATE_INFO (target);
+ tinfo = DECL_TEMPLATE_INFO (target);
tmpl = TI_TEMPLATE (tinfo);
args = TI_ARGS (tinfo);
decl = target;
@@ -26019,6 +26032,14 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain)
else
gcc_unreachable ();
+ if (!PRIMARY_TEMPLATE_P (tmpl))
+ return NULL_TREE;
+
+ if (!rechecking
+ && tinfo
+ && (VAR_P (target) || COMPLETE_TYPE_P (target)))
+ return TI_PARTIAL_INFO (tinfo);
+
tree main_tmpl = most_general_template (tmpl);
tree specs = DECL_TEMPLATE_SPECIALIZATIONS (main_tmpl);
if (!specs)
@@ -26068,10 +26089,7 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain)
/* Keep the candidate only if its constraints are satisfied. */
if (constraints_satisfied_p (ospec_tmpl, spec_args))
- {
- list = tree_cons (spec_args, ospec_tmpl, list);
- TREE_TYPE (list) = TREE_TYPE (t);
- }
+ list = tree_cons (spec_args, ospec_tmpl, list);
}
}
@@ -26133,7 +26151,10 @@ most_specialized_partial_spec (tree target, tsubst_flags_t complain)
return error_mark_node;
}
- return champ;
+ tree result = build_template_info (TREE_VALUE (champ), TREE_PURPOSE (champ));
+ if (!rechecking && tinfo)
+ TI_PARTIAL_INFO (tinfo) = result;
+ return result;
}
/* Explicitly instantiate DECL. */
@@ -27025,11 +27046,11 @@ instantiate_decl (tree d, bool defer_ok, bool expl_inst_class_mem_p)
if (variable_template_specialization_p (d))
{
/* Look up an explicit specialization, if any. */
- tree elt = most_specialized_partial_spec (d, tf_warning_or_error);
- if (elt && elt != error_mark_node)
+ tree partial_ti = most_specialized_partial_spec (d, tf_warning_or_error);
+ if (partial_ti && partial_ti != error_mark_node)
{
- td = TREE_VALUE (elt);
- args = TREE_PURPOSE (elt);
+ td = TI_TEMPLATE (partial_ti);
+ args = TI_ARGS (partial_ti);
}
}
diff --git a/gcc/cp/ptree.cc b/gcc/cp/ptree.cc
index e9b5066..33af7b8 100644
--- a/gcc/cp/ptree.cc
+++ b/gcc/cp/ptree.cc
@@ -346,6 +346,9 @@ cxx_print_xnode (FILE *file, tree node, int indent)
case TEMPLATE_INFO:
print_node (file, "template", TI_TEMPLATE (node), indent+4);
print_node (file, "args", TI_ARGS (node), indent+4);
+ if (TI_TEMPLATE (node)
+ && PRIMARY_TEMPLATE_P (TI_TEMPLATE (node)))
+ print_node (file, "partial", TI_PARTIAL_INFO (node), indent+4);
if (TI_PENDING_TEMPLATE_FLAG (node))
{
indent_to (file, indent + 3);