Re: [c++-concepts] Class template constraints
Andrew Sutton writes: | Ok to commit? Attached is the doc fix patch. I'll send the TREE_TYPE | patch shortly. Yes, please -- that is what Jason earlier. Let me know when youve committed so that I can synchronize with trunk. -- Gaby
Re: [c++-concepts] Class template constraints
Ok to commit? Attached is the doc fix patch. I'll send the TREE_TYPE patch shortly. Andrew Andrew Sutton On Sat, Sep 7, 2013 at 1:00 PM, Jason Merrill wrote: > On 09/06/2013 12:03 PM, Andrew Sutton wrote: >> >> +// Returns the template type of the class scope being entered. If we're >> +// entering a constrained class scope. TMPL is the most general template >> +// of the scope being entered, and TYPE is its type. > > > TMPL is not part of the interface of fixup_template_type, so it should be > documented when it is declared rather than before the function. > > OK with that tweak. > >> + tree cur_constr = TREE_TYPE (parms); > > > In a separate patch, I'd like to use a different macro name for getting > constraints from template parms. > > Jason > templates-2.patch Description: Binary data
Re: [c++-concepts] Class template constraints
On 09/06/2013 12:03 PM, Andrew Sutton wrote: +// Returns the template type of the class scope being entered. If we're +// entering a constrained class scope. TMPL is the most general template +// of the scope being entered, and TYPE is its type. TMPL is not part of the interface of fixup_template_type, so it should be documented when it is declared rather than before the function. OK with that tweak. + tree cur_constr = TREE_TYPE (parms); In a separate patch, I'd like to use a different macro name for getting constraints from template parms. Jason
Re: [c++-concepts] Class template constraints
Updated as per comments. I moved the resolve_template_scope function out to finish_template_type. I couldn't figure out how to get the parsed template parameter from the looked-up template in lookup_class_template. That information may not be available outside the parse state. Andrew Andrew Sutton On Wed, Sep 4, 2013 at 3:49 PM, Jason Merrill wrote: > On 09/04/2013 01:33 PM, Andrew Sutton wrote: >> >> Ah. The goal is to check after we've deduced/coerced template >> arguments into a valid substitution. With functions, that's in >> fn_type_unification (hopefully called from instantiate_template) > > > Actually fn_type_unification calls instantiate_template, but yep, we're on > the same page. > > Jason > templates.patch Description: Binary data
Re: [c++-concepts] Class template constraints
On 09/04/2013 01:33 PM, Andrew Sutton wrote: Ah. The goal is to check after we've deduced/coerced template arguments into a valid substitution. With functions, that's in fn_type_unification (hopefully called from instantiate_template) Actually fn_type_unification calls instantiate_template, but yep, we're on the same page. Jason
Re: [c++-concepts] Class template constraints
>> It's not supposed to be different. Checking constraints in >> instantiate_template is actually too late. We want to check before >> instantiation, at the point of use. > > Right, what I was getting at is that instantiate_template actually only > instantiates the declaration of a function, not the definition, so it > corresponds to lookup_template_class for class templates. Ah. The goal is to check after we've deduced/coerced template arguments into a valid substitution. With functions, that's in fn_type_unification (hopefully called from instantiate_template), and for classes in lookup_template_class. There are some other places too: get_class_bindings for partial specializations, and determine_specialization for explicit specializations. > Oh, did the comment just mean that absence is equivalent to absence? I > thought the comment was saying that absence is considered equivalent to > anything else. Just tweak the comment, then. Sounds good. Andrew
Re: [c++-concepts] Class template constraints
On 09/04/2013 11:59 AM, Andrew Sutton wrote: It's not supposed to be different. Checking constraints in instantiate_template is actually too late. We want to check before instantiation, at the point of use. Right, what I was getting at is that instantiate_template actually only instantiates the declaration of a function, not the definition, so it corresponds to lookup_template_class for class templates. instantiate_decl is what actually instantiates the body. Confusing internal function naming. I think that the absence of constraints fits into those definition nicely, since it represents the empty set of propositions. Oh, did the comment just mean that absence is equivalent to absence? I thought the comment was saying that absence is considered equivalent to anything else. Just tweak the comment, then. Jason
Re: [c++-concepts] Class template constraints
>> 1. Type constraints are checked on lookup rather than instantiation. > > > How is this different from function template constraints? Is this just a > difference in internal function name (instantiate_template vs > lookup_template_class)? It's not supposed to be different. Checking constraints in instantiate_template is actually too late. We want to check before instantiation, at the point of use. This also means we don't need complete types to check constraints. So this: template struct X; X* x; Should fail and does. This change also makes it impossible to have partial specializations that are more general than the primary template. Checking in lookup_class_template does not consult the specializations. Constraints on partial specializations are checked in most_specialized_class (or one of its subroutines). > >> +// Returns the type of a template specialization only if that >> +// specializaiton needs to defined. Otherwise (e.g., if the type has > > > specialization > >> + // Do the constraints match the most general template? Note that >> + // the absence of constraints will also match. >> + if (equivalent_constraints (cur_constr, DECL_CONSTRAINTS (tmpl))) > > > If absence matches, I think the name "equivalent" is misleading. But the > implementation seems to require subsumes in both directions. What's up > here? Subsumption is essentially computing an implication between constraints, so that if P subsumes Q, you could also say that P => Q. Checking in both directions gives P => Q and Q => P, or P <=> Q, which is logical equivalence. I think that the absence of constraints fits into those definition nicely, since it represents the empty set of propositions. >> + // Find the template parameter list at the a depth appropriate to >> + // the scope we're trying to enter. >> + tree parms = current_template_parms; >> + int depth = template_class_depth (type); >> + for (int n = processing_template_decl; n > depth && parms; --n) >> +parms = TREE_CHAIN (parms); > > > If you're going to use this function from lookup_template_class_1, it can't > use current_template_*, since those are parser state which might be > something completely unrelated when we get here during instantiation. I was worried about that. I'm not sure how this gets invoked during instantiation. I'll look at it. -- Andrew Sutton andrew.n.sut...@gmail.com
Re: [c++-concepts] Class template constraints
On 09/03/2013 11:01 AM, Andrew Sutton wrote: Attached is a patch for constrained class templates. It's the 3rd time I've sent it. Please feel free to ping me if you're waiting for a patch review; once a week is not too much. 1. Type constraints are checked on lookup rather than instantiation. How is this different from function template constraints? Is this just a difference in internal function name (instantiate_template vs lookup_template_class)? +// Returns the type of a template specialization only if that +// specializaiton needs to defined. Otherwise (e.g., if the type has specialization + // Do the constraints match the most general template? Note that + // the absence of constraints will also match. + if (equivalent_constraints (cur_constr, DECL_CONSTRAINTS (tmpl))) If absence matches, I think the name "equivalent" is misleading. But the implementation seems to require subsumes in both directions. What's up here? + // Find the template parameter list at the a depth appropriate to + // the scope we're trying to enter. + tree parms = current_template_parms; + int depth = template_class_depth (type); + for (int n = processing_template_decl; n > depth && parms; --n) +parms = TREE_CHAIN (parms); If you're going to use this function from lookup_template_class_1, it can't use current_template_*, since those are parser state which might be something completely unrelated when we get here during instantiation. +return resolve_template_scope(gen_tmpl, template_type); Space before (. + // Diaagnose constraints here since they are not diagnosed Extra 'a'. + // If not, it is equivalent to have failed to compute the binding. "to having failed" Jason
[c++-concepts] Class template constraints
Attached is a patch for constrained class templates. It's the 3rd time I've sent it. I added some fixes for bugs discovered after the previous send, and added support for matching constrained declarations in out-of-class member function definitions. 2013-08-02 Andrew Sutton * gcc/cp/pt.c (get_class_bindings): Pass the partial specialization for constraint evaluation. Evaluate constraints, resulting in deduction failure on error. (get_specializaing_template_decl), (get_specialization_constraints), (maybe_new_partial_specialization): New. (maybe_process_partial_specialization): Allow the creation of new types for constrained partial specializations. (process_partial_specialization): Modify the canonical type of constrained partial specializations. (resolve_template_scope): New. Match the template scope to a specialization with appropriate constraints. (lookup_template_class_1): Compare constraints when entering a template scope. Check constraints on lookup. Do not explicitly check alias constraints. (instantiate_class_template_1): Do not explicitly check constraints during class template instantiation. (tsubst_decl): Instantiate the constraints of template declarations. (more_specialized_class): Pass specializations to get_class_bindings(). Compare specialization constraints if the types are equivalent. (most_specialized_class): Pass specialization to get_class_bndings(). * gcc/cp/decl2.c (check_class_fn): Get the decl's requirements from either the current template reqs or from the template parameters. Allow overloading of constrained out-of-class member definitions. * gcc/cp/parser.c (cp_parser_parse_type_parameter): Attach requirements to the current template parameter list. (cp_parser_init_declarator): Parse requires clauses for out-of-class member definitions. Be sure to restore current constraints before exiting the function. (cp_parser_member_declarator): Restore the previous requirements in an early-exit branch. (cp_parser_late_parsing_for_member): Restore constraints after maybe_end_member_template_processing(). (cp_parser_template_declaration_after_exp): Attach constraints to the current template parameters. * gcc/cp/constraint.cc (reduce_template_id): Don't crash when omitting ()'s on constraint calls. (check_requirements): Don't evaluate dependent arguments. (check_constraints): Don't try to evaluate when arguments are dependent. (equivalent_constraints): Optimize the case when a and b are the same constraints. -- Andrew Sutton template.patch Description: Binary data
[c++-concepts] class template constraints
Attached is a patch that deals with class template constraints. In particular, it does 3 things: 1. Type constraints are checked on lookup rather than instantiation. 2. Initial support for constrained out-of-class definitions is added (more work needed) 3. Support for constrained partial template specialization is added. Change Log: 2013-08-02 Andrew Sutton * gcc/cp/pt.c (get_class_bindings): Pass the partial specialization for constraint evaluation. Evaluate constraints, resulting in deduction failure on error. (get_specializaing_template_decl), (get_specialization_constraints), (maybe_new_partial_specialization): New. (maybe_process_partial_specialization): Allow the creation of new types for constrained partial specializations. (process_partial_specialization): Modify the canonical type of constrained partial specializations. (lookup_template_class_1): Check constraints on lookup. Do not explicitly check alias constraints. (instantiate_class_template_1): Do not explicitly check constraints during class template instantiation. (more_specialized_class): Pass specializations to get_class_bindings(). Compare specialization constraints if the types are equivalent. (most_specialized_class): Pass specialization to get_class_bndings(). * gcc/cp/constraint.cc (reduce_template_id): Don't crash when omitting ()'s on constraint calls. (check_constraints): Don't try to evaluate when arguments are dependent. (equivalent_constraints): Optimize the case when a and b are the same constraints. * gcc/cp/decl2.c (check_class_fn): Allow overloading of constrained out-of-class member definitions. * gcc/cp/parser.c (cp_parser_init_declarator): Parse requires clauses for out-of-class member definitions. Be sure to restore current constraints before exiting the function. (cp_parser_late_parsing_for_member): Restore constraints after maybe_end_member_template_processing(). Andrew template-1.patch Description: Binary data
[c++-concepts] class template constraints
I changed the method by which class (and alias) template constraints are checked. Rather than waiting until instantiation, they are now checked after computing the binding in lookup_class template. Actually, after the hashtable lookup so we don't re-check constraints for previously instantiated specializations. Previously, this was allowed: vector* p; Assuming that vector restricted its arguments to only object types. The program is ill-formed if vector is ever instantiated. This patch causes formation of the type vector to result in an error. Changelog: 2013-06-25 Andrew Sutton * gcc/cp/constraint.cc (check_constraints): Don't check against dependent arguments. Just return true. * gcc/cp/ptr.c (lookup_class_template_1): Check template constraints and diagnose failures. Removing specific check for alias templates. (instantiate_class_template_1): Remove constraints check during template instantiation. Andrew class.patch Description: Binary data