This patch re-implements explicit instantiation and specialization.
The latter isn't fully tested just yet, but it's close.
Constraints for explicit instantiations and specializations are
deduced from their candidates, not explicitly specified as part of the
declaration.
2014-08-13 Andrew Sutton
Implement deduction-based explicit instantiation and specialization.
* gcc/cp/call.c (joust): Allow all non-templates to be ordered by
constraints.
* gcc/cp/pt.c (get_class_bindings): Remove superfluous parameter and
move constraint check into most_specialized_class.
(most_constrained_function): Order functions with the same signatures
by their constraints.
(determine_specialization): Candidates must satisfy constraints. Also,
order non-template candidates by constraints. Improve diagnostics
for instances where candidates are rejected.
(more_specialized_inst): New. Compare function templates.
(most_specialized_instantiation): Refactor to use
more_specialized_inst and order by constraints.
(most_specialized_class): Candidates must satisfy constraints.
* gcc/cp/decl.c (various) Cosmetic fixes.
(adjust_fn_constraints): Rewrite so that class template constraints
are not imposed on member function declarations.
* gcc/testsuite/g++.dg/concepts: New tests.
Andrew Sutton
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c (revision 213909)
+++ gcc/cp/decl.c (working copy)
@@ -991,11 +991,6 @@ decls_match (tree newdecl, tree olddecl)
if (t1 != t2)
return 0;
- // Normal functions can be constraind. Two functions with the
- // same type and different constraints are different functions.
- tree c1 = get_constraints (newdecl);
- tree c2 = get_constraints (olddecl);
-
if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
&& ! (DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl)))
@@ -1014,6 +1009,11 @@ decls_match (tree newdecl, tree olddecl)
type for declaration matching. */
r2 = fndecl_declared_return_type (olddecl);
+ // Normal functions can be constraind. Two functions with the
+ // same type and different constraints are different functions.
+ tree c1 = get_constraints (newdecl);
+ tree c2 = get_constraints (olddecl);
+
if (same_type_p (TREE_TYPE (f1), r2))
{
if (!prototype_p (f2) && DECL_EXTERN_C_P (olddecl)
@@ -1041,7 +1041,7 @@ decls_match (tree newdecl, tree olddecl)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
#endif
- else {
+ else
types_match =
compparms (p1, p2)
&& type_memfn_rqual (f1) == type_memfn_rqual (f2)
@@ -1049,7 +1049,6 @@ decls_match (tree newdecl, tree olddecl)
&& (TYPE_ATTRIBUTES (TREE_TYPE (newdecl)) == NULL_TREE
|| comp_type_attributes (TREE_TYPE (newdecl),
TREE_TYPE (olddecl)) != 0);
- }
}
else
types_match = 0;
@@ -7564,24 +7563,54 @@ get_leading_constraints ()
// parameter list. The adjustment makes them part of the current
// template requirements.
static void
-adjust_out_of_class_fn_requirements (tree ctype)
+adjust_fn_constraints (tree ctype)
{
+ // When grokking a member function template, we are processing
+ // template decl at a depth greater than that of the member's
+ // enclosing class. That is, this case corresponds to the
+ // following declarations:
+ //
+ //template
+ //struct S {
+ // template void f(U);
+ //};
+ //
+ //template template void S::f(U) { }
+ //
+ // In both decls, the constraint D is not the current leading
+ // constraint. Make it so.
+ //
+ // Note that for normal member functions, there are no leading
+ // requirements we need to gather.
if (ctype && processing_template_decl > template_class_depth (ctype))
{
if (tree ci = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
{
+ // TODO: When do I ever have leading requirements for a
+ // member function template?
tree reqs = CI_LEADING_REQS (ci);
if (reqs && !get_leading_constraints ())
current_template_reqs = save_leading_constraints (reqs);
}
}
- else if (current_template_parms)
+
+ // Otherwise, this is just a regular function template. Like so:
+ //
+ //template void f();
+ //
+ // Note that the constraint C is not the current leading requirement
+ // at this point; it was stashed before the declarator was parsed.
+ // Make it the leading constraint.
+ else if (!ctype && current_template_parms)
{
if (tree ci = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms))
{
tree r1 = CI_LEADING_REQS (ci);
if (current_template_reqs)
{
+// TODO: As with above, when do I ever have leading
+// requirements that aren't part of the