[PATCH] Diagnose hard errors during constraint satisfaction

2019-11-13 Thread Andrew Sutton
This changes the diagnostic of non-boolean constraints and rvalue
conversion failures in constraint satisfaction into hard errors. I
also cleaned up the satisfaction routines to reduce the number of
functions involved.

Jason, this is a squashed version of the patches I sent earlier today.

This patch also fixes the crash PR92439, which was caused by not
building the normalization tree in satisfy_constraint_expression.
However, there are some other problems with that example that cause it
to not compile (e.g., non-boolean atomic constraints).

Andrew Sutton


0001-Diagnose-certain-constraint-errors-as-hard-errors.patch
Description: Binary data


[PATCH] PR c++/92403

2019-11-13 Thread Andrew Sutton
Suppress diagnostics when substituting into requires-expressions
outside of concept definitions.

This change broke one existing test, which I've updated to match the
behavior of the current patch. Specifically, it changed the case
below:

template
constexpr bool subst = true;

template
constexpr bool test()
{
  if constexpr (requires { requires subst; }) // error?
return true;
  else
return false;
}

static_assert(!test());

Before, the program is ill-formed as a result of substituting void for
U. After applying, the requirement is false. If you replace the
requires-expression with a concept (either before or after the patch),
you get false. So, this seems like the right behavior.

Andrew Sutton


0001-Suppress-diagnostics-substituting-into-a-requires-ex.patch
Description: Binary data


[c++-concepts] Class template constraints

2013-09-03 Thread Andrew Sutton
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


Re: [c++-concepts] Class template constraints

2013-09-04 Thread Andrew Sutton
>> 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

2013-09-04 Thread Andrew Sutton
>> 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

2013-09-06 Thread Andrew Sutton
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

2013-09-09 Thread Andrew Sutton
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


[c++-concepts] pretty print fix

2013-09-09 Thread Andrew Sutton
The last merge didn't compile for me. Apparently some pretty printing
functions have disappeared that were being called in the concept
stuff. This patch just replaces the broken calls to pp_cxx_type_id
with pp->type_id.

Ok to commit?

Andrew Sutton


fix.patch
Description: Binary data


[c++-concepts] template parameter constraints

2013-09-10 Thread Andrew Sutton
I added a new macro to replace the use of TREE_TYPE to get
constraints. It's called TEMPLATE_PARMS_CONSTRAINTS. Patch attached:

2013-09-10  Andrew Sutton  
* gcc/cp/cp-tree.h (TEMPLATE_PARMS_CONSTRAINTS): New.
* gcc/cp/parser.c (cp_parser_template_declaration_after_export),
(cp_parser_type_parameter): Use TEMPLATE_PARMS_CONSTRAINTS.
* gcc/cp/semantics.c (fixup_template_scope): Use
 TEMPLATE_PARMS_CONSTRAINTS.


Andrew Sutton


template-parms.patch
Description: Binary data


Re: [c++-concepts] template parameter constraints

2013-09-10 Thread Andrew Sutton
Will amend and commit tomorrow morning!

Andrew
Andrew Sutton


On Tue, Sep 10, 2013 at 7:54 PM, Gabriel Dos Reis  wrote:
> Andrew Sutton  writes:
>
> | I added a new macro to replace the use of TREE_TYPE to get
> | constraints. It's called TEMPLATE_PARMS_CONSTRAINTS. Patch attached:
> |
> | 2013-09-10  Andrew Sutton  
> | * gcc/cp/cp-tree.h (TEMPLATE_PARMS_CONSTRAINTS): New.
> | * gcc/cp/parser.c (cp_parser_template_declaration_after_export),
> | (cp_parser_type_parameter): Use TEMPLATE_PARMS_CONSTRAINTS.
> | * gcc/cp/semantics.c (fixup_template_scope): Use
> |  TEMPLATE_PARMS_CONSTRAINTS.
>
> | +// Access template constraints associated with the template
> | +// parameter lists. Template parameter constraints are stored in
> | +// the TREE_TYPE of list.
>
> Hmm, we can have several levels of template parameter list.  What about:
>
>   // Logical constraints on the template parameters introduced at a
>   // given template parameter list level indicated by NODE.
>
> Patch OK with that change.
>
> Thanks,
>
> -- Gaby


[c++-concepts] Constrained friends

2013-09-13 Thread Andrew Sutton
This patch implements semantics for constrained friend templates and
classes. The only significant changes are in determine_specializaiton
and check_constrained_friend.

Unless a friend function is defined, a constraints on friend
declarations are never actually checked. The checking happens during
overload resolution against the actual (non-friend) declarations.

The change to determine_specialization is interesting. We have cases
where a programmer has written an explicit specialization and it's
being matched to a template. Previously, if constraints were not
satisfied, we would not record the template as a candidate. However,
this causes errors in class template instantiation if there are
constrained friend declarations whose constraints are not satisfied
("no matching template declaration").

With this patch, we defer constraints checks until we've selected the
best template for the specialization. And then we only check the
constraints if the declaration is a non-friend.

2013-09-13  Andrew Sutton  
* gcc/cp/cp-tree.h (check_constrained_friend): New.
* gcc/cp/pt.c (determine_specialization): Only check constraints
after determining which template the declaraiton is a specialization
of. Don't check constraints for friends during class template
instantiation.
(fn_type_unification): New parameter to determine if constraints
should be checked.
(more_specialized_class): Update for interface change.
(get_bindings): New parameter to determine if constraints should
be checked during fn_type_unification. New overload that checks
constraints by default.
* gcc/cp/parser.c (cp_parser_member_declaration): Check constrained
friends after parsing.
* gcc/cp/class.c (resolve_address_of_overloaded_function): Update
for interface change.
* gcc/cp/call.c (is_non_template_friend): New.
(add_function_candidate): Check constraints on constrained friend
templates.
(add_template_candidate_real): Update for interface change.
* gcc/cp/constraint.c (check_constrained_friend): New.


Andrew Sutton


friends.patch
Description: Binary data


Re: [c++-concepts] Constrained friends

2013-09-21 Thread Andrew Sutton
I'm going to rewrite this patch tomorrow morning. The semantics aren't
quite right --- they should be simpler.

>> Previously, if constraints were not
>> satisfied, we would not record the template as a candidate. However,
>> this causes errors in class template instantiation if there are
>> constrained friend declarations whose constraints are not satisfied
>> ("no matching template declaration").
>
> Is that wrong?  We normally give errors about friend declarations that don't
> match any template.  Why don't we want this error when the friend
> declaration is looking for a constrained template?

It is wrong, but not for the reasons I gave. This only happens when
you try to constrain a friend function that declares a specialization,
which happens to be completely separate from the previously declared
template.

I'm going to disallow the ability to declare constrained friend
specializations. They don't really make sense.

>> +  if (is_non_template_member_fn (fn) || is_non_template_friend (fn))
>
>
> Let's have one predicate instead of two; the condition here is a temploid
> that is not a specialization of a primary template.

Agreed.

>
>> +  if (!check_template_constraints (tmpl, args) && (complain &
>> tf_error))
>>  {
>>reason = template_constraint_failure (tmpl, args);
>>viable = false;
>
>
> Why add the complain check?  A constraint failure should make a candidate
> non-viable even in SFINAE context.

What have I done? That's awful...


>> +  // If we're not instantiating a friend function, then we need to
>> +  // ensure the specialization of the best template satisfies its
>> +  // constraints.
>
>
> Surely we need to check constraints in the earlier loop, so that we don't
> treat as a candidate a template that doesn't satisfy the constraints;
> otherwise if we have two templates
>
> template  T f(T) requires Thing;
> template  T* f(T*);
>
> and our specialization requires Thing, we would select the second (because
> it is otherwise more specialized) and then give an error about constraint
> mismatch; I would think we want to select the first.

I believe that's what the previous version did, and we'll go back to
that. This change was part of the semantics that I didn't get right.

>> +// If there is an overload with the same type and
>> +// constraints, then this is a good declaration.
>> +if (same_type_p (TREE_TYPE (fn), TREE_TYPE (f)))
>> +  if (equivalent_constraints (constr, get_constraints (f)))
>> +return;
>
>
> It seems that this will only allow friend declarations that match the
> template exactly, not friend declarations that are more specialized than the
> matching template.  It looks like you're trying to implement a subset of
> determine_specialization here, which I think is a mistake.

I agree. It's a mistake. This is also related to the semantics that I got wrong.

Effectively, the only changes needed for constrained friends are that:

a) you can't constrain non-dependent friends
b) you can't constraint non-template friend functions that declare a
specialization
and c) that we check non-template friends the same way as non-template
member fns

There should be no changes to any of the rules for determining specializations.

Andrew


[c++-concepts] constrained friends redux

2013-10-02 Thread Andrew Sutton
This patch implements constrained friends and disallows declarations
of constrained friend template specialization.

There was a previous question about whether I was doing the right
thing in determine_specialization. I'm looking at that issue
separately.

2013-10-01  Andrew Sutton  
* gcc/cp/parser.c (cp_parser_member_declaration): Check that
a constrained friend definition is valid.
* gcc/cp/decl.c (grokfndecl): Disallow constrained friend template
specializations.
* gcc/cp/constraints.cc (check_constrained_friend): New.
* gcc/cp/typeck.c (cp_build_function_call_vec): Diagnose constraints
in the presence of the failure of a single candidate.
* gcc/cp/cp-tree.h (check_constrained_friend): New.
* gcc/cp/call.c (is_non_template_member_fn): Make inline.
(is_non_template_friend), (is_constrainable_non_template_fn): New.
(add_function_candidate): Predicate check on
is_constrainable_non_template_fn.

Andrew Sutton


friends-2.patch
Description: Binary data


Re: [c++-concepts] constrained friends redux

2013-10-04 Thread Andrew Sutton
>> +  // Do not permit the declaration of constrained friend
>> +  // function declarations. They cannot be instantiated since
>> +  // the resulting declaration would never match the definition,
>> +  // which must be a non-template and cannot be constrained.
>
>
> You're in the template-id code here, so "must be a non-template" is
> confusing:
>
> template  void f();
>
> struct A {
>   friend void f(); // matches a template
> };
>
> Perhaps you mean that it must match a fully-instantiated function, so any
> constraints on the templates were considered during
> determine_specialization.

This seems like a simple comment fix, but there's a longer explanation
of what I want (see below). Would this be more appropriate?

  // Do not allow constrained friend template specializations.

The intent is stronger than to say it must match something. I don't
want to allow any declarations of the form

template
struct X {
  friend void f<>(T x) requires C; // Error.
};

This should never even get to determine_specialization since the
original declaration is never actually pushed.

We could use those constraints to match the specialization to one of
several constrained overloads, as you mentioned earlier, but I'd
rather avoid that for now. Solving that problem in general would
require that we allow constrained (explicit) specializations and
define a method of matching instantiated constraints to dependent
constraints, and that we do so as an alternative to the usual
constraint checking during template argument deduction.

Maybe it's a useful feature, but it's really hard to gauge how much
use it would actually get. We can always revisit that in the future.
Somebody else can write that paper :)

Andrew


Re: [c++-concepts] constrained friends redux

2013-10-04 Thread Andrew Sutton
>>> >Perhaps you mean that it must match a fully-instantiated function, so
>>> > any
>>> >constraints on the templates were considered during
>>> >determine_specialization.
>
>
>> This seems like a simple comment fix, but there's a longer explanation
>> of what I want (see below). Would this be more appropriate?
>>
>>// Do not allow constrained friend template specializations.
>>
>> The intent is stronger than to say it must match something.
>
>
> By "must" I meant that whatever it matches could only be a
> fully-instantiated function.


I see what you mean. I was caught up in the wrong part of the
sentence.. But yes, that's right.

> But I guess the main reason for disallowing constraints here is the same as
> for explicit specializations and non-template functions; non-dependent
> constraints don't really make any sense.

That's the intent.

Okay to commit?

Andrew


friends-3.patch
Description: Binary data


[c++-concepts] friends regression

2013-10-07 Thread Andrew Sutton
The last patch introduced a regression. This ensures that we don't
generate false positives diagnosing errors in non-template contexts.

2013-10-07  Andrew Sutton  
* gcc/cp/cp-tree.h (check_constrained_friend): Take requirements as
an argument.
* gcc/cp/constraints.cc (check_constrained_friend): Do not diagnose
errors in unconstrained friend declarations.
* gcc/cp/parser.cc (cp_parser_member_declaration): Pass current
requirements to check_constrained_friend.

Andrew Sutton


friends-4.patch
Description: Binary data


Re: [c++-concepts] friends regression

2013-10-08 Thread Andrew Sutton
No, any current_template_reqs are reset (set to null) before parsing
any trailing requirements and restored after the fact.

Andrew Sutton


On Mon, Oct 7, 2013 at 3:05 PM, Jason Merrill  wrote:
> OK.
>
> If we have a friend declaration inside a constrained partial specialization,
> will that still get a false positive?
>
> Jason


[c++-concepts] Shorthand notation

2013-10-16 Thread Andrew Sutton
I've committed initial support for shorthand constraints. This patch
adds support for parsing a concept-names as non-class names. When
introducing a template parameter, the concept name is transformed into
a constraint on the template parameter. Constrained parameters can
introduce type, non-type and template template parameters.

This has initial support for variadic constraints, but it's not well tested.

This patch does not yet support default arguments for constrained
template parameters, nor does it support the use of concept ids of
this form:

  template F>
void f();

There are a couple of interesting things in the patch. I'm using a
PLACEHOLDER_EXPR as a template argument in order to resolve constraint
names. Effectively, I deduce concepts by creating an expression like:

  Equality_comparable()

where ? is a placeholder, and after coerce_template_arguments
completes, I can extract the matched parameter from the placeholder.
This works nicely when concepts are overloaded or have default
arguments (although I'm not sure I'm testing that very thoroughly
right now).

With variadic constraints, I've had to add functionality to expand a
pack as a conjunction of requirements. For example, if you declare:

  template // Class() must be true for each T in Ts
void f();

The transformation is:

  template
requires Class()...
  void f();

Where Class()... expands to Class() && Class() && ... etc.
I feel like the current implementation is a bit hacky, and I'm
wondering if I should introduce a new node for a pack conjunction.

Change log follows.

2013-10-16  Andrew Sutton  
* gcc/cp/constraint.cc (conjoin_requiremens): New.
(resolve_constraint_check): Filter non-concept candidates before
coercing arguments. Perform deduction in a template-decl processing
context to prevent errors during diagnosis.
(finish_concept_name), (finish_shorthand_requirement),
(get_shorthand_requirements): New.
* gcc/cp/pt.c (template_parm_to_arg): Make non-static.
(process_templat_parm): Build shorthand requirements from the
parameter description.
(end_templat_parm_list): New.
(convert_placeholder_argument): New.
(convert_template_argument): Match placeholder arguments against
any template parameter.
(tsubst_pack_conjuction):  New.
(tsubst_expr): Expand a pack as a conjunction.
(type_dependent_expression_p): Placeholders are always type
dependent.
* gcc/cp/parser.c (cp_is_constrained_parameter),
(cp_finish_template_type_parm), (cp_finish_template_template_parm)
(cp_finish_non_type_template_parm), (cp_finish_constrined_parameter):
New.
(cp_parser_template_parameter): Handle constrained parameters.
(cp_parser_nonclass_name): An identifier naming an overload set
may declare a constrained parameter.
(cp_parser_type_parameter), (cp_parser_template_declaration_after_exp):
Get shorthand requirements from the tmeplate parameter list.
* gcc/cp/cp-tree.h (TEMPLATE_PARM_CONSTRAINTS): New.

Committed in 203704.

Andrew Sutton


Re: [c++-concepts] Shorthand notation

2013-10-18 Thread Andrew Sutton
A small follow up change. This removes the "sorry" from concept name
resolution. Committed in r203815.

2013-10-16  Andrew Sutton  
* gcc/cp/constraint.cc (finish_concept_name): Allow functions with
the same name as concepts to resolve as call expressions in the
usual way.

Andrew Sutton


On Wed, Oct 16, 2013 at 9:59 AM, Andrew Sutton
 wrote:
> I've committed initial support for shorthand constraints. This patch
> adds support for parsing a concept-names as non-class names. When
> introducing a template parameter, the concept name is transformed into
> a constraint on the template parameter. Constrained parameters can
> introduce type, non-type and template template parameters.
>
> This has initial support for variadic constraints, but it's not well tested.
>
> This patch does not yet support default arguments for constrained
> template parameters, nor does it support the use of concept ids of
> this form:
>
>   template F>
> void f();
>
> There are a couple of interesting things in the patch. I'm using a
> PLACEHOLDER_EXPR as a template argument in order to resolve constraint
> names. Effectively, I deduce concepts by creating an expression like:
>
>   Equality_comparable()
>
> where ? is a placeholder, and after coerce_template_arguments
> completes, I can extract the matched parameter from the placeholder.
> This works nicely when concepts are overloaded or have default
> arguments (although I'm not sure I'm testing that very thoroughly
> right now).
>
> With variadic constraints, I've had to add functionality to expand a
> pack as a conjunction of requirements. For example, if you declare:
>
>   template // Class() must be true for each T in Ts
> void f();
>
> The transformation is:
>
>   template
> requires Class()...
>   void f();
>
> Where Class()... expands to Class() && Class() && ... etc.
> I feel like the current implementation is a bit hacky, and I'm
> wondering if I should introduce a new node for a pack conjunction.
>
> Change log follows.
>
> 2013-10-16  Andrew Sutton  
> * gcc/cp/constraint.cc (conjoin_requiremens): New.
> (resolve_constraint_check): Filter non-concept candidates before
> coercing arguments. Perform deduction in a template-decl processing
> context to prevent errors during diagnosis.
> (finish_concept_name), (finish_shorthand_requirement),
> (get_shorthand_requirements): New.
> * gcc/cp/pt.c (template_parm_to_arg): Make non-static.
> (process_templat_parm): Build shorthand requirements from the
> parameter description.
> (end_templat_parm_list): New.
> (convert_placeholder_argument): New.
> (convert_template_argument): Match placeholder arguments against
> any template parameter.
> (tsubst_pack_conjuction):  New.
> (tsubst_expr): Expand a pack as a conjunction.
> (type_dependent_expression_p): Placeholders are always type
> dependent.
> * gcc/cp/parser.c (cp_is_constrained_parameter),
> (cp_finish_template_type_parm), (cp_finish_template_template_parm)
> (cp_finish_non_type_template_parm), (cp_finish_constrined_parameter):
> New.
> (cp_parser_template_parameter): Handle constrained parameters.
> (cp_parser_nonclass_name): An identifier naming an overload set
> may declare a constrained parameter.
> (cp_parser_type_parameter), 
> (cp_parser_template_declaration_after_exp):
> Get shorthand requirements from the tmeplate parameter list.
> * gcc/cp/cp-tree.h (TEMPLATE_PARM_CONSTRAINTS): New.
>
> Committed in 203704.
>
> Andrew Sutton


short-2.patch
Description: Binary data


Re: [c++-concepts] Shorthand notation

2013-10-18 Thread Andrew Sutton
I know. When I started working on the project, Gaby asked that I keep
all concept-related changes in the top-level Changelog.concepts with
full paths for the file names.

Andrew Sutton


On Fri, Oct 18, 2013 at 8:53 AM, Paolo Carlini  wrote:
> Hi,
>
>
> On 10/18/2013 02:23 PM, Andrew Sutton wrote:
>>
>> A small follow up change. This removes the "sorry" from concept name
>> resolution. Committed in r203815.
>>
>> 2013-10-16  Andrew Sutton  
>>  * gcc/cp/constraint.cc (finish_concept_name): Allow functions
>> with
>>  the same name as concepts to resolve as call expressions in the
>>  usual way.
>
> Nit: normally this would be just * constraint.cc, because the paths are
> relative to the location of the corresponding ChangeLog file (which is under
> gcc/cp)
>
> Thanks!
> Paolo.


[c++-concepts] Bugfix

2013-10-18 Thread Andrew Sutton
Fixing 2 issues. A test for __is_convertible_to was missing in
diagnose_trait, and *somehow* the logic for determining constraint
ordering w.r.t. requires expressions was missing.

Committed in 203826.

2013-10-16  Andrew Sutton  
* gcc/cp/logic.cc (left_requires), (decompose_left): Add
decomposition rules for requires expressions.
(subsumes_requires), (subsumes_prop): Add subsumption rules for
requires expressions.
* gcc/cp/constraint.cc (diagnose_trait): Diagnose failed conversion
requirements.

Andrew


[c++-concepts] bitfield reference bugfix

2013-10-22 Thread Andrew Sutton
This fixes the longstanding problem with bitfield references. The
default dialect was set to cxx1y, which was resulting different
conversions for bitfield references. I'm not sure if there's a change
in semantics for 1y or if that's a separate bug, but it's not related
to concepts.

Also prevent an ICE for invalid constrained friends.

2013-10-16  Andrew Sutton  
* gcc/c-family/c-common.c (cxx_dialect): Make the default
language C++11.
* gcc/cp/constraint.cc (check_constrained_friend): Don't assert
on error_mark_node.

Andrew


bugfix-2.patch
Description: Binary data


Re: [c++-concepts] small tidbits to get it to build

2013-10-23 Thread Andrew Sutton
Hi Ed,

It looks like we did reserve "assume" as a keyword, but it's not being
used... By any chance, did you configure without --disable-bootstrap?

I think it would be a better solution to remove the unused keywords --
there were a couple of others that we grabbed for some other
concepts-related work, but which aren't included in Concepts Lite.

I'll apply the typeck fix.

Andrew Sutton


On Tue, Oct 22, 2013 at 10:02 PM, Ed Smith-Rowland <3dw...@verizon.net> wrote:
> I had to get past two small bugs to get c++-concepts to build.
> Take a good look because I'm not sure if they're right.  The solutions
> should be harmless though.
>
> Ed
>


[c++-concepts] Specialization of concepts

2013-10-23 Thread Andrew Sutton
This patch disallows the explicit specialization of concepts, as
required by the specification. It also fixes an ICE when comparing
overloads of non-template members.

2013-10-23  Andrew Sutton  
* gcc/cp/class.c (get_member_fntemplate): New.
(are_constrained_member_overloads): Only get a template declaration
if the member function is, in fact, a template or temploid.
* gcc/cp/pt.c (check_explicit_specialization): Do not allow
explicit specializations to be declared 'concept', and do not allow
an explicit specialization of a concept.
* gcc/cp/decl.c (grokfndecl): Propagate the concept flag to
check_explicit_specialization.

Committed in r203970.

Andrew


bugfix-3.patch
Description: Binary data


Re: [c++-concepts] small tidbits to get it to build

2013-10-24 Thread Andrew Sutton
Hi Ed,

I committed half of your patch (the unused variable part) in r204011
and removed the unused keywords as a resolution for the other half in
r204012.

Changelog/patch follow:

2013-10-24  Andrew Sutton  
* gcc/cp/c-common.c (c_common_r): Remove unused keywords "assume",
"axiom", and "forall".
* gcc/cp/c-common.h (rid): Removed unused reserved word ids.

Andrew


On Wed, Oct 23, 2013 at 8:05 PM, Ed Smith-Rowland <3dw...@verizon.net> wrote:
> On 10/23/2013 08:36 AM, Andrew Sutton wrote:
>>
>> Hi Ed,
>>
>> It looks like we did reserve "assume" as a keyword, but it's not being
>> used... By any chance, did you configure without --disable-bootstrap?
>>
>> I think it would be a better solution to remove the unused keywords --
>> there were a couple of others that we grabbed for some other
>> concepts-related work, but which aren't included in Concepts Lite.
>>
>> I'll apply the typeck fix.
>>
>> Andrew Sutton
>>
>>
>> On Tue, Oct 22, 2013 at 10:02 PM, Ed Smith-Rowland <3dw...@verizon.net>
>> wrote:
>>>
>>> I had to get past two small bugs to get c++-concepts to build.
>>> Take a good look because I'm not sure if they're right.  The solutions
>>> should be harmless though.
>>>
>>> Ed
>>>
> I did this:
> $ ../gcc_concepts/configure --prefix=/home/ed/bin_concepts
> --enable-languages=c,c++,lto
>
> This is pretty base bones - no special treatment configure and the branch
> worked pretty well.
>
> Ed
>


keyword.patch
Description: Binary data


[c++-concepts] Requires expr in non-templte

2013-10-25 Thread Andrew Sutton
This patch prevents the use of requires expressions in non-template
scopes. This restriction was relaxed in the most recent version of
concepts lite, but the implementation requires some thought. For now,
I am marking it an error to make it consistent with previous versions
of the spec.

2013-10-25  Andrew Sutton  
* gcc/cp/parsre.c (cp_parser_requires_expression): Gracefully
fail when parsing a requires expr outside a template.

Andrew Sutton


template-requires.patch
Description: Binary data


[c++-concepts] Constrained scope bugfix

2013-10-30 Thread Andrew Sutton
Partially fixing a bug that caused lookup errors in valid programs. For example:

template
  pair::type void f(T, U); // Error, no such pair

When entering a template scope, we tried to match the template to one
having the same constraints. Obviously pair doesn't have Int and Float
constraints, and it probably doesn't have a partial specialization
with those constraints either.

I relaxed the fixup_template_type function so that it would just
return the looked-up type without emitting a diagnostic. This fix
makes the following a legal, however:

template
  struct S { void f(); }

template
  void S::f() { } // Should be an error

The right solution seems to be to diagnose the error only when
defining an out-of-class member by verifying that each template scope
in the qualified name matches a declaration with the same constraints.

2013-10-30  Andrew Sutton  
* gcc/cp/semantics.c (fixup_template_type): Don't emit errors when
no templates can be found with matching constraints.
Index: gcc/cp/semantics.c
===
--- gcc/cp/semantics.c	(revision 203626)
+++ gcc/cp/semantics.c	(working copy)
@@ -2847,8 +2847,35 @@ finish_template_decl (tree parms)
 
 // Returns the template type of the class scope being entered. If we're
 // entering a constrained class scope. TYPE is the class template
-// scope being entered. If TYPE is not a class-type (e.g. a typename type),
-// then no fixup is needed.
+// scope being entered and we may need to match the intended type with
+// a constrained specialization. For example:
+//
+//template
+//  struct S { void f(); }; #1
+//
+//template
+//  void S::f() { }  #2
+//
+// We check, in #2, that S refers precisely to the type declared by
+// #1 (i.e., that the constraints match). Note that the following should
+// be an error since there is no specialization of S that is 
+// unconstrained, but this is not diagnosed here.
+//
+//template
+//  void S::f() { }
+//
+// We cannot diagnose this problem here since this function also matches
+// qualified template names that are not part of a definition. For example:
+//
+//template
+//  typename pair::first_type void f(T, U);
+//
+// Here, it is unlikely that there is a partial specialization of
+// pair constrained for for Integral and Floating_point arguments.
+//
+// The general rule is: if a constrained specialization with matching
+// constraints is found return that type. Alos note that if TYPE is not a 
+// class-type (e.g. a typename type), then no fixup is needed.
 static tree
 fixup_template_type (tree type)
 {
@@ -2866,14 +2893,8 @@ fixup_template_type (tree type)
 return type;
   tree cur_constr = TEMPLATE_PARMS_CONSTRAINTS (parms);
 
-  // Do the constraints match those of the most general template? 
-  // If the constraints are NULL_TREE, this will match the most general
-  // template iff it is unconstrained.
+  // Search for a specialization whose constraints match.
   tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
-  if (equivalent_constraints (cur_constr, DECL_CONSTRAINTS (tmpl)))
-return type;
-
-  // Can we find a specialization that matches?
   tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
   while (specs)
 {
@@ -2883,10 +2904,8 @@ fixup_template_type (tree type)
   specs = TREE_CHAIN (specs);
 }
 
-  // Emit an error, but return the type to allow processing to continue.
-  // TODO: We should emit candidates since we've just scanned the 
-  // list of template constraints.
-  error ("type %qT does not match any declarations", type);
+  // If no specialization matches, then must return the type
+  // previously found.
   return type;
 }
 
@@ -2904,7 +2923,7 @@ finish_template_type (tree name, tree ar
   type = lookup_template_class (name, args,
 NULL_TREE, NULL_TREE, entering_scope,
 tf_warning_or_error | tf_user);
-  
+
   // If entering a scope, correct the lookup to account for constraints.
   if (entering_scope)
 type = fixup_template_type (type);


[c++-concepts] Diagnostics patch

2013-10-30 Thread Andrew Sutton
Applying a patch from Ville that adds diagnostics for the concept
specifier. Thanks Ville!

2013-10-30  Ville Voutilainen  
* gcc/cp/decl.c (grokdeclarator): Reject concept keyword
in typedefs, function parameters, data members, non-static
member functions and variables. Allow static member functions
to be concepts.

Andrew Sutton
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c	(revision 204092)
+++ gcc/cp/decl.c	(working copy)
@@ -9074,6 +9074,12 @@
   if (name == NULL)
 name = decl_context == PARM ? "parameter" : "type name";
 
+  if (concept_p && typedef_p)
+{
+  error ("% cannot appear in a typedef declaration");
+  return error_mark_node;
+}
+
   if (constexpr_p && typedef_p)
 {
   error ("% cannot appear in a typedef declaration");
@@ -9387,9 +9393,12 @@
 	   || thread_p)
 	error ("storage class specifiers invalid in parameter declarations");
 
+  /* Function parameters cannot be concept. */
+  if (concept_p)
+  error ("a parameter cannot be declared %");
   /* Function parameters cannot be constexpr.  If we saw one, moan
  and pretend it wasn't there.  */
-  if (constexpr_p)
+  else if (constexpr_p)
 {
   error ("a parameter cannot be declared %");
   constexpr_p = 0;
@@ -10619,6 +10628,11 @@
 			   uqname, ctype);
 		return error_mark_node;
 		  }
+if (concept_p)
+  {
+error ("a destructor cannot be %");
+return error_mark_node;
+  }
 if (constexpr_p)
   {
 error ("a destructor cannot be %");
@@ -10632,6 +10646,12 @@
 		   id_declarator->u.id.unqualified_name);
 		return error_mark_node;
 	  }
+	if (sfk == sfk_constructor)
+if (concept_p)
+  {
+error ("a constructor cannot be %");
+return error_mark_node;
+  }
 
 	/* Tell grokfndecl if it needs to set TREE_PUBLIC on the node.  */
 	function_context = (ctype != NULL_TREE) ?
@@ -10645,7 +10665,7 @@
 			   unqualified_id,
 			   virtualp, flags, memfn_quals, rqual, raises,
 			   friendp ? -1 : 0, friendp, publicp,
-   inlinep | (2 * constexpr_p),
+   inlinep | (2 * constexpr_p) | (4 * concept_p),
 			   sfk,
 			   funcdef_flag, template_count, in_namespace,
 			   attrlist, declarator->id_loc);
@@ -10739,8 +10759,12 @@
 		if (declspecs->gnu_thread_keyword_p)
 		  DECL_GNU_TLS_P (decl) = true;
 		  }
-
-		if (constexpr_p && !initialized)
+		if (concept_p)
+		  // TODO: This needs to be revisited once variable
+		  // templates are supported
+		error ("static data member %qE declared %",
+			   unqualified_id);
+		else if (constexpr_p && !initialized)
 		  {
 		error ("constexpr static data member %qD must have an "
 			   "initializer", decl);
@@ -10749,7 +10773,10 @@
 	  }
 	else
 	  {
-if (constexpr_p)
+		if (concept_p)
+		  error ("non-static data member %qE declared %",
+			 unqualified_id);
+else if (constexpr_p)
 		  {
 		error ("non-static data member %qE declared %",
 			   unqualified_id);
@@ -10897,6 +10924,15 @@
   {
 	/* It's a variable.  */
 
+	// TODO: This needs to be revisited once variable
+	// templates are supported
+	if (concept_p)
+	  {
+	error ("variable %qE declared %",
+		   unqualified_id);
+	return error_mark_node;
+	  }
+	
 	/* An uninitialized decl with `extern' is a reference.  */
 	decl = grokvardecl (type, unqualified_id,
 			declspecs,
Index: gcc/testsuite/g++.dg/concepts/decl-diagnose.C
===
--- gcc/testsuite/g++.dg/concepts/decl-diagnose.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/decl-diagnose.C	(working copy)
@@ -0,0 +1,20 @@
+// { dg-options "-std=c++11" }
+typedef concept int CINT; // { dg-error "'concept' cannot appear in a typedef declaration" }
+
+void f(concept int); // { dg-error "a parameter cannot be declared 'concept'" }
+
+concept int f2(); // { dg-error "result must be bool" }
+concept bool f3();
+
+struct X
+{
+  concept int f4(); // { dg-error "result must be bool|declared with function parameters" }
+  concept bool f5(); // { dg-error "declared with function parameters" }
+  static concept bool f6();
+  static concept bool x; // { dg-error "declared 'concept'" }
+  concept int x2; // { dg-error "declared 'concept'" }
+  concept ~X(); // { dg-error "a destructor cannot be 'concept'" }
+  concept X(); // { dg-error "a constructor cannot be 'concept'" }
+};
+
+concept bool X2; // { dg-error "declared 'concept'" }


Re: C++ PATCH to implement fold-expressions

2015-09-17 Thread Andrew Sutton
Fantastic. I've wanted to get back to this, but since school started
back up, I haven't had any time to look at it.

Thanks!

Andrew


On Thu, Sep 17, 2015 at 2:04 PM, Jason Merrill  wrote:
> Back in January Andrew mostly implemented C++1z fold-expressions
> (https://isocpp.org/files/papers/n4295.html), but the patch broke bootstrap.
> I've fixed it up now and am committing it to the trunk.
>
> Andrew: The main change I made was to drop tentative parsing in favor of
> scanning the tokens ahead looking for an ellipsis next to a fold-operator.
> I also tweaked some diagnostics, fixed handling of dependent expressions
> with no TREE_TYPE, and corrected empty fold of modops.
>
> Tested x86_64-pc-linux-gnu, applying to trunk.


Re: C++ PATCH for non-type constrained-type-specifiers

2015-11-06 Thread Andrew Sutton
> I started looking at allowing non-type constrained-type-specifiers in auto
> deduction and then realized that we didn't handle them in function
> parameters either.  Fixing that brought home to me the oddity of having a
> type-specifier stand in for a non-type.  Mind weighing in on that on the
> core reflector?

That is a little weird. The non-type placeholders should be
id-expressions that name a concept. And template placeholders would be
template-names.

I'll create an issue for it. I need to email Mike Miller and figure
out how issues processing will work. But not until I'm out of the
weeds for the semester.


> I also wonder why we have two different ways of expressing a
> constrained-type-specifier in the implementation: a constrained
> template-parameter (TYPE_DECL, is_constrained_parameter) and a constrained
> auto (TEMPLATE_TYPE_PARM).  Why not represent them the same way?

It's probably a historical distinction. We didn't get concepts as
placeholders until much later in the standardization process.

But with auto template parameters on the horizon, it might be
worthwhile to maintain the distinction. That feature adds a wonderful
little ambiguity:

template struct S;

would declare a non-type template parm whose type is deduced from a
template argument.

template concept bool C = true;
template struct S;

Is C a constrained placeholder (as per a reasonable interpretation of
parameter-declarations), or does it declare a type parameter (as per
the TS)? It's going to end up being the latter.

Combining the representations might make it difficult to tease out
intent later. But that's just me speculating.


Andrew


[PATCH] concepts cleanups and subsumption caching

2019-10-15 Thread Andrew Sutton
This patch finishes moving concepts-related functionality out of pt.c
and into constraint.cc an logic.cc, and adds logic.cc to gtfiles.

As part of that cleanup, I reimplemented and reenabled the subsumption
caching. It's not clear if this provides any significant performance
benefits, but it will prevent redundant and potentially costly
comparisons of constraints.

Tested on bootstrap and vs. cmcstl2.

Andrew Sutton


cleanup.patch
Description: Binary data


[PATCH] diagnose hard errors in concept satisfaction

2019-10-15 Thread Andrew Sutton
Certain errors encountered during constraint satisfaction render the
program ill-formed. Emit those as errors during satisfaction and not
when diagnosing constraint errors.

The errors should include the full context for failure (i.e., when
satisfying X, when satisfying Y, this failed), but we don't build that
information until we know we need to diagnose an error. This patch
does not include that context.

Andrew Sutton


errors.patch
Description: Binary data


[PATCH] fix constrained auto parsing issue

2019-10-17 Thread Andrew Sutton
This fixes a parsing bug with constrained placeholders uses as the
first parameter of a constructor.

Andrew Sutton


0001-Fix-a-bug-with-type-constraints-in-constructors.patch
Description: Binary data


Re: [PATCH] fix constrained auto parsing issue

2019-10-21 Thread Andrew Sutton
In cp_parser_simple_type_specifier:

if (!type && flag_concepts && decl_specs)
{
  /* Try for a type-constraint with template arguments.  We check
 decl_specs here to avoid trying this for a functional cast.  */
 ...

It's subtle.

Andrew Sutton

On Mon, Oct 21, 2019 at 2:22 PM Jason Merrill  wrote:
>
> On 10/17/19 10:36 AM, Andrew Sutton wrote:
> > This fixes a parsing bug with constrained placeholders uses as the
> > first parameter of a constructor.
>
> > +  Parse with an empty set of declaration specifiers since we're
> > +  trying to match a type-specifier of the first parameter.  */
>
> Why does that make a difference?
>
> Jason
>


[PATCH] PR c++/92078 Add access specifiers to specializations

2019-11-14 Thread Andrew Sutton
Fixes mentioned issue. Tested on bootstrap and cmcsstl2.

gcc/cp/
* pt.c (maybe_new_partial_specialization): Apply access to newly
created partial specializations. Update comment style.

gcc/testsuite/
* g++.dg/cpp2a/concepts-pr92078.C: New.

Andrew


pr92078.patch
Description: Binary data


[PATCH] Fixes PR c++/89913

2019-11-15 Thread Andrew Sutton
Avoid ICE when the alias is ill-formed.

 gcc/cp/
  * pt.c (get_underlying_template): Exit loop if the original type
of the alias is null.

gcc/testsuite/
  * g++.dg/cpp2a/pr89913.C: New test.

Andrew Sutton


0001-Don-t-segfault-on-error-PR-c-89913.patch
Description: Binary data


[PATCH] Prevent recursive satisfaction (PR c++/88395)

2019-11-18 Thread Andrew Sutton
This applies on top of the patch here:
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01034.html

Wrap satisfaction with push/pop_tinst_level to force termination on recursion.

Andrew Sutton


0001-Prevent-recursive-satisfaction-PR-c-88395.patch
Description: Binary data


Re: [PATCH] Prevent recursive satisfaction (PR c++/88395)

2019-11-18 Thread Andrew Sutton
I forgot to mention a somewhat odd test included in the patch:
concepts-recursive-sat3.C does not recurse. Code follows:

template
concept Fooable = requires(T t) { foo(t); };

template
void foo(T t) { }

void test()
{
  foo(0); // { dg-error "unsatisfied constraints" }
}

It doesn't crash, but it doesn't diagnose also doesn't fail as a
result of recursive instantiation. The recursive-sat2.C test is the
same except that it instantiates foo with a class type. This seems
like it might be related to ADL, but entirely certain.

Andrew Sutton

On Mon, Nov 18, 2019 at 10:13 AM Andrew Sutton
 wrote:
>
> This applies on top of the patch here:
> https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01034.html
>
> Wrap satisfaction with push/pop_tinst_level to force termination on recursion.
>
> Andrew Sutton


[PATCH] PR c++/92236: Improve static assertions of concepts

2019-11-20 Thread Andrew Sutton
This patch builds on https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01034.html.

Tie static assertion diagnostics into constraint diagnostic. For
example, this program:

template
concept iterator =
  requires (I i)
  {
++i;
*i;
  };

static_assert(iterator);

Yields these errors:

x.cpp:11:15: error: static assertion failed
   11 | static_assert(iterator);
  |   ^
x.cpp:11:15: note: constraints not satisfied
x.cpp:4:9:   required by the constraints of ‘template concept iterator’
x.cpp:5:3:   in requirements with ‘int i’
x.cpp:8:5: note: the required expression ‘* i’ is invalid
8 | *i;
  | ^~

Andrew Sutton


0001-Emit-detailed-diagnostics-for-static-assertion-failu.patch
Description: Binary data


[PATCH] PR c++/92439: Improve diagnostics for ill-formed requires-clauses

2019-11-22 Thread Andrew Sutton
This does a much better job identifying when an expression in a
requires-clause needs parentheses.

Andrew Sutton


0001-PR-c-92439.patch
Description: Binary data


Re: [PATCH] Prevent recursive satisfaction (PR c++/88395)

2019-11-27 Thread Andrew Sutton
> > +  if (tmpl)
> > + push_tinst_level (tmpl);
>
> Actually, why not pass 't' here?

I thought it would matter if 't' was a non-template. Turns out it
doesn't. Updated and committed.


[PATCH] PR C++/92739

2019-12-02 Thread Andrew Sutton
Find attached.

   gcc/cp/
* parser.c (cp_parser_constraint_requires_parens): Exclude
attributes
as postfix expressions.

gcc/testsuite/
* g++.dg/concepts-pr92739.C: New test.

Andrew Sutton


0001-Fix-PR-c-92739.patch
Description: Binary data


Re: Patch for constexpr variable templates

2014-08-07 Thread Andrew Sutton
This patch prevents the initializer from being checked when it is
dependent. It also sets the type of a dependent template-id referring
to a variable template to be unknown, making such expressions type
dependent.

2014-08-07  Andrew Sutton  

* pt.c (lookup_template_variable): Make the type unspecified if
any template arguments are dependent.
* decl.c (cp_finish_decl): Don't check the initializer if it is
value-dependent.

New test included.

Andrew Sutton


On Wed, Aug 6, 2014 at 9:34 PM, Jason Merrill  wrote:
> On 08/05/2014 04:06 PM, Paolo Carlini wrote:
>>
>> Great. I will double check but var-templ4.C fails for me with an ICE.
>
>
> Hunh, I wonder how I missed that.
>
> Here's what I'm checking in; we want to unset DECL_COMDAT for variable
> templates, too.
>
>
Index: gcc/testsuite/g++.dg/cpp1y/var-templ6.C
===
--- gcc/testsuite/g++.dg/cpp1y/var-templ6.C	(revision 0)
+++ gcc/testsuite/g++.dg/cpp1y/var-templ6.C	(revision 0)
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++1y" }
+
+template
+  constexpr bool Class = __is_class(T);
+
+template
+  constexpr bool Test = Class;
+
+struct S { };
+
+static_assert(!Test, "");
+static_assert(Test, "");
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c	(revision 213667)
+++ gcc/cp/decl.c	(working copy)
@@ -6417,19 +6417,20 @@ cp_finish_decl (tree decl, tree init, bo
 	  DECL_INITIAL (decl) = NULL_TREE;
 	}
 
+  bool value_dependent_p = init && value_dependent_init_p (init);
+
   /* Generally, initializers in templates are expanded when the
 	 template is instantiated.  But, if DECL is a variable constant
 	 then it can be used in future constant expressions, so its value
 	 must be available. */
-
-  if (!VAR_P (decl) || dependent_type_p (type))
+  if (!VAR_P (decl) || type_dependent_p || value_dependent_p)
 	/* We can't do anything if the decl has dependent type.  */;
   else if (init
 	   && init_const_expr_p
 	   && !type_dependent_p
 	   && decl_maybe_constant_var_p (decl)
 	   && !type_dependent_init_p (init)
-	   && !value_dependent_init_p (init))
+	   && !value_dependent_p)
 	{
 	  /* This variable seems to be a non-dependent constant, so process
 	 its initializer.  If check_initializer returns non-null the
Index: gcc/cp/pt.c
===
--- gcc/cp/pt.c	(revision 213667)
+++ gcc/cp/pt.c	(working copy)
@@ -8260,13 +8260,23 @@ lookup_template_class (tree d1, tree arg
   return ret;
 }
 
-/* Return a TEMPLATE_ID_EXPR for the given variable template and ARGLIST. */
+/* Return a TEMPLATE_ID_EXPR for the given variable template and ARGLIST. 
+   If the ARGLIST refers to any template parameters, the type of the
+   expression is the unknown_type_node since the template-id could
+   refer to an explicit or partial specialization.
+*/
 
 tree
 lookup_template_variable (tree templ, tree arglist)
 {
-  return build2 (TEMPLATE_ID_EXPR, TREE_TYPE (templ), templ, arglist);
+  tree type;
+  if (uses_template_parms (arglist))
+type = unknown_type_node;
+  else
+type = TREE_TYPE (templ);
+  return build2 (TEMPLATE_ID_EXPR, type, templ, arglist);
 }
+
 
 struct pair_fn_data
 {


Re: Patch for constexpr variable templates

2014-08-07 Thread Andrew Sutton
>>  * decl.c (cp_finish_decl): Don't check the initializer if it is
>>  value-dependent.
>
>
> Why is this needed?

I thought that check_initializer was evaluating the constant
expression, and was resulting in errors because a template-id
referring to a variable template with a concrete type wasn't being
marked as dependent.

Taking a second look, this change doesn't appear to be needed. The
change to lookup_template_variable seems to do enough. I just reran
the tests and it seems to behave correctly without it.

Andrew


[c++-concepts] constraints redux

2014-08-08 Thread Andrew Sutton
This patch revisits the normalization and checking of constraints. In
particular, it ensures that associated constraints are always
normalized so that checking constraints will never instantiate a
concept declaration.

This also removes the constraint check from fn_type_unification as per
discussion in Rapperswil. Candidates whose constraints are not
satisfied are just marked non-viable in overload resolution. This also
clears up an issue where constraints for function templates were being
checked twice during overload resolution.

I also ended up renaming a lot of functions to make them match the
wording the specification. Basically, "requirements -> constraints".

Updated all affected tests.

2014-08-08  Andrew Sutton  

* gcc/cp/logic.cc (subsumes_constraints_nonnull): Don't re-normalize
constraints, it's already been done.
* gcc/cp/cp-tree.h (*_requirement[s]): Renamed to *_constraint[s] to
reflect wording in specification. Removed reduce_requirements.
* gcc/cp/pt.c (process_template_parm, tsubst_pack_conjunction): Update
from renaming.
(fn_type_unification): Remove constraint check.
* gcc/cp/parser.c (cp_parser_type_parameter,
cp_parser_trailing_requirements,
cp_parser_template_declaration_after_export,
synthesize_implicit_template_parm): Update from renaming.
* gcc/cp/constraint.cc: Renamed a lot of functions to reflect wording
in specification.
(finish_template_constraints): Normalize associated constraints.
(tsubst_constraint_expr): Renamed from instantiate_requirements.
Normalize associated constraints.
(check_satisfied): Return true if the arguments refer to template
parameters.
(all_constraints_satisfied, any_conjunctions_satisfied,
check_requirements): No longer needed.
(check_diagnostic_constraints): Just normalize the expression, don't
    decompose it.

Andrew Sutton
Index: gcc/cp/cp-tree.h
===
--- gcc/cp/cp-tree.h	(revision 213667)
+++ gcc/cp/cp-tree.h	(working copy)
@@ -6079,10 +6079,6 @@ extern tree maybe_resolve_dummy			(tree,
 extern tree nonlambda_method_basetype		(void);
 extern void maybe_add_lambda_conv_op(tree);
 extern bool is_lambda_ignored_entity(tree);
-extern tree finish_template_requirements(tree);
-extern tree save_leading_requirements   (tree);
-extern tree save_trailing_requirements  (tree);
-extern bool valid_requirements_p(tree);
 
 /* in tree.c */
 extern int cp_tree_operand_length		(const_tree);
@@ -6415,20 +6411,23 @@ extern void suggest_alternatives_for
 extern tree strip_using_decl(tree);
 
 /* in constraint.cc */
-extern tree conjoin_requirements(tree, tree);
-extern tree conjoin_requirements(tree);
-extern tree reduce_requirements (tree);
+extern tree conjoin_constraints (tree, tree);
+extern tree conjoin_constraints (tree);
 extern tree get_constraints (tree);
 extern void set_constraints (tree, tree);
-extern tree get_shorthand_requirements  (tree);
+extern tree get_shorthand_constraints   (tree);
 
 extern tree build_concept_check (tree, tree, tree = NULL_TREE);
 extern tree build_constrained_parameter (tree, tree, tree = NULL_TREE);
 extern bool deduce_constrained_parameter(tree, tree&, tree&);
 extern tree resolve_constraint_check(tree);
 
+extern tree finish_template_constraints (tree);
+extern tree save_leading_constraints(tree);
+extern tree save_trailing_constraints   (tree);
+extern bool valid_requirements_p(tree);
 extern tree finish_concept_name (tree);
-extern tree finish_shorthand_requirement(tree, tree);
+extern tree finish_shorthand_constraint (tree, tree);
 extern tree finish_requires_expr(tree, tree);
 extern tree finish_expr_requirement (tree, tree, tree);
 extern tree finish_expr_requirement (tree);
@@ -6439,8 +6438,6 @@ extern tree finish_noexcept_requirement
 extern tree finish_validexpr_expr   (tree);
 extern tree finish_validtype_expr   (tree);
 extern tree finish_constexpr_expr   (tree);
-extern tree finish_concept_name (tree);
-extern tree finish_shorthand_requirement(tree, tree);
 
 extern void check_constrained_friend(tree, tree);
 
@@ -6452,8 +6449,8 @@ extern tree tsubst_expr_req
 extern tree tsubst_type_req (tree, tree, tree);
 extern tree tsubst_nested_req   (tree, tree, tree);
 
-extern tree instantiate_requirements(tree, tree, bool);
 extern tree tsubst_constraint_info

[c++-concepts] substitution fixes

2014-08-11 Thread Andrew Sutton
Fixing some bugs substituting through constraints. In particular, when
diagnosing an error, make sure that we use the right arguments.

There was also a bug caused by substitution through a decltype-type.
In particular, when folding a non-dependent expression containing a
decltype-type, the inner type is not being resolved (because tsubst
returns early when args == NULL_TREE).

The second patch fixes a regression introduced by the first patch.

2014-08-11  Andrew Sutton  

* gcc/cp/pt.c (tsubst): Don't short circuit substitution into
types when processing constraints.
* gcc/cp/constraint.c (tsubst_constraint_expr): Indicate that
constraint processing is happening.
(tsubst_constraint_info): Just substitute directly into the
normalized constraints instead of re-normalizing.
(diagnose_constraints): Adjust template arguments when
diagnosing template constraint failures.
* gcc/cp/logic.cc (decompose_assumptions): Handle null assumptions.

Andrew Sutton
Index: pt.c
===
--- pt.c	(revision 213758)
+++ pt.c	(working copy)
@@ -11960,6 +11960,8 @@ tsubst_exception_specification (tree fnt
   return new_specs;
 }
 
+extern int processing_constraint;
+
 /* Take the tree structure T and replace template parameters used
therein with the argument vector ARGS.  IN_DECL is an associated
decl for diagnostics.  If an error occurs, returns ERROR_MARK_NODE.
@@ -11994,7 +11996,7 @@ tsubst (tree t, tree args, tsubst_flags_
   if (DECL_P (t))
 return tsubst_decl (t, args, complain);
 
-  if (args == NULL_TREE)
+  if (args == NULL_TREE && !processing_constraint)
 return t;
 
   code = TREE_CODE (t);
Index: semantics.c
===
--- semantics.c	(revision 213758)
+++ semantics.c	(working copy)
@@ -7011,6 +7011,7 @@ finish_decltype_type (tree expr, bool id
   return type;
 }
 
+
   /* The type denoted by decltype(e) is defined as follows:  */
 
   expr = resolve_nondeduced_context (expr);
@@ -7386,7 +7387,7 @@ finish_trait_expr (cp_trait_kind kind, t
 	  || kind == CPTK_IS_LITERAL_TYPE
 	  || kind == CPTK_IS_POD
 	  || kind == CPTK_IS_POLYMORPHIC
-|| kind == CPTK_IS_SAME_AS
+  || kind == CPTK_IS_SAME_AS
 	  || kind == CPTK_IS_STD_LAYOUT
 	  || kind == CPTK_IS_TRIVIAL
 	  || kind == CPTK_IS_UNION);
Index: constraint.cc
===
--- constraint.cc	(revision 213758)
+++ constraint.cc	(working copy)
@@ -241,7 +241,7 @@ tree normalize_stmt (tree);
 tree normalize_decl (tree);
 tree normalize_misc (tree);
 tree normalize_logical (tree);
-tree normalize_call(tree);
+tree normalize_call (tree);
 tree normalize_requires (tree);
 tree normalize_expr_req (tree);
 tree normalize_type_req (tree);
@@ -1114,14 +1114,14 @@ tsubst_local_parms (tree t,
 }
 
 // Substitute ARGS into the requirement body (list of requirements), T.
+// Note that if any substitutions fail, then this is equivalent to 
+// returning false.
 tree
 tsubst_requirement_body (tree t, tree args, tree in_decl)
 {
   tree r = NULL_TREE;
   while (t)
 {
-  // If any substitutions fail, then this is equivalent to
-  // returning false.
   tree e = tsubst_expr (TREE_VALUE (t), args, tf_none, in_decl, false);
   if (e == error_mark_node)
 e = boolean_false_node;
@@ -1142,7 +1142,6 @@ tsubst_requires_expr (tree t, tree args,
   return finish_requires_expr (p, r);
 }
 
-
 // Substitute ARGS into the valid-expr expression T.
 tree
 tsubst_validexpr_expr (tree t, tree args, tree in_decl)
@@ -1197,6 +1196,12 @@ tsubst_nested_req (tree t, tree args, tr
   return tsubst_expr (TREE_OPERAND (t, 0), args, tf_none, in_decl, false);
 }
 
+// Used in various contexts to control substitution. In particular, when
+// non-zero, the substitution of NULL arguments into a type will still
+// process the type as if passing non-NULL arguments, allowing type
+// expressions to be fully elaborated during substitution.
+int processing_constraint;
+
 // Substitute the template arguments ARGS into the requirement
 // expression REQS. Errors resulting from substitution are not
 // diagnosed.
@@ -1208,11 +1213,13 @@ tree
 tsubst_constraint_expr (tree reqs, tree args, bool do_not_fold)
 {
   cp_unevaluated guard;
+  ++processing_constraint;
   if (do_not_fold)
 ++processing_template_decl;
   tree r = tsubst_expr (reqs, args, tf_none, NULL_TREE, false);
   if (do_not_fold)
 --processing_template_decl;
+  --processing_constraint;
   return r;
 }
 
@@ -1230,10 +1237,8 @@ tsubst_constraint_info (tree ci, tree ar
 result->leading_reqs = tsubst_constraint_expr (r, args, true);
   if (tree r = CI_TRAILING_REQS (ci))
 result->trailing_reqs = tsubst_constraint_expr (r, args, true);
-
-  // Build the normalized associated requiremnts.
-  tree r = 

Re: Patch for constexpr variable templates

2014-08-12 Thread Andrew Sutton
>>  * pt.c (lookup_template_variable): Make the type unspecified if
>>  any template arguments are dependent.
>
>
> This hunk is OK.

Hi Jason, did you apply this hunk of the patch, or should I just
resend this by itself?

Andrew


Re: Patch for constexpr variable templates

2014-08-12 Thread Andrew Sutton
Oohh... I can commit to trunk? I can do it tomorrow morning.

Andrew Sutton


On Tue, Aug 12, 2014 at 4:59 PM, Jason Merrill  wrote:
> On 08/12/2014 04:21 PM, Andrew Sutton wrote:
>>>>
>>>>   * pt.c (lookup_template_variable): Make the type unspecified
>>>> if
>>>>   any template arguments are dependent.
>>>
>>>
>>>
>>> This hunk is OK.
>>
>>
>> Hi Jason, did you apply this hunk of the patch, or should I just
>> resend this by itself?
>
>
> I thought you would apply it, but I can if you'd rather.
>
> Jason
>


Re: [c++-concepts] variable concepts

2014-08-13 Thread Andrew Sutton
Committed.

Andrew Sutton


On Wed, Aug 13, 2014 at 3:24 AM, Braden Obrzut  wrote:
> This patch adds support for variable concepts.
>
> There is a known issue that prevents concept variables from having requires
> expressions that have parameters.  This issue is not within the scope of
> this patch as it affects adhoc requires expressions as well.
>
> 2014-08-13  Braden Obrzut 
>
> * gcc/cp/constraint.cc (deduce_constrained_parameter): Deduce concept
> from variable concept template-id expressions.
> (normalize_var): New.
> (normalize_template_id): Identify variable concepts.
> (build_concept_check): Handle variable concepts.
> (finish_shorthand_requirement): Handle variable concepts.
> (diagnose_var): New.
> (diagnose_node): Identify variable concepts.
> * gcc/cp/decl.c (grokvardecl): Pass concept flag through to
> check_explicit_specialization.
> (grokdeclarator): Allow variable concepts and pass concept flag through
> grokvardecl.
> * gcc/cp/parser.c (cp_is_constrained_parameter): Accept variable
> concepts.
> (cp_parser_nonclass_name): Accept variable concepts.
> (get_concept_from_constraint): Handle variable concepts.
> * gcc/cp/pt.c (tsubst_copy_and_build): Lookup variable templates.
> (value_dependent_expression_p): Check requires expressions for value
> dependence.
> * gcc/cp/semantics.c (finish_call_expr): Don't instantiate variable
> templates if processing a template declaration.
> * gcc/testsuite/g++.dg/concepts/decl-diagnose.C: Change expected error
> as variable concepts are now handled.
> * gcc/testsuite/g++.dg/concepts/var-concepts1.C: New test.
> * gcc/testsuite/g++.dg/concepts/var-concepts2.C: New test.
>


Re: Patch for constexpr variable templates

2014-08-13 Thread Andrew Sutton
>> Oohh... I can commit to trunk?
>
> Yes, you're on the write-after-approval list in MAINTAINERS. :)

True, but it's my first commit to trunk :) Incidentally, that's committed now.

Andrew


[c++-concepts] explicit instantiation and specialization

2014-08-13 Thread Andrew Sutton
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 a

Re: [c++-concepts] explicit instantiation and specialization

2014-08-13 Thread Andrew Sutton
Ah... sorry. Leftovers. I didn't have time to run a full bootstrap
build before heading out for a few days. I'll try to get those out
tomorrow afternoon-ish.

Andrew


On Wed, Aug 13, 2014 at 9:13 PM, Ed Smith-Rowland <3dw...@verizon.net> wrote:
> I get build fail:
>
> ../../gcc_concepts/gcc/cp/call.c:8793:8: error: unused variable ‘m1’
> [-Werror=unused-variable]
>tree m1 = get_temploid (cand1);
> ^
> ../../gcc_concepts/gcc/cp/call.c:8794:8: error: unused variable ‘m2’
> [-Werror=unused-variable]
>tree m2 = get_temploid (cand2);
> ^
> cc1plus: all warnings being treated as errors
>
> Commenting the lines let the build finish.
>
> Ed
>


Re: [c++-concepts] explicit instantiation and specialization

2014-08-15 Thread Andrew Sutton
Just committed this patch, fixing the bootstrap.

2014-08-13  Andrew Sutton  

Fix regression in bootstrap.
  * gcc/cp/call.c (get_temploid): Removed. No longer called.
  (joust): Remove unused variable declarations.

Andrew


On Wed, Aug 13, 2014 at 9:50 PM, Andrew Sutton
 wrote:
> Ah... sorry. Leftovers. I didn't have time to run a full bootstrap
> build before heading out for a few days. I'll try to get those out
> tomorrow afternoon-ish.
>
> Andrew
>
>
> On Wed, Aug 13, 2014 at 9:13 PM, Ed Smith-Rowland <3dw...@verizon.net> wrote:
>> I get build fail:
>>
>> ../../gcc_concepts/gcc/cp/call.c:8793:8: error: unused variable ‘m1’
>> [-Werror=unused-variable]
>>tree m1 = get_temploid (cand1);
>> ^
>> ../../gcc_concepts/gcc/cp/call.c:8794:8: error: unused variable ‘m2’
>> [-Werror=unused-variable]
>>tree m2 = get_temploid (cand2);
>> ^
>> cc1plus: all warnings being treated as errors
>>
>> Commenting the lines let the build finish.
>>
>> Ed
>>
Index: gcc/cp/call.c
===
--- gcc/cp/call.c	(revision 213924)
+++ gcc/cp/call.c	(working copy)
@@ -8755,24 +8755,6 @@ add_warning (struct z_candidate *winner,
   winner->warnings = cw;
 }
 
-// When a CANDidate function is a member function of a class template
-// specialization, return the temploid describing that function.
-// Returns NULL_TREE otherwise.
-static inline tree
-get_temploid (struct z_candidate *cand)
-{
-  gcc_assert (cand);
-  tree t = NULL_TREE;
-  if (!cand->template_decl)
-{
-  if (DECL_P (cand->fn) && DECL_USE_TEMPLATE (cand->fn))
-t = DECL_TI_TEMPLATE (cand->fn);
-  if (t && TREE_CODE (t) == TEMPLATE_INFO)
-t = TI_TEMPLATE (t);
-}
-return t;
-}
-
 /* Compare two candidates for overloading as described in
[over.match.best].  Return values:
 
@@ -8789,10 +8771,6 @@ joust (struct z_candidate *cand1, struct
   size_t i;
   size_t len;
 
-  // Try to get a temploid describing each candidate. 
-  tree m1 = get_temploid (cand1);
-  tree m2 = get_temploid (cand2);
-
   /* Candidates that involve bad conversions are always worse than those
  that don't.  */
   if (cand1->viable > cand2->viable)


[c++-concepts] 2 patches

2014-08-18 Thread Andrew Sutton
The first improves support for shorthand concepts, and includes the
ability to write default arguments. Also, no more ICE when omitting
identifiers for template parameters.

The second adds constraint checks when taking the address of an
overloaded function.

Corresponding change logs follow:

2014-08-13  Andrew Sutton  

* gcc/cp/class.c (resolve_address_of_overloaded_function): Check
constraints.
* gcc/cp/decl.c (grokfndecl): For now, disallow constrained
non-template functions.
* gcc/testsuite/g++.dg/concepts: New tests.

2014-08-13  Andrew Sutton  

* gcc/cp/parser.c (get_id_declarator, get_identifier): New helper
functions.s
(cp_check_constrained_type_parm): Don't fail on null declarators.
(cp_finish_constrained_parameter): Remove redundant processing for
checking declarations.
(cp_maybe_type_parameter, cp_declares_type_parameter,
cp_declares_type_template_parameter,
cp_declares_template_template_parameter): New helper functions for
determining when a parameter declaration is actually a constrained
template parameter.
(cp_parser_default_type_template_argument,
cp_parser_default_template_template_argument): Parsing support
for argument types of default arguments.
(cp_parser_template_parameter): Finish constrained parameters
after all variadic and default arg checks.
(cp_parser_parameter_declaration): Parse default arguments
differently if the parameter actually declares a type parameter.
* gcc/testsuite/g++.dg/concepts: New tests.

Andrew Sutton
Index: gcc/cp/parser.c
===
--- gcc/cp/parser.c	(revision 213909)
+++ gcc/cp/parser.c	(working copy)
@@ -13221,6 +13221,29 @@ cp_parser_template_parameter_list (cp_pa
   return end_template_parm_list (parameter_list);
 }
 
+// Given a declarator, get the declarator-id part, or NULL_TREE if this
+// is an abstract declarator.
+static inline cp_declarator*
+cp_get_id_declarator (cp_declarator *declarator) 
+{
+  cp_declarator *d = declarator;
+  while (d && d->kind != cdk_id)
+d = d->declarator;
+  return d;
+}
+
+// Get the declared name from the DECLARATOR or NULL_TREE if this is
+// DECLARATOR is NULL
+static inline tree
+cp_get_identifier (cp_declarator *declarator)
+{
+  declarator = cp_get_id_declarator (declarator);
+  if (declarator)
+return declarator->u.id.unqualified_name;
+  else
+return NULL_TREE;
+}
+
 // Returns true if PARM declares a constrained-parameter.
 static inline bool
 cp_is_constrained_parameter (cp_parameter_declarator *parm)
@@ -13242,8 +13265,9 @@ bool
 cp_check_constrained_type_parm (cp_parser *parser, 
 cp_parameter_declarator *parm)
 {
-  // Don't ptr, ref, function, or array declarators for a constrained type
-  // or template template parameter.
+  if (!parm->declarator)
+return true;
+  
   if (parm->declarator->kind != cdk_id)
 {
   cp_parser_error (parser, "invalid constrained type parameter");
@@ -13320,28 +13344,16 @@ cp_finish_constrained_parameter (cp_pars
  bool *is_parameter_pack)
 {
   tree decl = parmdecl->decl_specifiers.type;
-  tree id = parmdecl->declarator->u.id.unqualified_name;
+  tree id = cp_get_identifier (parmdecl->declarator);
   tree def = parmdecl->default_argument;
   tree proto = DECL_INITIAL (decl);
 
-  // Remember if the user declared this as a parameter pack and
-  // erase that flag on the annotation. Template packs are dealt
-  // with separately.
-  bool is_pack = parmdecl->declarator->parameter_pack_p;
-  if (is_pack)
-parmdecl->declarator->parameter_pack_p = false;
-
-  // Is the prototype a parameter pack? If so, but the declaration
-  // does not include "...", then emit an error.
+  // A templat parameter constrained by a variadic concept shall also
+  // be declared as a template parameter pack.
   bool is_variadic = template_parameter_pack_p (proto);
-  if (is_variadic && !is_pack)
+  if (is_variadic && !*is_parameter_pack)
 cp_parser_error (parser, "variadic constraint introduced without %<...%>");
 
-  // The prototype is a template parameter pack, then the resulting
-  // parameter also needs to be a pack.
-  if (is_pack || is_variadic)
-*is_parameter_pack = true;
-
   // Build the parameter. Return an error if the declarator
   // was invalid.
   tree parm;
@@ -13361,6 +13373,111 @@ cp_finish_constrained_parameter (cp_pars
   return parm;
 }
 
+// Returns the type of the given TYPE may represent the declaration of
+// a template type parameter. This is a helper function for the
+// cp_declares_type* functions below.
+static inline bool
+cp_maybe_type_parameter (tree type)
+{
+  return type
+ && TREE_CODE (ty

[c++-concepts] normalization checks

2014-08-19 Thread Andrew Sutton
This patch adds checks for user-defined logical operators during
constraint normalization and ensures that all atomics can be converted
to bool.

2014-08-14  Andrew Sutton  

Implement normalization checks.
* gcc/cp/constraint.cc (normalize_expr): Delegate cast and
atomic nodes to a dedicated function.
(check_logical): Check that an && or || does not resolve to a
user-defined function.
(normalize_logical): Check operators and save the locaiton of
the new expression.
(normalize_call, normalize_var): Remove spurios error messages.
(normalize_cast): New, delegates to normalize atom.
(normalize_atom): Check that instantiated expressions can be
converted to bool
(tsubst_constraint_info): Re-normalize the associated constraints
to check for post-substitution restrictions.
* gcc/cp/cp-tree.h (xvalue_result_type): Add to header.


Andrew Sutton
Index: gcc/cp/constraint.cc
===
--- gcc/cp/constraint.cc	(revision 213924)
+++ gcc/cp/constraint.cc	(working copy)
@@ -264,6 +264,8 @@ tree normalize_nested_req (tree);
 tree normalize_var (tree);
 tree normalize_template_id (tree);
 tree normalize_stmt_list (tree);
+tree normalize_cast (tree);
+tree normalize_atom (tree);
 
 // Reduce the requirement T into a logical formula written in terms of
 // atomic propositions.
@@ -328,7 +330,7 @@ normalize_expr (tree t)
   return normalize_template_id (t);
 
 case CAST_EXPR:
-  return normalize_node (TREE_VALUE (TREE_OPERAND (t, 0)));
+  return normalize_cast (t);
 
 case BIND_EXPR:
   return normalize_node (BIND_EXPR_BODY (t));
@@ -339,7 +341,7 @@ normalize_expr (tree t)
 
 // Everything else is atomic.
 default:
-  return t;
+  return normalize_atom (t);
 }
 }
 
@@ -402,6 +404,34 @@ normalize_misc (tree t)
   return NULL_TREE;
 }
 
+// Check that the logical expression is not a user-defined operator.
+bool
+check_logical (tree t) 
+{
+  // We can't do much for type dependent expressions.
+  if (type_dependent_expression_p (t) || value_dependent_expression_p (t))
+return true;
+
+  // Resolve the logical operator. Note that template processing is
+  // disabled so we get the actual call or target expression back.
+  // not_processing_template_sentinel sentinel;
+  tree arg1 = TREE_OPERAND (t, 0);
+  tree arg2 = TREE_OPERAND (t, 1);
+
+  tree ovl = NULL_TREE;
+  tree expr = build_new_op (input_location, TREE_CODE (t), LOOKUP_NORMAL, 
+arg1, arg2, /*arg3*/NULL_TREE, 
+&ovl, tf_none);
+  if (TREE_CODE (expr) != TREE_CODE (t))
+{
+  error ("user-defined operator %qs in constraint %qE",
+ operator_name_info[TREE_CODE (t)].name, t);
+  ;
+  return false;
+}
+  return true;
+}
+
 // Reduction rules for the binary logical expression T (&& and ||).
 //
 // Generate a new expression from the reduced operands. If either operand
@@ -409,14 +439,18 @@ normalize_misc (tree t)
 tree
 normalize_logical (tree t)
 {
+  if (!check_logical (t))
+return NULL_TREE;
+
   tree l = normalize_expr (TREE_OPERAND (t, 0));
   tree r = normalize_expr (TREE_OPERAND (t, 1));
   if (l && r)
 {
-  t = copy_node (t);
-  TREE_OPERAND (t, 0) = l;
-  TREE_OPERAND (t, 1) = r;
-  return t;
+  tree result = copy_node (t);
+  SET_EXPR_LOCATION (result, EXPR_LOCATION (t));
+  TREE_OPERAND (result, 0) = l;
+  TREE_OPERAND (result, 1) = r;
+  return result;
 }
   else
 return NULL_TREE;
@@ -440,18 +474,13 @@ normalize_call (tree t)
   // Reduce the body of the function into the constriants language.
   tree body = normalize_constraints (DECL_SAVED_TREE (fn));
   if (!body)
-{
-  error ("could not inline requirements from %qD", fn);
-  return error_mark_node;
-}
+return error_mark_node;
 
   // Instantiate the reduced results using the deduced args.
   tree result = tsubst_constraint_expr (body, args, false);
   if (result == error_mark_node)
-{
-  error ("could not instantiate requirements from %qD", fn);
-  return error_mark_node;
-}
+return error_mark_node;
+
   return result;
 }
 
@@ -469,18 +498,12 @@ normalize_var (tree t)
   // Reduce the initializer of the variable into the constriants language.
   tree body = normalize_constraints (DECL_INITIAL (decl));
   if (!body)
-   {
- error ("could not inline requirements from %qD", decl);
- return error_mark_node;
-   }
+return error_mark_node;
 
   // Instantiate the reduced results.
   tree result = tsubst_constraint_expr (body, TREE_OPERAND (t, 1), false);
   if (result == error_mark_node)
-{
-  error ("could not instantiate requirements from %qD", decl);
-  return error_mark_node;
-}
+return err

[c++-concepts] variable concept fixes

2014-08-20 Thread Andrew Sutton
Add more diagnostics for variable concepts. Also fix a regression
where non-template concepts variables were causing ICEs because they
aren't being allocated via build_lang_decl.

2014-08-15  Andrew Sutton  

Additional declaration restrictions on variable concepts.
* gcc/cp/decl.c (is_concept_var): New.
(cp_finish_decl): Check for uninitialized variable
concepts.
(grokvardecl): Don't set the concept flag for non-template variables.
* g++.dg/concepts/decl-diagnose.C: Add tests.

Andrew Sutton
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c	(revision 214239)
+++ gcc/cp/decl.c	(working copy)
@@ -6259,6 +6259,16 @@ value_dependent_init_p (tree init)
   return false;
 }
 
+// Returns true if a DECL is VAR_DECL with the concept specifier. Note
+// that not all variables are decl-lang-specific.
+static inline bool
+is_concept_var (tree decl) 
+{
+  return VAR_P (decl) 
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_DECLARED_CONCEPT_P (decl);
+}
+
 /* Finish processing of a declaration;
install its line number and initial value.
If the length of an array type is not known before,
@@ -6435,6 +6445,8 @@ cp_finish_decl (tree decl, tree init, bo
 	init = NULL_TREE;
 	  release_tree_vector (cleanups);
 	}
+  else if (!init && is_concept_var (decl))
+error ("variable concept has no initializer");
   else if (!DECL_PRETTY_FUNCTION_P (decl))
 	{
 	  /* Deduce array size even if the initializer is dependent.  */
@@ -8264,9 +8276,17 @@ grokvardecl (tree type,
   else
 DECL_INTERFACE_KNOWN (decl) = 1;
 
-  // Mark the variable as a concept.
+  // Check that the variable can be safely declared as a concept.
   if (conceptp)
-DECL_DECLARED_CONCEPT_P (decl) = true;
+{
+  if (!processing_template_decl) 
+{
+  error ("a non-template variable cannot be %");
+  return NULL_TREE;
+}
+  else
+DECL_DECLARED_CONCEPT_P (decl) = true;
+}
 
   // Handle explicit specializations and instantiations of variable templates.
   if (orig_declarator)


Re: [c++-concepts] variable concept fixes

2014-08-20 Thread Andrew Sutton
> On 08/20/2014 08:56 PM, Andrew Sutton wrote:
>>
>> +  return VAR_P (decl)
>> + && DECL_LANG_SPECIFIC (decl)
>> + && DECL_DECLARED_CONCEPT_P (decl);
>
> this is brittle from the formatting point of view. Please double check in
> detail what I'm going to say, but I think that in such cases you simply want
> to wrap the whole thing in round parentheses.

Sorry, did you just mean to wrap the entire conjunction in parens? I'm
trying to find the formatting guidelines to check, but not succeeding
at the moment.

Andrew


[c++-concepts] template scoping error

2014-08-20 Thread Andrew Sutton
Fixes a regression in lookup rules involving declarations with
nested-name-specifiers. In particular, we don't actually want to
execute these rules if we absolutely don't have to.

2014-08-15  Andrew Sutton  

Fixing regression in scoping rules for templates.
* gcc/cp/semantics.c (fixup_tmeplate_type): Lift check to
finish_template_type.
(finish_template_type): Only do this when concepts are enabled,
and also when the class is actually a template. For non-dependent
types there are no actions to be taken.

Andrew Sutton
Index: gcc/cp/semantics.c
===
--- gcc/cp/semantics.c	(revision 214228)
+++ gcc/cp/semantics.c	(working copy)
@@ -3004,10 +3004,6 @@ finish_template_decl (tree parms)
 static tree
 fixup_template_type (tree type)
 {
-  // Don't try to fix non-class types.
-  if (!CLASS_TYPE_P (type))
-return type;
-
   // Find the template parameter list at the a depth appropriate to
   // the scope we're trying to enter. 
   tree parms = current_template_parms;
@@ -3055,8 +3051,12 @@ finish_template_type (tree name, tree ar
 NULL_TREE, NULL_TREE, entering_scope,
 tf_warning_or_error | tf_user);
 
-  // If entering a scope, correct the lookup to account for constraints.
-  if (entering_scope)
+  // If entering a scope of a template, correct the lookup to 
+  // account for constraints.
+  if (flag_concepts 
+  && entering_scope 
+  && CLASS_TYPE_P (type) 
+  && CLASSTYPE_IS_TEMPLATE (type))
 type = fixup_template_type (type);
 
   if (type == error_mark_node)


Re: [c++-concepts] variable concept fixes

2014-08-21 Thread Andrew Sutton
Ah... thanks for the clarification. Fixed (and committed).

Andrew

On Thu, Aug 21, 2014 at 4:26 AM, Paolo Carlini  wrote:
> Hi Andrew,
>
>
> On 08/20/2014 11:08 PM, Andrew Sutton wrote:
>>>
>>> On 08/20/2014 08:56 PM, Andrew Sutton wrote:
>>>>
>>>> +  return VAR_P (decl)
>>>> + && DECL_LANG_SPECIFIC (decl)
>>>> + && DECL_DECLARED_CONCEPT_P (decl);
>>>
>>> this is brittle from the formatting point of view. Please double check in
>>> detail what I'm going to say, but I think that in such cases you simply
>>> want
>>> to wrap the whole thing in round parentheses.
>>
>> Sorry, did you just mean to wrap the entire conjunction in parens? I'm
>> trying to find the formatting guidelines to check, but not succeeding
>> at the moment.
>
> Yes, I meant the whole conjunction, sorry about my sloppy language. In terms
> of GNU coding standards:
>
> http://www.gnu.org/prep/standards/standards.html#Formatting
>
> toward the end of the section, for example.
>
> Paolo.
Index: gcc/cp/decl.c
===
--- gcc/cp/decl.c	(revision 214241)
+++ gcc/cp/decl.c	(working copy)
@@ -6264,9 +6264,9 @@ value_dependent_init_p (tree init)
 static inline bool
 is_concept_var (tree decl) 
 {
-  return VAR_P (decl) 
- && DECL_LANG_SPECIFIC (decl)
- && DECL_DECLARED_CONCEPT_P (decl);
+  return (VAR_P (decl) 
+  && DECL_LANG_SPECIFIC (decl)
+  && DECL_DECLARED_CONCEPT_P (decl));
 }
 
 /* Finish processing of a declaration;


[c++-concepts] constrained friends

2014-08-21 Thread Andrew Sutton
Added tests for constrained friends.  No code, we already to the right thing.

2014-08-15  Andrew Sutton  

Add tests for constrained friends.
* gcc/testsuite/g++.dg/concepts/friend1.C: New.
* gcc/testsuite/g++.dg/concepts/friend2.C: New.

Andrew
Index: gcc/testsuite/g++.dg/concepts/friend2.C
===
--- gcc/testsuite/g++.dg/concepts/friend2.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/friend2.C	(revision 0)
@@ -0,0 +1,20 @@
+// { dg-options "-std=c++1z" }
+
+template
+  concept bool Eq() { return requires(T t) { t == t; }; }
+
+template struct Foo { };
+
+template
+  struct S { // { dg-error "constraint failure" }
+template friend class Bar;
+
+friend class Foo;
+  };
+
+struct X { };
+
+int main() {
+  S si; // OK
+  S sx;
+}
Index: gcc/testsuite/g++.dg/concepts/friend1.C
===
--- gcc/testsuite/g++.dg/concepts/friend1.C	(revision 0)
+++ gcc/testsuite/g++.dg/concepts/friend1.C	(revision 0)
@@ -0,0 +1,33 @@
+// { dg-options "-std=c++1z" }
+
+template
+  concept bool Eq() { return requires(T t) { t == t; }; }
+
+struct Nt {
+  template friend void f(T) { }
+} nt;
+
+template struct S;
+
+template
+  void proc(S*);
+
+template
+  struct S {
+friend bool operator==(S, S) requires Eq() { return true; }
+
+friend void proc<>(S*); // { dg-error "does not match any template declaration" }
+  };
+
+struct X { } x;
+
+int main() {
+  f(0); // OK
+  f(x); // { dg-error "cannot call" }
+
+  S si;
+  si == si; // OK
+
+  S sx; 
+  sx == sx; // { dg-error "no match" }
+}


[c++-concepts] cleanup expressions

2014-10-13 Thread Andrew Sutton
Sometimes, cleanup_point_exprs are being added to concept definitions.
This patch allows that to happen, but removes the cleanup point during
normalization.

2014-10-13  Andrew Sutton  

Fix bug related to cleanup expressions in concept definitions.
* gcc/cp/constraint.cc (check_function_concept): See through
cleanup handlers when checking the body of a function.
(normalize_cast): Removed. Handled in a default case.
(normalize_cleanup_point): New. Normalize the expression without
the cleanup handler.

Andrew Sutton


Re: [c++-concepts] cleanup expressions

2014-10-13 Thread Andrew Sutton
And here's the patch:


Andrew Sutton


On Mon, Oct 13, 2014 at 3:33 PM, Andrew Sutton
 wrote:
> Sometimes, cleanup_point_exprs are being added to concept definitions.
> This patch allows that to happen, but removes the cleanup point during
> normalization.
>
> 2014-10-13  Andrew Sutton  
>
> Fix bug related to cleanup expressions in concept definitions.
> * gcc/cp/constraint.cc (check_function_concept): See through
> cleanup handlers when checking the body of a function.
> (normalize_cast): Removed. Handled in a default case.
> (normalize_cleanup_point): New. Normalize the expression without
>     the cleanup handler.
>
> Andrew Sutton
Index: constraint.cc
===
--- constraint.cc	(revision 215720)
+++ constraint.cc	(working copy)
@@ -285,6 +285,14 @@ check_function_concept (tree fn)
   tree body = DECL_SAVED_TREE (fn);
   if (TREE_CODE (body) == BIND_EXPR)
 body = BIND_EXPR_BODY (body);
+  
+  // Sometimes a funciton call results the creation of clean up
+  // points. Allow these to be preserved in the body of the 
+  // constraint, as we might actually need them for some constexpr
+  // evaluations.
+  if (TREE_CODE (body) == CLEANUP_POINT_EXPR)
+body = TREE_OPERAND(body, 0);
+
   if (TREE_CODE (body) != RETURN_EXPR)
 error_at (loc, "function concept definition %qD has multiple statements", 
   fn);
@@ -316,9 +324,9 @@ tree normalize_expr_req (tree);
 tree normalize_type_req (tree);
 tree normalize_nested_req (tree);
 tree normalize_var (tree);
+tree normalize_cleanup_point (tree);
 tree normalize_template_id (tree);
 tree normalize_stmt_list (tree);
-tree normalize_cast (tree);
 tree normalize_atom (tree);
 
 // Reduce the requirement T into a logical formula written in terms of
@@ -383,12 +391,12 @@ normalize_expr (tree t)
 case TEMPLATE_ID_EXPR: 
   return normalize_template_id (t);
 
-case CAST_EXPR:
-  return normalize_cast (t);
-
 case BIND_EXPR:
   return normalize_node (BIND_EXPR_BODY (t));
 
+case CLEANUP_POINT_EXPR:
+  return normalize_cleanup_point (t);
+
 // Do not recurse.
 case TAG_DEFN: 
   return NULL_TREE;
@@ -655,12 +663,11 @@ normalize_requires (tree t)
   return t;
 }
 
-// Normalize a cast expression.
+// Normalize a cleanup point by normalizing the underlying
+// expression.
 tree
-normalize_cast (tree t) 
-{
-  // return normalize_node (TREE_VALUE (TREE_OPERAND (t, 0)));
-  return normalize_atom (t);
+normalize_cleanup_point (tree t) {
+  return normalize_node (TREE_OPERAND (t, 0));
 }
 
 // Normalize an atomic expression by performing some basic checks.


[c++-concepts] introduction syntax regression

2014-10-13 Thread Andrew Sutton
The original patch for concept introductions was not popping a
deferred access check. This fixes that problem, although I'm not sure
if we need to defer access checks at all.

2014-10-13  Andrew Sutton  

Fix regression related to concept introductions.
* gcc/cp/constraint.cc (cp_parser_template_declaration_after_exp):
Pop deferred access checks afer parsing the introduction.


Andrew Sutton
Index: parser.c
===
--- parser.c	(revision 214991)
+++ parser.c	(working copy)
@@ -24409,19 +24409,21 @@ cp_parser_template_declaration_after_exp
 	= current_template_reqs;
 	}
 }
-  else if(flag_concepts)
+  else if (flag_concepts)
 {
   need_lang_pop = false;
   checks = NULL;
   saved_template_reqs = release (current_template_reqs);
-  push_deferring_access_checks (dk_deferred);
 
   // Scope may be changed by a nested-name-specifier.
   tree saved_scope = parser->scope;
   tree saved_qualifying_scope = parser->qualifying_scope;
   tree saved_object_scope = parser->object_scope;
 
+  push_deferring_access_checks (dk_deferred);
   parameter_list = cp_parser_template_introduction (parser);
+  pop_deferring_access_checks ();
+
   if (parameter_list == error_mark_node)
 {
 	  // Restore template requirements before returning.


[c++-concepts]

2014-10-20 Thread Andrew Sutton
Fixing issues reported by users.

2014-10-20  Andrew Sutton  

Fixing user-reported issues and regressions
* gcc/cp/parser.c (cp_parser_template_declaration_after_exp):
Only pop access checks on failed parsing.
* gcc/cp/pt.cpp (type_dependent_expr_p): Always treat a
requires-expr as if dependently typed. Otherwise, we try to
evaluate these expressions when they have dependent types.
* gcc/cp/constriant.cc (normalize_stmt_list): Remove unused
function.
(normalize_call): Don't fold constraints during normalization.
* gcc/testsuite/g++.dg/concepts/decl-diagnose.C: Update diagnostics.

Andrew Sutton
Index: pt.c
===
--- pt.c	(revision 214991)
+++ pt.c	(working copy)
@@ -21646,6 +21646,16 @@ type_dependent_expression_p (tree expres
 	return dependent_type_p (type);
 }
 
+  // A requires expression has type bool, but is always treated as if
+  // it were a dependent expression.
+  //
+  // FIXME: This could be improved. Perhaps the type of the requires
+  // expression depends on the satisfaction of its constraints. That
+  // is, its type is bool only if its substitution into its normalized
+  // constraints succeeds.
+  if (TREE_CODE (expression) == REQUIRES_EXPR)
+return true;
+
   if (TREE_CODE (expression) == SCOPE_REF)
 {
   tree scope = TREE_OPERAND (expression, 0);
Index: constraint.cc
===
--- constraint.cc	(revision 216159)
+++ constraint.cc	(working copy)
@@ -326,7 +326,6 @@ tree normalize_nested_req (tree);
 tree normalize_var (tree);
 tree normalize_cleanup_point (tree);
 tree normalize_template_id (tree);
-tree normalize_stmt_list (tree);
 tree normalize_atom (tree);
 
 // Reduce the requirement T into a logical formula written in terms of
@@ -559,13 +558,13 @@ normalize_call (tree t)
   tree fn = TREE_VALUE (check);
   tree args = TREE_PURPOSE (check);
 
-  // Reduce the body of the function into the constriants language.
+  // Normalize the body of the function into the constriants language.
   tree body = normalize_constraints (DECL_SAVED_TREE (fn));
   if (!body)
 return error_mark_node;
 
   // Instantiate the reduced results using the deduced args.
-  tree result = tsubst_constraint_expr (body, args, false);
+  tree result = tsubst_constraint_expr (body, args, true);
   if (result == error_mark_node)
 return error_mark_node;
 
Index: testsuite/g++.dg/concepts/decl-diagnose.C
===
--- testsuite/g++.dg/concepts/decl-diagnose.C	(revision 214241)
+++ testsuite/g++.dg/concepts/decl-diagnose.C	(working copy)
@@ -4,12 +4,12 @@ typedef concept int CINT; // { dg-error
 
 void f(concept int); // { dg-error "a parameter cannot be declared 'concept'" }
 
-concept int f2(); // { dg-error "result must be bool" }
+concept int f2(); // { dg-error "return type" }
 concept bool f3();
 
 struct X
 {
-  concept int f4(); // { dg-error "result must be bool|declared with function parameters" }
+  concept int f4(); // { dg-error "return type|function parameters" }
   concept bool f5(); // { dg-error "declared with function parameters" }
   static concept bool f6(); // { dg-error "a concept cannot be a static member function" }
   static concept bool x; // { dg-error "declared 'concept'" }
Index: cp/parser.c
===
--- cp/parser.c	(revision 216159)
+++ cp/parser.c	(working copy)
@@ -24422,12 +24422,10 @@ cp_parser_template_declaration_after_exp
 
   push_deferring_access_checks (dk_deferred);
   parameter_list = cp_parser_template_introduction (parser);
-  pop_deferring_access_checks ();
-
   if (parameter_list == error_mark_node)
 {
-	  // Restore template requirements before returning.
 	  current_template_reqs = saved_template_reqs;
+  pop_deferring_access_checks ();
 	  return;
 }
 


[c++-concepts] Terse notation

2014-06-11 Thread Andrew Sutton
Sorry if you receive multiple versions of this. The original message
bounced (formatting).

Attached is a patch that greatly improves terse notation support for
generic functions and the use of concept names in
constrained-type-specifiers. There are actually 2 patches. The second
includes unit tests. Mostly, this is just cleaning up a previous
(hacky) commit. Most of the work is done in the parser, since terse
notation is largely syntactic.

Generic functions can be declared with auto and concept names in
namespace and class scope. Definitions can be matched to declarations,
and overloading is supported.

Various restrictions are put in place to prevent things like this:

  template // C constrains a type argument!

That holds when C constrains a template template argument also.

The patch also includes the initial parsing and semantic hooks for
handling constrained-type-specifiers in compound requirements:

  {expr} -> const auto&; // unnamed result type must form a valid type
  {expr} -> C; // unnamed result type satisfies the concept C

Semantics will come later.

Changelog:

2014-06-11  Andrew Sutton  
* gcc/cp/cp-tree.h (build_constrained_parameter): Renamed fro
describe_tempalte_parm.
* gcc/cp/parser.c (cp_check_constrained_type_parm): New. Prevent
declaration of cv-qualifed or non-id types.
(cp_constrained_type_template_parm): Renamed, check for invalid
specifiers.
(cp_constrained_template_template_parm): Renamed, check for invalid
specifiers.
(cp_constrained_non_type_tmeplate_parm): Renamed.
(cp_finish_constrained-parameter): Support checking of decarlarations.
(cp_check_concept_name): Renamed. Add initial support for auto
and constrained-type-specifiers in compound requirements.
(cp_parser_nonclass_name): Only check for concept names if -fconcepts
is on.
(cp_manage_requirements): New RAII guard for managinging the
current_template_reqs variable during declaration parsing.
(cp_paresr_trailing_requirements): Refactored common parsing
requirements from cp_parser_init_declarator and
cp_parser_member_declarator. Take terse constraints from implicit
parameter declarations.
(cp_parser_init_declarator): Cleanup, refactor requirement logic.
(cp_parser_type_id_1): Allow auto in compound requirements.
(cp_parser_member_declaration): Cleanup, refactor requirement logic.
(cp_parser_compound_requirement): Note parsing state for the
trailing-type-id so we can get auto and constrained-type-specifiers.
(cp_parser_function_definition_after_decl): Remove broken constraint
association.
* gcc/cp/parser.h (cp_parser): New member.
* gcc/cp/constraint.cc (finish_validtype_expr): Initial (non-)handling
of auto in type requirements.
(finish_concept_name): Moved to cp_check_concept_name.
* gcc/testuite/g++.dg/concepts/constrained-parm.C: New test.
* gcc/testuite/g++.dg/concepts/generic-fn.C: New test.

Andrew Sutton
Index: constrained-parm.C
===
--- constrained-parm.C	(revision 0)
+++ constrained-parm.C	(revision 0)
@@ -0,0 +1,13 @@
+// { dg-options "-std=c++1y" }
+
+template
+  concept bool C() { return __is_class(T); }
+
+template struct S1 { };// { dg-error "cv-qualified" }
+template struct S2 { }; // { dg-error "cv-qualified" }
+template struct S3 { }; // { dg-error "invalid" }
+template struct S3a { };  // { dg-error "invalid" }
+template struct S3b { };  // { dg-error "invalid" }
+template struct S4 { }; // { dg-error "invalid" }
+template struct S4 { };   // { dg-error "invalid|expected" } 
+template struct S5 { };  // { dg-error "invalid" }
Index: generic-fn.C
===
--- generic-fn.C	(revision 0)
+++ generic-fn.C	(revision 0)
@@ -0,0 +1,108 @@
+// { dg-options "-std=c++1y" }
+
+#include 
+
+template
+  concept bool C() { return __is_class(T); }
+
+struct S { } s;
+
+int called;
+
+// Basic terse notation
+void f(auto x) { called = 1; }
+void g(C x) { called = 2; }
+
+// Overloading generic functions
+void h(auto x) { called = 1; }
+void h(C x) { called = 2; }
+
+void p(auto x);
+void p(C x);
+
+struct S1 {
+  void f1(auto x) { called = 1; }
+  void f2(C x) { called = 2; }
+
+  void f3(auto x) { called = 1; }
+  void f3(C x) { called = 2; }
+};
+
+template
+  struct S2 {
+void f1(auto x) { called = 1; }
+void f2(C x) { called = 2; }
+
+void f3(auto x) { called = 1; }
+void f3(C x) { called = 2; }
+
+void h1(auto x);
+void h2(C x);
+
+void h3(auto x);
+void h3(C x);
+
+template
+  void g1(T t, U u) { called = 1; }
+
+template
+  void g2(T t, U u);
+  

terse notation diagnostics

2014-06-12 Thread Andrew Sutton
Adds additional checks and tests for ill-formed programs.

2014-06-12  Andrew Sutton  
* gcc/cp/parser.c (cp_check_type_concept): New.
(cp_check_concept_name): Remove redundant condition from check.
Diagnose misuse of non-type concepts in constrained type specifiers.
* gcc/testuite/g++.dg/concepts/generic-fn.C: Add tests for
non-simple constrained-type-specifiers and nested-name-specifiers
in concept names.
* gcc/testuite/g++.dg/concepts/generic-fn-err.C: New tests for
diagnosing ill-formed programs.

Committed in r211585.

Andrew Sutton
Index: parser.c
===
--- parser.c	(revision 211476)
+++ parser.c	(working copy)
@@ -15132,11 +15132,22 @@ cp_parser_type_name (cp_parser* parser)
   return type_decl;
 }
 
-
+/// Returns true if proto is a type parameter, but not a template template
+/// parameter.
+static bool
+cp_check_type_concept (tree proto, tree fn) 
+{
+  if (TREE_CODE (proto) != TYPE_DECL) 
+{
+  error ("invalid use of non-type concept %qD", fn);
+  return false;
+}
+  return true;
+}
 
 // If DECL refers to a concept, return a TYPE_DECL representing the result
 // of using the constrained type specifier in the current context. 
-
+//
 // DECL refers to a concept if
 //   - it is an overload set containing a function concept taking a single
 // type argument, or
@@ -15173,9 +15184,13 @@ cp_check_concept_name (cp_parser* parser
 
   // In template paramteer scope, this results in a constrained parameter.
   // Return a descriptor of that parm.
-  if (template_parm_scope_p () && processing_template_parmlist)
+  if (processing_template_parmlist)
 return build_constrained_parameter (proto, fn);
 
+  // In any other context, a concept must be a type concept.
+  if (!cp_check_type_concept (proto, fn))
+return error_mark_node;
+
   // In a parameter-declaration-clause, constrained-type specifiers
   // result in invented template parameters.
   if (parser->auto_is_implicit_function_template_parm_p)
Index: generic-fn.C
===
--- generic-fn.C	(revision 211476)
+++ generic-fn.C	(working copy)
@@ -1,11 +1,16 @@
+// { dg-do run }
 // { dg-options "-std=c++1y" }
 
 #include 
+#include 
 
 template
   concept bool C() { return __is_class(T); }
 
-struct S { } s;
+template
+  concept bool Type() { return true; }
+
+struct S { };
 
 int called;
 
@@ -50,7 +55,43 @@ template
   };
 
 
+void ptr(C*) { called = 1; }
+void ptr(const C*) { called = 2; }
+
+void ref(C&) { called = 1; }
+void ref(const C&) { called = 2; }
+
+void 
+fwd_lvalue_ref(Type&& x) {
+  using T = decltype(x);
+  static_assert(std::is_lvalue_reference::value, "not an lvlaue reference");
+}
+
+void 
+fwd_const_lvalue_ref(Type&& x) {
+  using T = decltype(x);
+  static_assert(std::is_lvalue_reference::value, "not an lvalue reference");
+  using U = typename std::remove_reference::type;
+  static_assert(std::is_const::value, "not const-qualified");
+}
+
+void fwd_rvalue_ref(Type&& x) {
+  using T = decltype(x);
+  static_assert(std::is_rvalue_reference::value, "not an rvalue reference");
+}
+
+// Make sure we can use nested names speicifers for concept names.
+namespace N {
+  template
+concept bool C() { return true; }
+} // namesspace N
+
+void foo(N::C x) { }
+
 int main() {
+  S s;
+  const S cs;
+
   f(0); assert(called == 1);
   g(s); assert(called == 2);
 
@@ -60,7 +101,6 @@ int main() {
   S1 s1;
   s1.f1(0); assert(called == 1);
   s1.f2(s); assert(called == 2);
-  // s1.f2(0); // Error
 
   s1.f3(0); assert(called == 1);
   s1.f3(s); assert(called == 2);
@@ -68,26 +108,35 @@ int main() {
   S2 s2;
   s2.f1(0); assert(called == 1);
   s2.f2(s); assert(called == 2);
-  // s2.f2(0); // Error
 
   s2.f3(0); assert(called == 1);
   s2.f3(s); assert(called == 2);
 
   s2.h1(0); assert(called == 1);
   s2.h2(s); assert(called == 2);
-  // s2.h2(0); // Error
 
   s2.h3(0); assert(called == 1);
   s2.h3(s); assert(called == 2);
 
   s2.g1(s, s); assert(called == 1); 
-  // s2.g(s, 0); // Error
-  // s2.g(0, s); // Error
-
   s2.g2(s, s); assert(called == 2);
-  // s2.g(s, 0); // Error
+
+  ptr(&s); assert(called == 1);
+  ptr(&cs); assert(called == 2);
+
+  ref(s); assert(called == 1);
+  ref(cs); assert(called == 2);
+
+  // Check forwarding problems
+  fwd_lvalue_ref(s);
+  fwd_const_lvalue_ref(cs);
+  fwd_rvalue_ref(S());
+
+  foo(0);
 }
 
+// Test that decl/def matching works.
+
 void p(auto x) { called = 1; }
 void p(C x) { called = 2; }
 
Index: generic-fn-err.C
===
--- generic-fn-err.C	(revision 0)
+++ generic-fn-err.C	(revision 0)
@@ -0,0 +1,51 @@
+// { dg-options "-std=c++1y" }
+
+#include 
+
+template
+  concept bool C() { return __is_cla

partial-concept-ids

2014-06-12 Thread Andrew Sutton
Add support for partial concept ids. Mostly this just refactors the
basic support for concept names to also allow a template and extra
arguments.

Also added the missing .exp file for the test suite.

2014-06-12  Andrew Sutton  
* gcc/cp/constraint.cc (deduce_constrained_parameter): Refactor
common deduction framework into separate function.
(build_call_check): New.
(build_concept_check): Take additional arguments to support the
creation of constrained-type-specifiers from partial-concept-ids.
(build_constrained_parameter): Take arguments from a partial-concept-id.
* gcc/cp/cp-tree.h (build_concept_check, biuld_constrained_parameter):
Take a template argument list, defaulting to NULL_TREE.
* gcc/cp/parser.c (cp_parser_template_id): Check to see if a
template-id is a concept check.
(cp_check_type_concept): Reorder arguments
(cp_parser_allows_constrained_type_specifier): New. Check contexts
where a constrained-type-specifier is allowed.
(cp_maybe_constrained_type_specifier): New. Refactored common rules
for concept name checks.
(cp_maybe_partial_concept_id): New. Check for
constrained-type-specifiers.
* gcc/testuite/g++.dg/concepts/partial.C: New tests.
* gcc/testuite/g++.dg/concepts/partial-err.C: New tests.
* gcc/testuite/g++.dg/concepts/concepts.exp: Add missing test driver.

Andrew Sutton
Index: parser.c
===
--- parser.c	(revision 211585)
+++ parser.c	(working copy)
@@ -2523,7 +2523,10 @@ static tree cp_parser_make_typename_type
 static cp_declarator * cp_parser_make_indirect_declarator
  (enum tree_code, tree, cp_cv_quals, cp_declarator *, tree);
 
+/* Concept-related syntactic transformations */
 
+static tree cp_maybe_concept_name   (cp_parser *, tree);
+static tree cp_maybe_partial_concept_id (cp_parser *, tree, tree);
 
 // -- //
 // Unevaluated Operand Guard
@@ -13775,6 +13778,11 @@ cp_parser_template_id (cp_parser *parser
 		   || TREE_CODE (templ) == OVERLOAD
 		   || BASELINK_P (templ)));
 
+  // If the template + args designate a concept, then return
+  // something else.
+  if (tree id = cp_maybe_partial_concept_id (parser, templ, arguments))
+return id;
+
   template_id = lookup_template_function (templ, arguments);
 }
 
@@ -14995,7 +15003,8 @@ cp_parser_simple_type_specifier (cp_pars
 	}
   /* Otherwise, look for a type-name.  */
   else
-	type = cp_parser_type_name (parser);
+type = cp_parser_type_name (parser);
+  
   /* Keep track of all name-lookups performed in class scopes.  */
   if (type
 	  && !global_p
@@ -15071,6 +15080,7 @@ cp_parser_simple_type_specifier (cp_pars

type-name:
  concept-name
+ partial-concept-id
 
concept-name:
  identifier
@@ -15092,6 +15102,7 @@ cp_parser_type_name (cp_parser* parser)
 /*check_dependency_p=*/true,
 /*class_head_p=*/false,
 /*is_declaration=*/false);
+
   /* If it's not a class-name, keep looking.  */
   if (!cp_parser_parse_definitely (parser))
 {
@@ -15107,6 +15118,7 @@ cp_parser_type_name (cp_parser* parser)
 	 /*check_dependency_p=*/true,
 	 none_type,
 	 /*is_declaration=*/false);
+
   /* Note that this must be an instantiation of an alias template
 	 because [temp.names]/6 says:
 	 
@@ -15135,7 +15147,7 @@ cp_parser_type_name (cp_parser* parser)
 /// Returns true if proto is a type parameter, but not a template template
 /// parameter.
 static bool
-cp_check_type_concept (tree proto, tree fn) 
+cp_check_type_concept (tree fn, tree proto) 
 {
   if (TREE_CODE (proto) != TYPE_DECL) 
 {
@@ -15145,57 +15157,58 @@ cp_check_type_concept (tree proto, tree
   return true;
 }
 
-// If DECL refers to a concept, return a TYPE_DECL representing the result
-// of using the constrained type specifier in the current context. 
-//
-// DECL refers to a concept if
-//   - it is an overload set containing a function concept taking a single
-// type argument, or
-//   - it is a variable concept taking a single type argument
-//
-//
-// TODO: DECL could be a variable concept.
+/// Returns true if the parser is in a context that allows the
+/// use of a constrained type specifier.
+static inline bool
+cp_parser_allows_constrained_type_specifier (cp_parser *parser)
+{
+  return flag_concepts 
+&& (processing_template_parmlist
+|| parser->auto_is_implicit_function_template_parm_p
+|| parser->in_result_type_constraint_p);
+}
+
+// Check if DECL and ARGS can form a constrained-type-specifier. If ARGS
+// is non-null, we try to form a concept check of the form DECL
+// where ? is a placeholder for any kind of template argument. If ARGS
+// is NULL, then we try to form a concept che

Re: [c++-concepts] Fix assertion failure with cp_maybe_constrained_type_specifier

2014-06-24 Thread Andrew Sutton
Braden,

Did you have a specific test case that causes this breakage? I have a
feeling that if we're missing base-link nodes in one place, we'll miss
them in others too.

Andrew


On Tue, Jun 17, 2014 at 4:54 AM, Braden Obrzut  wrote:
> cp_maybe_constrained_type_specifier asserted that the decl passed in would
> be of type OVERLOAD, however a clean build of the compiler was broken since
> it could also be a BASELINK.  I'm not entirely sure when this is the case,
> except that it seems to happen with class member templates as it also caused
> a test case in my next patch to fail.  The solution is to check for a
> BASELINK and extract the functions from it.
>
> The possibility of decl being a BASELINK is asserted near the call in
> cp_parser_template_id (cp_maybe_partial_concept_id just calls the function
> in question at this time).
>
> 2014-06-17  Braden Obrzut  
> * gcc/cp/parser.c (cp_maybe_constrained_type_specifier): Fix assertion
> failure if baselink was passed in as decl.
>


Re: [c++-concepts] Fix assertion failure with cp_maybe_constrained_type_specifier

2014-06-24 Thread Andrew Sutton
Committed as r211935. I updated the patch to add a more appropriate
comment and changelog entry.

Andrew

On Tue, Jun 24, 2014 at 8:07 AM, Ed Smith-Rowland <3dw...@verizon.net> wrote:
> I saw this during bootstrap.  I've verified that the patch works (I was
> working on similar).
>
> Ed
>
Index: parser.c
===
--- parser.c	(revision 211591)
+++ parser.c	(working copy)
@@ -15175,9 +15175,15 @@ cp_parser_allows_constrained_type_specif
 static tree
 cp_maybe_constrained_type_specifier (cp_parser *parser, tree decl, tree args)
 {
-  gcc_assert (TREE_CODE (decl) == OVERLOAD);
   gcc_assert (args ? TREE_CODE (args) == TREE_VEC : true);
 
+  // If we get a reference to a member function, allow the referenced
+  // functions to participate in this resolution: the baselink may refer
+  // to a static member concept.
+  if (BASELINK_P (decl))
+decl = BASELINK_FUNCTIONS (decl);
+  gcc_assert (TREE_CODE (decl) == OVERLOAD);
+
   // Don't do any heavy lifting if we know we're not in a context
   // where it could succeed.
   if (!cp_parser_allows_constrained_type_specifier (parser))


[c++-concepts] small pretty printing fix

2014-06-24 Thread Andrew Sutton
This helps improve debug output. When pretty printing template args
including a placeholder, show  instead of a dump_expr
error.

2014-06-24  Andrew Sutton  
  * gcc/cp/error.C (dump_expr): Pretty print placeholder to improve
  debug output.

Committed as r211942.

Andrew
Index: gcc/cp/error.c
===
--- gcc/cp/error.c	(revision 211415)
+++ gcc/cp/error.c	(working copy)
@@ -2656,6 +2656,10 @@ dump_expr (cxx_pretty_printer *pp, tree
 case CONSTEXPR_EXPR:
   pp_cxx_constexpr_expr (cxx_pp, t);
 
+case PLACEHOLDER_EXPR:
+  pp_cxx_ws_string (cxx_pp, "");
+  break;
+
   /*  This list is incomplete, but should suffice for now.
 	  It is very important that `sorry' does not call
 	  `report_error_function'.  That could cause an infinite loop.  */


[c++-concepts] member concepts

2014-06-24 Thread Andrew Sutton
Actually allow member concepts in using shorthand notation.

2014-06-24  Andrew Sutton  
* gcc/cp/parser.c (cp_maybe_constrained_type_specifier): Defer
handling the BASELINK check until concept-resolution in order to
allow member conceps.
(cp_parser_nonclass_name): Also Check for concept-names when the
lookup finds a BASELINk.
* gcc/cp/constraint.cc: (resolve_constraint_check) If the call
target is a base-link, resolve against its overload set.
(build_concept_check): Update comments and variable names to
reflect actual processing.
* gcc/testuite/g++.dg/concepts/mem-concept.C: New test.
* gcc/testuite/g++.dg/concepts/mem-concept-err.C: New test.

Committed as r211946.

Andrew Sutton
Index: mem-concept.C
===
--- mem-concept.C	(revision 0)
+++ mem-concept.C	(revision 0)
@@ -0,0 +1,28 @@
+// { dg-options "-std=c++1y" }
+
+struct Base {
+  template
+static concept bool D() { return __is_same_as(T, int); }
+
+  template
+static concept bool E() { return __is_same_as(T, U); }
+};
+
+void f1(Base::D) { }
+void f2(Base::E x) { }
+
+template
+  struct S : Base {
+void f1(Base::D) { }
+void f2(Base::E x) { }
+  };
+
+int main() { 
+  f1(0);
+
+  f2(0.0);
+
+  S s;
+  s.f1(0);
+  s.f2(0);
+}
Index: mem-concept-err.C
===
--- mem-concept-err.C	(revision 0)
+++ mem-concept-err.C	(revision 0)
@@ -0,0 +1,40 @@
+// { dg-options "-std=c++1y" }
+
+
+// The following error is emitted without context. I'm not
+// certain why that would be the case. It comes as a result
+// of failing the declaration of S::f0().
+//
+//cc1plus: error: expected ';' at end of member declaration
+
+
+struct Base {
+  template
+bool C() const { return false; } // Not a concept!
+
+  template
+static concept bool D() { return __is_same_as(T, int); }
+
+  template
+static concept bool E() { return __is_same_as(T, U); }
+};
+
+void f1(Base::D) { }
+void f2(Base::E x) { }
+
+template
+  struct S : Base {
+void f0(Base::C x) { } // { dg-error "expected|type" }
+void f1(Base::D) { }
+void f2(Base::E x) { }
+  };
+
+int main() { 
+  f1('a'); // { dg-error "matching" }
+  f2(0);   // { dg-error "matching" }
+
+  S s;
+  s.f1('a'); // { dg-error "matching" }
+  s.f2('a'); // { dg-error "matching" }
+}
+
Index: pt.c
===
--- pt.c	(revision 211415)
+++ pt.c	(working copy)
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3.
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "print-tree.h"
 #include "stringpool.h"
 #include "varasm.h"
 #include "attribs.h"
Index: parser.c
===
--- parser.c	(revision 211935)
+++ parser.c	(working copy)
@@ -15168,6 +15168,7 @@ cp_parser_allows_constrained_type_specif
 || parser->in_result_type_constraint_p);
 }
 
+
 // Check if DECL and ARGS can form a constrained-type-specifier. If ARGS
 // is non-null, we try to form a concept check of the form DECL
 // where ? is a placeholder for any kind of template argument. If ARGS
@@ -15177,13 +15178,6 @@ cp_maybe_constrained_type_specifier (cp_
 {
   gcc_assert (args ? TREE_CODE (args) == TREE_VEC : true);
 
-  // If we get a reference to a member function, allow the referenced
-  // functions to participate in this resolution: the baselink may refer
-  // to a static member concept.
-  if (BASELINK_P (decl))
-decl = BASELINK_FUNCTIONS (decl);
-  gcc_assert (TREE_CODE (decl) == OVERLOAD);
-
   // Don't do any heavy lifting if we know we're not in a context
   // where it could succeed.
   if (!cp_parser_allows_constrained_type_specifier (parser))
@@ -15191,7 +15185,8 @@ cp_maybe_constrained_type_specifier (cp_
 
   // Try to build a call expression that evaluates the concept. This
   // can fail if the overload set refers only to non-templates.
-  tree call = build_concept_check (decl, build_nt(PLACEHOLDER_EXPR), args);
+  tree placeholder = build_nt(PLACEHOLDER_EXPR);
+  tree call = build_concept_check (decl, placeholder, args);
   if (call == error_mark_node)
 return NULL_TREE;
   
@@ -15291,7 +15286,8 @@ cp_parser_nonclass_name (cp_parser* pars
   //
   // TODO: The name could also refer to a variable template or an
   // introduction (if followed by '{').
-  if (flag_concepts && TREE_CODE (type_decl) == OVERLOAD)
+  if (flag_concepts && 
+(TREE_CODE (type_decl) == OVERLOAD || BASELINK_P (type_decl)))
   {
 // Determine whether the overload refers to a concept.
 if (tree decl = cp_maybe_concept_name (parser, ty

Re: [c++-concepts] Fix assertion failure with cp_maybe_constrained_type_specifier

2014-06-24 Thread Andrew Sutton
Weird.  Any chance you're doing a bootstrap build?

There was an earlier bootstrapping issue with this branch. We had
turned on -std=c++1y by default, and it was causing some conversion
errors with lvalue references to bitfields in libasan.

This doesn't *look* like a regression caused by concepts -- I don't
think I'm touching the initializer code at all.

Andrew Sutton


On Tue, Jun 24, 2014 at 11:42 AM, Ed Smith-Rowland <3dw...@verizon.net> wrote:
> I'm not sure the warning is correct in any case...
>
> In i386.h
> 
> struct stringop_algs
> {
>   const enum stringop_alg unknown_size;
>   const struct stringop_strategy {
> const int max;
> const enum stringop_alg alg;
> int noalign;
>   } size [MAX_STRINGOP_ALGS];
> };
>
> in i386.c
> ---
> static stringop_algs ix86_size_memcpy[2] = {
>   {rep_prefix_1_byte, {{-1, rep_prefix_1_byte, false}}},
>   {rep_prefix_1_byte, {{-1, rep_prefix_1_byte, false;
> static stringop_algs ix86_size_memset[2] = {
>   {rep_prefix_1_byte, {{-1, rep_prefix_1_byte, false}}},
>   {rep_prefix_1_byte, {{-1, rep_prefix_1_byte, false;
>


Re: Re: [c++-concepts] Fix assertion failure with cp_maybe_constrained_type_specifier

2014-06-25 Thread Andrew Sutton
> I did a full 3-stage bootstrap which is the default these days.
> I'll try --disable-bootstrap and see what happens.

I just did a full bootstrap build and got the same errors. The errors
are correct for C++11, which was enabled by default in this branch.
IIRC, aggregate initialization requires the initializer-clause to
match the structure exactly (or at least not omit any const
initializers?)

I think this was something Gaby wanted when we created the branch, but
I'm not sure it's worth keeping because of the bootstrapping errors. I
could reset the default dialect to 98 and turn on concepts iff 1y is
enabled, or I could turn on 1y if -fconcepts is enabled.

Thoughts?

Andrew


[c++-concepts] constraint folding

2014-06-25 Thread Andrew Sutton
Updating constraint parsing to match changes to spec. Constraints must
always left unfolded, even when non-dependent, until they are
evaluated.

2014-06-25  Andrew Sutton  
* gcc/cp/parser.c (cp_parser_requires_clause): Don't fold expressions
 when parsing a requires-clause.
* gcc/cp/constraint.cc (reduce_requirements): Don't fold
 expressions during constraint normalization.

Andrew Sutton


Re: [c++-concepts] Change constraint equivalence

2014-06-27 Thread Andrew Sutton
> Please drop gcc/ and gcc/testsuite/ prefixes (the former goes to
> cp/ChangeLog, the latter to testsuite/ChangeLog).

This is the format (and file) that Gaby requested when we started the
project. We can certainly distribute the entries, but I don't know if
its worthwhile right now.

Andrew


[c++-concepts] constraint association

2014-06-28 Thread Andrew Sutton
After merging from trunk this morning, I discovered that
DECL_SIZE_UNIT is now being used to store lists of specializations. I
had been using that to store template constraints. Oops.

This patch moves constraints outside the usual tree structures into an
association maintained in a hash table. It also lays the framework for
allowing constraints to be associated with any _*DECL node (templates,
functions, variables, types, etc).

Changelog below; committed as 212103.

2014-06-28  Andrew Sutton  
* gcc/cp/cp-tree.h (DECL_CONSTRAINTS): Remove this macro; use
get_constraints instead.
(set_constraints): new.
* gcc/cp/cxx-pretty-print.c (pp_cxx_template_declaration): Use
get_constraints.
* gcc/cp/pt.c (get_specialization_constraints): Use get_constraints.
(build_template_decl): Use get_constraints.
(process_partial_specialization): Use get_constraints.
(add_inherited_template_parms): Use get_constraints.
(redeclare_class_template): Use get_constraints.
(is_compatible_template_arg): Use get_constraints.
(tsubst_friend_class): Use get_constraints.
(tsubst_decl): Uset get_constraints.
* gcc/cp/semantics.c (finish_template_template_parm): Use
get_constraints.
(fixup_template_type): Use get_constraints.
* gcc/cp/constraint.cc (constraints): New global association
of declarations to constraints.
(get_constraints): Return the associated constraints from the
hash table.
(set_constraints): New. Associate constraints with a declaration.
(check_template_constraints): Use get_constraints.
(equivalently_constrained): Use get_constraints.
(more_constrained): Use get_constraints.
(diagnose_constraints): Use get_constraints.
* gcc/testsuite/g++.dg/concepts/partial-spec.C: New.

Andrew
Index: gcc/cp/cxx-pretty-print.c
===
--- gcc/cp/cxx-pretty-print.c	(revision 212100)
+++ gcc/cp/cxx-pretty-print.c	(working copy)
@@ -2220,7 +2220,7 @@ pp_cxx_template_declaration (cxx_pretty_
   pp_newline_and_indent (pp, 3);
 }
 
-  if (tree c = DECL_CONSTRAINTS (t))
+  if (tree c = get_constraints (t))
 {
   pp_cxx_ws_string (pp, "requires");
   pp->expression (CI_REQUIREMENTS (c));
Index: gcc/cp/pt.c
===
--- gcc/cp/pt.c	(revision 212101)
+++ gcc/cp/pt.c	(working copy)
@@ -846,7 +846,7 @@ get_specialization_constraints (tree typ
   // that type. If it is an explicit specialization, return null since
   // non-templates cannot be constrained.
   if (tree d = get_specializing_template_decl (type))
-return DECL_CONSTRAINTS (d);
+return get_constraints (d);
   else
 return NULL_TREE;
 }
@@ -4147,10 +4147,10 @@ build_template_decl (tree decl, tree par
 {
   tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
   DECL_TEMPLATE_PARMS (tmpl) = parms;
-  DECL_CONSTRAINTS (tmpl) = constr;
   DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl);
   DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
   DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
+  set_constraints (tmpl, constr);
 
   return tmpl;
 }
@@ -4319,7 +4319,7 @@ process_partial_specialization (tree dec
  arguments but different constraints. */
   tree main_type = TREE_TYPE (maintmpl);
   tree main_args = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (main_type));
-  tree main_constr = DECL_CONSTRAINTS (maintmpl);
+  tree main_constr = get_constraints (maintmpl);
   if (comp_template_args (inner_args, main_args)
   && equivalent_constraints (current_template_reqs, main_constr))
 error ("partial specialization %qT does not specialize any "
@@ -5229,13 +5229,13 @@ add_inherited_template_parms (tree fn, t
   // If the inherited constructor was constrained, then also
   // propagate the constraints to the new declaration by
   // rewriting them in terms of the local template parameters.
-  tree cons = DECL_CONSTRAINTS (inherited);
+  tree cons = get_constraints (inherited);
   if (cons)
 {
   ++processing_template_decl;
   tree reqs = instantiate_requirements (CI_REQUIREMENTS (cons), args);
   --processing_template_decl;
-  DECL_CONSTRAINTS (tmpl) = make_constraints (reqs);
+  set_constraints (tmpl, make_constraints (reqs));
 }
 
   DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args);
@@ -5354,7 +5354,7 @@ redeclare_class_template (tree type, tre
 }
 
   // Cannot redeclare a class template with a different set of constraints. 
-  if (!equivalent_constraints (DECL_CONSTRAINTS (tmpl), cons))
+  if (!equivalent_constraints (get_constraints (tmpl), cons))
 {
   error_at (input_location, "redeclaration %q#D with different "
 "constraints", tmpl);
@@ -6586,8 +6586,8 @@ is_compati

[c++-concepts] Compiler options/bootstrap

2014-06-28 Thread Andrew Sutton
This patch restores C++98 as the default language in this branch and
disables -fconcepts by default. Using -std=c++1z will enable
-fconcepts.

I wanted to give an error if -fconcepts is used with dialect <= cxx11,
but I didn't find the right place to put the check.

This also adds a new format specifier ("Z") to the cxxdiag flags. That
warning was turning into an error in the bootstrap build. FYI: The
bootstrap builds cleanly for me now.

Committed in r212105.

2014-06-28  Andrew Sutton  
* gcc/c-family/c.opt (flag_concepts): Don't enable by default.
* gcc/c-family/c-opts.c (set_std_cxx1z): Enable concepts if
-std=cxx1z is selected.
* gcc/c-family/c-format.c (gcc_cxxdia): Add "Z" as format specifier.
* gcc/cp/c-common.c (cxx_dialect): Make -std=c++98 the default
language again.
* gcc/cp/lex.c (cxx_init): Don't set flag_concepts explicitly.
* gcc/testsuite/g++.dg/concepts/*.C: Updat build flags.

Andrew


Re: [c++-concepts] code review

2015-05-01 Thread Andrew Sutton
> It looks like things are coming together pretty well.  What's your feeling
> about readiness to merge into the trunk?  Is the branch down to no
> regressions?

They are coming together pretty well. We have one major unit test
failure involving template introductions (Braden is working on it),
one involving constraint equivalence that I plan to tackle next week.

Other than those issues, which I hope to clear up next week, I think it's ready.

> See you on Monday!

Unfortunately, I won't be attending.

Andrew

>
>> @@ -4146,21 +4146,21 @@ build_new_function_call (tree fn, vec
>> **args, bool koenig_p,
>>if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
>>  {
>>/* If overload resolution selects a specialization of a
>> + function concept for non-dependent template arguments,
>> + the expression is true if the constraints are satisfied
>> + and false otherwise.
>>
>>   NOTE: This is an extension of Concepts Lite TS that
>>   allows constraints to be used in expressions. */
>> +  if (flag_concepts && !processing_template_decl)
>>  {
>>tree tmpl = DECL_TI_TEMPLATE (cand->fn);
>> +  tree targs = DECL_TI_ARGS (cand->fn);
>>tree decl = DECL_TEMPLATE_RESULT (tmpl);
>> +  if (DECL_DECLARED_CONCEPT_P (decl)
>> +  && !uses_template_parms (targs)) {
>> +return evaluate_function_concept (decl, targs);
>
>
> If processing_template_decl is false, uses_template_parms should always be
> false as well.
>
>> +function_concept_check_p (tree t)
>
>
>> +  tree fn = CALL_EXPR_FN (t);
>> +  if (TREE_CODE (fn) == TEMPLATE_ID_EXPR
>> +  && TREE_CODE (TREE_OPERAND (fn, 0)) == OVERLOAD)
>> +{
>> +  tree f1 = OVL_FUNCTION (TREE_OPERAND (fn, 0));
>
>
> I think you want get_first_fn here.
>
>>if (TEMPLATE_PARM_CONSTRAINTS (current_template_parms))
>> -TYPE_CANONICAL (type) = type;
>> +SET_TYPE_STRUCTURAL_EQUALITY (type);
>
>
> This seems like papering over an underlying issue.  What was the testcase
> that motivated this change?
>
>> @@ -11854,7 +11854,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t
>> complain)
>> -   if (!spec)
>> +   if (!spec && DECL_LANG_SPECIFIC (t))
>> -   if (!local_p)
>> +   if (!local_p && DECL_LANG_SPECIFIC (r))
>
>
> What motivated these changes?  From the testcase, it seems that you're
> getting here with the decl for "using TD = int", which shouldn't happen.
>
>> @@ -1159,7 +1159,6 @@ check_noexcept_r (tree *tp, int * /*walk_subtrees*/,
>> void * /*data*/)
>> -  tree type = TREE_TYPE (TREE_TYPE (fn));
>> -  if (!TYPE_NOTHROW_P (type))
>> +  if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
>
>
> The old code was incorrectly assuming that CALL_EXPR_FN is always a function
> pointer, but your new code seems to be incorrectly assuming that it's always
> a function or an expression taking the address of a function; I think this
> will break on a call to a function pointer variable.
>
>> @@ -3481,13 +3481,27 @@ cxx_eval_constant_expression (const constexpr_ctx
>> *ctx, tree t,
>>  case REQUIRES_EXPR:
>> +  if (!processing_template_decl)
>> +return evaluate_constraint_expression (t, NULL_TREE);
>> +  else
>> +*non_constant_p = true;
>> +return t;
>
>
> We shouldn't get here with a dependent REQUIRES_EXPR (or any dependent
> expression), so we shouldn't ever hit the else clause.
>
>> @@ -18063,18 +18063,41 @@ cp_parser_declarator (cp_parser* parser,
>> +  /* Function declarations may be followed by a trailing
>> + requires-clause. Declarators for function declartions
>> + are function declarators wrapping an id-declarator.
>> + If the inner declarator is anything else, it does not
>> + declare a function. These may also be reference or
>> + pointer declarators enclosing such a function declarator.
>> + In the declaration :
>> +
>> +int *f(args)
>> +
>> + the declarator is *f(args).
>> +
>> + Abstract declarators cannot have a requires-clauses
>> + because they do not declare functions. Here:
>>
>>  void f() -> int& requires false
>>
>> + The trailing return type contains an abstract declarator,
>> + and the requires-clause applies to the function
>> + declaration and not the abstract declarator.  */
>> +  if (flag_concepts && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
>>  {
>> +  /* We could have things like *f(args) or &f(args).
>> + Look inside references and pointers.  */
>> +  cp_declarator* p = declarator;
>> +  if (p->kind == cdk_reference || p->kind == cdk_pointer)
>> +p = p->declarator;
>> +
>> +  /* Pointers or references with no name, or functions
>> + with no name cannot have constraints.  */
>> +  if (!p || !p->declarator)
>> +return declarator;
>> +
>> +  /* Look for f(args) but not (*f)(args).  */
>> +  

Re: [c++-concepts] code review

2015-05-08 Thread Andrew Sutton
Today is the first day I've had to look at these comments.


>>if (TEMPLATE_PARM_CONSTRAINTS (current_template_parms))
>> -TYPE_CANONICAL (type) = type;
>> +SET_TYPE_STRUCTURAL_EQUALITY (type);
>
>
> This seems like papering over an underlying issue.  What was the testcase
> that motivated this change?


It almost certainly is, but I haven't been able to find or write a
minimal test case that reproduces the reason for failure. Basically,
we end up with multiple specializations having the same type but
different constraints (since constraints are attached to the
declaration and not the type itself).

I think that I'm running into the same problems with auto a
placeholder in recent commits.


>> @@ -11854,7 +11854,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t
>> complain)
>> -   if (!spec)
>> +   if (!spec && DECL_LANG_SPECIFIC (t))
>> -   if (!local_p)
>> +   if (!local_p && DECL_LANG_SPECIFIC (r))
>
>
> What motivated these changes?  From the testcase, it seems that you're
> getting here with the decl for "using TD = int", which shouldn't happen.


That's the pretty much it... I suppose we could guard against
substituting into these kinds of declarations from within
tsubst_type_requirement and satisfy_type_constraint. To me it seems
like tsubst should work, but just return the same thing.


>> @@ -1159,7 +1159,6 @@ check_noexcept_r (tree *tp, int * /*walk_subtrees*/,
>> void * /*data*/)
>> -  tree type = TREE_TYPE (TREE_TYPE (fn));
>> -  if (!TYPE_NOTHROW_P (type))
>> +  if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
>
>
> The old code was incorrectly assuming that CALL_EXPR_FN is always a function
> pointer, but your new code seems to be incorrectly assuming that it's always
> a function or an expression taking the address of a function; I think this
> will break on a call to a function pointer variable.


I will experiment.


>> @@ -3481,13 +3481,27 @@ cxx_eval_constant_expression (const constexpr_ctx
>> *ctx, tree t,
>>  case REQUIRES_EXPR:
>> +  if (!processing_template_decl)
>> +return evaluate_constraint_expression (t, NULL_TREE);
>> +  else
>> +*non_constant_p = true;
>> +return t;
>
>
> We shouldn't get here with a dependent REQUIRES_EXPR (or any dependent
> expression), so we shouldn't ever hit the else clause.


IIRC we get here because of build_x_binary_op. It tries to build
non-dependent operands when the operands are not type-dependent.
requires-expressions have type bool, so they get run through the
constexpr evaluator even when processing_template_decl is true.

I've made requires-expressions instantiation dependent, but that
doesn't help in this case.


>> +static inline bool
>> +pending_expansion_p (tree t)
>> +{
>> +  return (TREE_CODE (t) == PARM_DECL && CONSTRAINT_VAR_P (t)
>> +  && PACK_EXPANSION_P (TREE_TYPE (t)));
>> +}
>
>
> What's the difference between this and function_parameter_pack_p?


Not a lot, except that replacing pending_expansion_p in one of the two
places that it's used causes ICEs :)  This function can almost
certainly be removed.


>> +check_implicit_conversion_constraint (tree t, tree args,
>> +  tsubst_flags_t complain, tree
>> in_decl)
>> +{
>> +  tree expr = ICONV_CONSTR_EXPR (t);
>> +
>> +  /* Don't tsubst as if we're processing a template. If we try
>> + to we can end up generating template-like expressions
>> + (e.g., modop-exprs) that aren't properly typed. */
>> +  int saved_template_decl = processing_template_decl;
>> +  processing_template_decl = 0;
>
>
> Why are we checking constraints when processing_template_decl is true?


IIRC I allow constraints to be evaluated in any context because it
lets us catch these kinds of errors:

template
void f()
{
  vector v; // error: constraints not satisfied
}


>> +  ++processing_template_decl;
>> +  tree constr = transform_expression (lift_function_definition (fn,
>> args));
>> +  --processing_template_decl;
>
>
> Why do you need to set processing_template_decl here and in other calls to
> transform_expression?  I don't notice anything that would be helped,
> especially now that you're using separate tree codes for constraints, though
> there is this in check_logical_expr:
>
>> +  /* Resolve the logical operator. Note that template processing is
>> + disabled so we get the actual call or target expression back.
>> + not_processing_template_sentinel sentinel.
>
>
> I guess that isn't needed anymore?


I've had problems in the past where substitution tries a little too
eagerly to fold expressions into constants --- especially type traits.
Those need to be preserved in the text for ordering.

Although I think this really only matters when you're instantiating a
class template whose members are constraints.


Andrew


[c++-concepts] merge from trunk

2014-11-13 Thread Andrew Sutton
I just merged the concepts branch with trunk, after fighting with the
testing framework for the past hour. There was a change to

gcc/testsuite/lib/prune.exp

yesterday that doesn't appear to be compatible with *something* in
this branch. It broke the entire test suite, giving the errors below
for every .exp file.

Using /home/faculty/asutton/local/share/dejagnu/baseboards/unix.exp as
board description file for target.
Using /home/faculty/asutton/local/share/dejagnu/config/unix.exp as
generic interface file for target.
Using 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/config/default.exp
as tool-and-target-specific interface file.
Running 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp
...
ERROR: tcl error sourcing
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp.
ERROR: couldn't compile regular expression pattern: quantifier operand invalid
while executing
"regsub -all "$srcdir\/" $text "" text"
(procedure "prune_gcc_output" line 50)
invoked from within
"prune_gcc_output $text"
(procedure "gcc-dg-prune" line 8)
invoked from within
"${tool}-dg-prune $target_triplet $comp_output"
(procedure "saved-dg-test" line 183)
invoked from within
"saved-dg-test 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/2105-1.c
{  -O0 } -w"
("eval" body line 1)
invoked from within
"eval saved-dg-test $args "
(procedure "dg-test" line 11)
invoked from within
"dg-test $test "$flags $flags_t" ${default-extra-flags}"
(procedure "gcc-dg-runtest" line 33)
invoked from within
"gcc-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] "" "-w""
(file 
"/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp"
line 30)
invoked from within
"source 
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp"
("uplevel" body line 1)
invoked from within
"uplevel #0 source
/home/faculty/asutton/Code/gcc/c++-concepts/gcc/testsuite/gcc.c-torture/compile/compile.exp"
invoked from within
"catch "uplevel #0 source $test_file_name""

I removed the offending line of code in this branch just to make the tests run.

That change does not affect any other builds on my system, so
something isn't being configured correctly. I just can't find what it
is.

Andrew


Re: Concepts code review

2014-11-16 Thread Andrew Sutton
>>> +// Bring the parameters of a function declaration back into
>>> +// scope without entering the function body. The declarator
>>> +// must be a function declarator. The caller is responsible
>>> +// for calling finish_scope.
>>> +void
>>> +push_function_parms (cp_declarator *declarator)
>>
>> I think if the caller is calling finish_scope, I'd prefer for the
>> begin_scope call to be there as well.
>>
> Even though Andrew said that this will change later for other reasons, it's
> a function I wrote so: I actually debated this with Andrew before.  My
> rationale for calling begin_scope in the function was that it feels
> consistent with the semantics of the call. Specifically it can be seen as
> reopening the function parameter scope.  Thus the call is balanced by
> calling finish_scope.  Either way would work of course, but perhaps it just
> needed a better name and/or comment?

In the process of removing constraints from lang_decl nodes, I also
ended up addressing a lot of the other constraint processing comments
-- it made sense to do it at the same time.

One of those was moving a requires-clause into a function declarator.
I had thought that this would prevent me from having to re-open that
scope, but it doesn't. The parameter scope is closed at a lower level
in the parse :/

So this issue is still around.

>>> +  // Save the current template requirements.
>>> +  saved_template_reqs = release (current_template_reqs);
>>
>>
>> It seems like a lot of places with saved_template_reqs variables could be
>> converted to use cp_manage_requirements.
>>
> Probably.  The instance you quoted isn't very trivial though.  The
> requirements are saved in two different branches and need to be restored
> before a certain point in the function.  Might just need to spend more time
> looking over the code.

I got rid of current_template_reqs in my current work. Constraints are
associated directly with a template parameter list or a declarator.

>>> +  // FIXME: This could be improved. Perhaps the type of the requires
>>> +  // expression depends on the satisfaction of its constraints. That
>>> +  // is, its type is bool only if its substitution into its normalized
>>> +  // constraints succeeds.
>>
>>
>> The requires-expression is not type-dependent, but it can be
>> instantiation-dependent and value-dependent.
>>
> This is an interesting change.  The REQUIRES_EXPR is currently marked as
> value dependent.  The ChangeLog indicates that Andrew loosened the
> conditions for being value dependent for some cases, but then added it as
> type dependent when something else failed.  May require some time to pin
> down exactly what needs to be done here.

I think something may have changed since I made that change... If I'm
remembering correctly, it used to be the case that build_x_binary_op
would try to fold the resulting expression when the operands weren't
type dependent. That happens in conjoin_constraints.

Now it looks like it's calling build_non_dependent_expr, which does
something a little different.

I agree that requires-expressions are not type-dependent (they have type bool).

Andrew


Re: Concepts code review

2014-11-12 Thread Andrew Sutton
>> +  // The constraint info maintains information about constraints
>> +  // associated with the declaration.
>> +  tree constraint_info;
>
>
> We talked back at the end of June about moving this into a separate
> hashtable; I'm still reluctant to add another pointer to most declarations
> when only a minority will have constraints.  As I was saying in the earlier
> thread, I think the problem you were hitting should be resolved by looking
> through clones with DECL_ORIGIN.  This needs to be fixed before merge, since
> it significantly affects non-concepts compiles.


Agreed. I'll probably start looking at this on Friday morning.


>> +  // Zeroth, a constrained function is not viable if its constraints are
>> not
>> +  // satisfied.
>
> As I suggested in the document review, I think we want to check this after
> the number of parameters, to avoid unnecessary implicit template
> instantiation in evaluating the constraints.  Patch attached.


Great. I'll apply that after I merge with trunk (which is going on right now).



>> +resolve_constraint_check (tree call)
>> +{
>> +  gcc_assert (TREE_CODE (call) == CALL_EXPR);
>
>
> Maybe also assert that the call has no function arguments?


I'll have to look, but we might get regular calls to constexpr
functions through this code path, which are then filtered out during
processing.

It might be better to not take this path if there are function
arguments since that couldn't possibly be a constraint check.


>> deduce_concept_introduction (tree expr)
>> {
>>   if (TREE_CODE (expr) == TEMPLATE_ID_EXPR)
>> {
>>   // Get the parameters from the template expression.
>>   tree decl = TREE_OPERAND (expr, 0);
>>   tree args = TREE_OPERAND (expr, 1);
>>   tree var = DECL_TEMPLATE_RESULT (decl);
>>   tree parms = TREE_VALUE (DECL_TEMPLATE_PARMS (decl));
>>
>>   parms = coerce_template_parms (parms, args, var);
>
>
> Do you still need this coerce_template_parms now that I've added a call to
> lookup_template_variable?  Well, once my change is merged onto the branch or
> the branch onto trunk.


Maybe? I'm not sure what the call to lookup_template_variable is going
to do :) I think we still need to instantiate default arguments in
order to perform the match.


> Can you reduce the code duplication between deduce_constrained_parameter and
> deduce_concept_introduction?


Yes.

>>   // Sometimes a function call results in the creation of clean up
>>   // points. Allow these to be preserved in the body of the
>>   // constraint, as we might actually need them for some constexpr
>>   // evaluations.
>
>
> What need are you thinking of?  CLEANUP_POINT_EXPR is ignored in constexpr
> evaluation.
>
> Also, this function seems like reinventing massage_constexpr_body, can we
> share code?


I didn't know if the forthcoming generalized constexpr evaluator would
act on those or not. We'll have a look at the massage_constexpr_body
function. I wonder if we can apply that to both function and constexpr
variables.


>> +  // Normalize the body of the function into the constriants language.
>> +  tree body = normalize_constraints (DECL_SAVED_TREE (fn));
>> +  if (!body)
>> +return error_mark_node;
> ...
>>
>> +  // Reduce the initializer of the variable into the constriants
>> language.
>> +  tree body = normalize_constraints (DECL_INITIAL (decl));
>
>
> If we're normalizing before substitution, why wait until the point of use to
> do it?  At least we could cache the result of normalization.


We should be normalizing and caching as soon as we can create a
complete declaration (for some declaration of complete). For functions
and function templates, for example, that's at the top of grokfndecl.

Although, as I think about it, I seem to remember having to
re-normalize a constraint in certain circumstances, but I can't
remember what they are. I'll take a look at this.


>>   // Modify the declared parameters by removing their context (so they
>>   // don't refer to the enclosing scope), and marking them constant (so
>>   // we can actually check constexpr properties).
>
>
> We don't check constexpr using these parms anymore, but rather the
> substituted arguments, so we don't need to mark them constant, right? Is the
> other (context) change still relevant?


That will come out.


>> +  // TODO: Actually check that the expression can be constexpr
>> +  // evaluatd.
>> +  //
>> +  // return truth_node (potential_constant_expression (expr));
>> +  sorry ("constexpr requirement");
>
>
> Pass it to maybe_constant_value and check whether the result is
> TREE_CONSTANT?  Or do we want to remove the constexpr requirement code now
> that it's out of the proposal?


This should come out. I think we'll get a non-language way of checking
this in the not-so-distant future.


>>   DECL_INITIAL (decl) = proto;  // Describing parameter
>>   DECL_SIZE_UNIT (decl) = fn;   // Constraining function declaration
>>   DECL_SIZE (decl) = args;  // Extra template arguments.
>
>
> I'

Re: Concepts code review

2014-11-12 Thread Andrew Sutton
>> Agreed. I'll probably start looking at this on Friday morning.
>
>
> Note that end of stage 1 is Saturday, as I just realized today.  So the
> sooner the better.  :)

Ouch. Good thing my merge with trunk broke in unexpected ways this
morning -- minimally, something in cgraph ended up missing a #include
in the merge and I don't know how to fix it :/

Andrew


Re: [C++ Patch] PR 71140 ("[concepts] ill-formed nested-requirement lacking a semicolon not rejected")

2018-10-12 Thread Andrew Sutton
>
> BTW, I would discourage you from messing much with the concepts code
> at this point, as a major overhaul should be coming soon.
>

Major overhaul:

https://github.com/asutton/gcc (branch is concepts; we're about 2 weeks
back from trunk).

Unfortunately, I we haven't been following GCC commit discipline, and
there's a bunch of dead/legacy code that I need to clean up. And of course
some regressions. I wanted to spend the weekend on this and forward a
cleaner version next week. But no time is as good as the present it seems.

This fork reimplements concepts as currently specified in the WD (for the
most part). It also preserves TS syntax (but not behavior), although there
are certainly going to be some new bugs.

-std=c++2a turns on concepts by default (sets -fconcepts)
-fconcepts-ts can be additionally specified to enable TS extensions
(abbreviated fn templates, etc).
-fconcepts on its own gives you (should give you) TS syntax with C++20
semantics and no C++20 features.

Here's what's changed:
- new requires clause syntax as required in the WD (-fconcepts-ts will
change this back to the TS syntax)
- concept bool is now a warning, although (IIRC) disabled with
-fconcepts-ts. Function and variable concepts live on.
- concepts are now their own kind of declaration (CONCEPT_DECL). That was a
big change.
- now only 3 kinds of constraints: conj, disj, and pred (should be
atomic, also needs a dead code cleanup).
- constraints on declarations are represented as expressions -- no
normalization until later
- associated constraints are only instantiated when checked -- no premature
substitution
- new implementaiton of satisfaction, does not require ahead-of-time
normalization
- new implementation of normalization (fewer nodes, smaller impl)
- atomic constraint comparison based on expr identity/parameter mapping
- complete rewrite of subsumption (new comparison model invalidated some
assumptions in the old impl)
- constrained decls differentiated by syntax of constraints (not
equivalence)
- moved the concepts testsuite into c++2a directory as a vetting/curating
process, new 2a tests, new ts-compatability tests

There are some bugs and regressions. I know for a fact that we've broken
partial specialization of variable templats, but I'm really not sure how.
There's also probably a bug in the constraint comparison implementation
that affects partial ordering. More testing is needed. I mostly ignored the
TS support while updating to the WD semantics, so that's been a little
buggy when I brought it back online. Also, sometimes diagnostics aren't
emitted correctly.

I'm not quite sure how to proceed with submitting this patch. Once I made
the decision to make concepts their own kind of declaration, the idea of
sending small patches went right out the window.


Re: [concepts] Update to match the working draft (and bit more)

2018-10-18 Thread Andrew Sutton
Well,,that's unfortunate. Please forgive the alternative patch submission.

https://github.com/asutton/gcc/blob/master/concepts.patch


> Attached is a rework of the Concepts TS implementation to match the
> Working Draft. It's a big patch -- I'd loved to make it smaller, but
> it didn't work out that way.
>
> Here's a brief summary of changes:
>
> - Make concepts work with -std=c++2a; warn if -fconcepts is also supplied.
> - Add a new flag -fconcepts-ts to enable TS syntax* when -std=c++2a is
used.
> - No more bool for concepts. They are their own kind of declaration.
> - New grammar for requires clauses (unfortunately). This can be
> overriden with -fconcepts-ts.
> - Support "concept bool" with -fconcepts-ts. This includes both
> variable and function concepts.
> - Constraints are instantiated only at the point of use and properly
> interleave substitution and evaluation. This should fix any issues
> with "premature substitution" errors.
> - Implement semantic comparison of atomic constraints (P0717). This
> may be buggy. More testing with complex refinement hierarchies is
> needed.
> - Completely rewrite the subsumption algorithm in logic. The WD broke
> a number of assumptions the previous version relied on, so a simple
> fix wasn't possible. We haven't seen the performance issues related to
> subsumption that showed up in the past. They're still there, but other
> core changes minimize the likelihood of achieving worst case.
> - Declaration matching is syntactic (P0716).
> - Warnings are emitted for the use of TS syntax unless -fconcepts-ts
> is specified. And if you do use -fconcepts, the same-type rule for
> abbreviated function templates is dead.
> - And just because... make template introduction semantics actually
> conform to the TS. We weren't allowing the introduction of a fixed
> series of template parameters for an introduced pack. We do now.
>
> This is not a perfect patch.
>
> - It somehow breaks partial template specializations of variable
> templates (cpp2a/concepts pr80471.C). I have no idea how that
> happened. It almost looks like a GC bug.
> - There's a new regression in cpp2a/concepts-ts2.C)
> - This breaks a lot of concepts TS support (the g++.dg/concepts dir).
> - We've seen other errors in parts of GCC not even remotely related to
> concepts**.
>
> My goals over the next few weeks are to clean up the regressions and
> start working through the backlog of concepts issues. That includes
> fixing new issues as they arise.
>
> * This patch does not preserve the Concepts TS semantics. Anybody
> relying on e.g., subtleties of the partial ordering rules in the TS
> will find themselves with broken code. This was a conscious choice.
> there are serious design issues in the TS.
>
> ** Unfortunately, my testing effort before sending this patch is a bit
> hampered by the fact that a clean bootstrap build ICEs here (bootstrap
> build on Mac OS -- can give more details if needed).
>
> ../../isl/isl_tab_pip.c: In function
‘isl_tab_basic_set_non_trivial_lexmin’:
> ../../isl/isl_tab_pip.c:5087:21: internal compiler error: in check, at
> tree-vrp.c:155
>  5087 | __isl_give isl_vec *isl_tab_basic_set_non_trivial_lexmin(
>   | ^~~~
>
> This one isn't my fault :)
>
> Enjoy,
>

>> Hi. This is the qmail-send program at sourceware.org.
>> I'm afraid I wasn't able to deliver your message to the following
addresses.
>> This is a permanent error; I've given up. Sorry it didn't work out.
>>
>> :
>> ezmlm-reject: fatal: Sorry, I don't accept messages larger than 40
bytes (#5.2.3)


> Andrew Sutton


Re: [C++ Patch] PR 71140 ("[concepts] ill-formed nested-requirement lacking a semicolon not rejected")

2018-10-31 Thread Andrew Sutton
Sorry for the slow reply. I've been stuck working on some other projects.


> Can you say a bit about why that was better than continuing to use
> VAR_DECL?
>

I wanted to make sure that we avoid normal VAR_DECL processing routines, so
we don't e.g., slip into a function where we might try to generate an
address for a concept.


Yeah, don't worry about trying to send small patches.  I don't mind
> reviewing what's on the branch, though at least the final patch should
> be sent to the list for archival.
>
> What feedback are you looking for at this point?
>

Mostly anything that would obviously prevent or cause problems merging in
the near future.

I'll try to keep the asutton/gcc fork on github rebased on trunk so there
shouldn't be too many merge issues.


[PATCH] Add -std=c++2a

2017-07-20 Thread Andrew Sutton
This adds a new C++ dialect, enabled by -std=c++2a.

libcpp/
Add support for C++2a.
* include/cpplib.h (c_lang): Add CXX2A and GNUCXX2A.
* init.c (lang_defaults): Add rows for CXX2A and GNUCXX2A.
(cpp_init_builtins): Set __cplusplus to 201707L for C++2x.

gcc/c-family/
Add support for -std=c++2a.
* c-common.h (cxx_dialect): Add cxx2a as a dialect.
* opt.c: Add options for -std=c++2a and -std=gnu++2a.
* c-opts.c (set_std_cxx2a): New.
(c_common_handle_option): Set options when -std=c++2a is enabled.

gcc/testsuite/
New test for -std=c++2a.
* g++.dg/cpp2a/cplusplus.C: New.


Andrew Sutton


cxx2a.patch
Description: Binary data


Re: [PATCH] Add -std=c++2a

2017-07-20 Thread Andrew Sutton
For now, I think these two are incompatible. There are more features
in -fconcepts than in C++20 (so far). There are also some changes in
syntax and semantics that would be nice to diagnose. A good example
would be 'concept' as a decl-specifier (TS) vs. 'concept' as a
declaration introducer (WD).

I was going to submit a followup that emits a warning when both
-std=c++2a and -fconcepts are both enabled and then disables
-fconcepts.

Andrew Sutton


On Thu, Jul 20, 2017 at 1:04 PM, Markus Trippelsdorf
 wrote:
> On 2017.07.20 at 09:33 -0400, Andrew Sutton wrote:
>> This adds a new C++ dialect, enabled by -std=c++2a.
>>
>> libcpp/
>> Add support for C++2a.
>> * include/cpplib.h (c_lang): Add CXX2A and GNUCXX2A.
>> * init.c (lang_defaults): Add rows for CXX2A and GNUCXX2A.
>> (cpp_init_builtins): Set __cplusplus to 201707L for C++2x.
>>
>> gcc/c-family/
>> Add support for -std=c++2a.
>> * c-common.h (cxx_dialect): Add cxx2a as a dialect.
>> * opt.c: Add options for -std=c++2a and -std=gnu++2a.
>> * c-opts.c (set_std_cxx2a): New.
>> (c_common_handle_option): Set options when -std=c++2a is enabled.
>>
>> gcc/testsuite/
>> New test for -std=c++2a.
>> * g++.dg/cpp2a/cplusplus.C: New.
>
> Perhaps you should enable -fconcepts by default?
>
> --
> Markus


Re: [PATCH] Giant concepts patch

2016-07-10 Thread Andrew Sutton
I just tried building a fresh pull of cmcstl2, and I'm not seeing any
errors as a result of not handling those missing codes in
tsubst_constraint. At one point, I think it was not possible to get
those other constraints in this context because they were nested in a
parm_constr. But that seems obviously untrue now. But still... that
gcc_unreachable isn't being triggered by any code in cmcstl.

I attached a patch that adds tsubsts for the missing constraints.
Unfortunately, I don't have time to test thoroughly today.

I did find another bug building cmcstl2, hence the attached
disable-opt patch. For some reason, the memoization of concept
satisfaction is giving momoized results for concept + args that have
not yet been evaluated. This is exactly the same problem that made me
disable the lookup/memoize_constraint_sat optimizations. Somehow I'm
getting the same hash code for different arguments, and they also
happen to compare equal.

This doesn't seem to affect memoization of concept satisfaction. At
least I haven't seen it yet.

Anyways, disabling that optimization lets me build cmcstl2 with
concepts. Sort of; there's a bug in the library, which is why Casey is
added to the mailing. You're missing a const overload of operator* for
basic_operator. Patch forthcoming.

Changelogs below.

2016-07-10  Andrew Sutton  

* constraint.cc (tsubst_type_constr, tsubst_implicit_conversion_constr,
tsubst_argument_deduction_constr, tsubst_exception_constr): New.
(tsubst_constraint): Add cases for missing constraints.

2016-07-10  Andrew Sutton  

* pt.c (lookup_concept_satisfaction, memoize_concept_satisfaction):
Disable memoization of concept results.
Andrew Sutton


On Sat, Jul 9, 2016 at 11:24 AM, Andrew Sutton
 wrote:
> Do we have a smaller test that reproduces this? One reason I didn't make
> much progress was that I could never find a small test that triggers the
> problem. I just pulled your branch and plan to do some digging tomorrow.
>
>
>
> On Fri, Jul 8, 2016 at 6:42 PM Jason Merrill  wrote:
>>
>> On Wed, Jun 22, 2016 at 2:25 AM, Andrew Sutton
>>  wrote:
>> >> > I've run into some trouble building cmcstl2: declarator requirements
>> >> > on a function can lead to constraints that tsubst_constraint doesn't
>> >> > handle.  What was your theory of only handling a few _CONSTR codes
>> >> > there?  This is blocking me from checking in the patch.
>> >
>> > I wonder if those were the problems that I was running into, but hadn't
>> > diagnosed. I had thought it shouldn't be possible to get the full set of
>> > constraints in tsubst_constraint. I may have mis-analyzed the problem
>> > for
>> > function constraints.
>>
>> Any further thoughts?
>>
>> Jason
>
> --
> Andrew Sutton
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 145ae1e..745cbbc 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1625,12 +1625,70 @@ static tree
 tsubst_expr_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 {
   cp_unevaluated guard;
-
   tree expr = EXPR_CONSTR_EXPR (t);
-  tree check = tsubst_expr (expr, args, complain, in_decl, false);
-  if (check == error_mark_node)
+  tree ret = tsubst_expr (expr, args, complain, in_decl, false);
+  if (ret == error_mark_node)
+return error_mark_node;
+  return build_nt (EXPR_CONSTR, ret);
+}
+
+static tree
+tsubst_type_constr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
+{
+  tree type = TYPE_CONSTR_TYPE (t);
+  tree ret = tsubst (type, args, complain, in_decl);
+  if (ret == error_mark_node)
 return error_mark_node;
-  return build_nt (EXPR_CONSTR, check);
+  return build_nt (TYPE_CONSTR, ret);
+}
+
+static tree
+tsubst_implicit_conversion_constr (tree t, tree args, tsubst_flags_t complain, 
+   tree in_decl)
+{
+  cp_unevaluated guard;
+  tree expr = ICONV_CONSTR_EXPR (t);
+  tree type = ICONV_CONSTR_TYPE (t);
+  tree new_expr = tsubst_expr (expr, args, complain, in_decl, false);
+  if (new_expr == error_mark_node)
+return error_mark_node;
+  tree new_type = tsubst (type, args, complain, in_decl);
+  if (new_type == error_mark_node)
+return error_mark_node;
+  return build_nt (ICONV_CONSTR, new_expr, new_type);
+}
+
+static tree
+tsubst_argument_deduction_constr (tree t, tree args, tsubst_flags_t complain, 
+  tree in_decl)
+{
+  cp_unevaluated guard;
+  tree expr = DEDUCT_CONSTR_EXPR (t);
+  tree pattern = DEDUCT_CONSTR_PATTERN (t);
+  tree autos = DEDUCT_CONSTR_PLACEHOLDER(t);
+  tree new_expr = tsubst_expr (expr, args, complain, in_decl, false);
+  if (new_expr == error_mark_node)
+return error_mark_node;
+  /* It seems like substituting through the pattern will no

Re: [PATCH] Giant concepts patch

2016-07-10 Thread Andrew Sutton
Ah sure. Jason has been vetting my post-Jacksonville concepts patch in
the branch jason/concepts-rewrite. I just pulled this off the github
GCC mirror this morning to look at an outstanding question. Resulted
in the previous 2 patches.

I tried building a fresh pull of your cmcstl2 and got an off-by const
error. It looks like it's coming from counted_iterator. I'll post the
repro instructions and the error on the bug report.

Andrew


concept diagnostics

2015-08-18 Thread Andrew Sutton
This is not a proper patch. I'm missing the usual changelog and I'm
still running the regression tests, but I wanted to get some opinions
before committing more time to it.

This patch extends the diagnostics for concepts to report precise
failures when constraints are not satisfied. It currently reports up
to 7 errors and then elides the rest. That should probably be under
control of a compiler option, but I'd like some suggestions on how to
proceed.

Also, diagnostics are currently emitted as notes against the location
of the concept declaration. It would be better to diagnose the failure
against location of each requirement, but we're not doing a very good
job tracking source locations for those.

Also, in a lot of cases, we probably just want to replay a
substitution with tf_error to generate precise failures. Although that
potentially generates *way* more information (e.g., candidate sets for
failed overload resolution).

I also started try to apply these diagnostics to static_if. The basic
idea being: if you write static_if(C, "") where C is a concept,
then you should get the full diagnostics for that concept. I suspect
that this will be the most requested feature within a few months time.

Unfortunately, I ran into a little problem that C is immediately
folded into true/false and the original expression is unrecoverable
from finish_static_if. I tinkered with parsing the condition as a
non-constant expression and then folding it on demand, but that caused
a number of regressions, so I had to back it out. Any thoughts on how
to proceed?

Andrew
Index: cxx-pretty-print.c
===
--- cxx-pretty-print.c	(revision 226937)
+++ cxx-pretty-print.c	(working copy)
@@ -2600,6 +2600,7 @@ pp_cxx_compound_requirement (cxx_pretty_
   pp_cxx_ws_string (pp, "->");
   pp->type_id (type);
 }
+  pp_cxx_semicolon (pp);
 }
 
 /* nested requirement:
@@ -2646,7 +2647,7 @@ pp_cxx_implicit_conversion_constraint (c
   pp_left_paren (pp);
   pp->expression (ICONV_CONSTR_EXPR (t));
   pp_cxx_separate_with (pp, ',');
-  pp->expression (ICONV_CONSTR_TYPE (t));
+  pp->type_id (ICONV_CONSTR_TYPE (t));
   pp_right_paren (pp);
 }
 
Index: cp-tree.h
===
--- cp-tree.h	(revision 226937)
+++ cp-tree.h	(working copy)
@@ -6680,6 +6680,8 @@ extern tree tsubst_requires_expr
 extern tree tsubst_constraint   (tree, tree, tsubst_flags_t, tree);
 extern tree tsubst_constraint_info  (tree, tree, tsubst_flags_t, tree);
 extern bool function_concept_check_p(tree);
+extern bool variable_concept_check_p(tree);
+extern bool concept_check_p (tree);
 
 extern tree evaluate_constraints(tree, tree);
 extern tree evaluate_function_concept   (tree, tree);
@@ -6687,6 +6689,7 @@ extern tree evaluate_variable_concept
 extern tree evaluate_constraint_expression  (tree, tree);
 extern bool constraints_satisfied_p (tree);
 extern bool constraints_satisfied_p (tree, tree);
+extern bool constraint_expression_satisfied_p   (tree, tree);
 
 extern bool equivalent_constraints  (tree, tree);
 extern bool equivalently_constrained(tree, tree);
Index: constraint.cc
===
--- constraint.cc	(revision 226937)
+++ constraint.cc	(working copy)
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.
 #include "wide-int.h"
 #include "inchash.h"
 #include "tree.h"
+#include "print-tree.h"
 #include "stringpool.h"
 #include "attribs.h"
 #include "intl.h"
@@ -113,13 +114,22 @@ conjoin_constraints (tree t)
   return r;
 }
 
-/* Returns true if T is a call expression to a function
-   concept. */
+/* Returns true if T is an expression that would evaluate
+   a variable or function concept. */
+
+bool
+concept_check_p (tree t)
+{
+  return function_concept_check_p (t) || variable_concept_check_p (t);
+}
+
+/* Returns true if T is a call to a function concept. */
 
 bool
 function_concept_check_p (tree t)
 {
-  gcc_assert (TREE_CODE (t) == CALL_EXPR);
+  if (!t || t == error_mark_node || TREE_CODE (t) != CALL_EXPR)
+return false;
   tree fn = CALL_EXPR_FN (t);
   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR
   && TREE_CODE (TREE_OPERAND (fn, 0)) == OVERLOAD)
@@ -132,6 +142,17 @@ function_concept_check_p (tree t)
   return false;
 }
 
+/* Returns true if T is a template-id referring to a variable concept. */
+
+bool
+variable_concept_check_p (tree t)
+{
+  if (!t || t == error_mark_node || TREE_CODE (t) != TEMPLATE_ID_EXPR)
+return false;
+  return variable_template_p (TREE_OPERAND (t, 0));
+}
+
+
 /*---
 Resolution of qualified concept names
 ---*/
@@ -350,12 +371,12 @@ lift_func

Re: [c++-concepts]

2013-05-30 Thread Andrew Sutton
>   * Check against cxx11 dialect, not cxx0x.

Let's talk about this tomorrow. I'm not quite sure how to do this.

>   * Any particular reason to use classes with operator() for the
> parseers and the combinators?  GCC can inline indirect calls to
> functions with internal linkage.  That should cut down on the
> constructor boilerplates.  This particular change can be addressed
> after the commit.

Some of the other combinators that I've built for the requires
expression have data fields that act as arguments to the actual other
cp_parser_* calls. I'll submit those with the relevant patch.

This should be easy to refactor, though.

> | +template
> | +inline T* take(T*& p)
> | +{
> | +  T* q = p;
> | +  p = NULL;
> | +  return q;
> | +}
> | +} // namespace
> | +
> | +
>
> Call it 'release' -- following standard library terminology.

Ah... yes. Good name.

> Suggestion: nonnull_or_else? or assert_nonnull? or check_nonnull?
> or validate?

check_nonnull is a good name.

> | -  /* 1 spare bit */
> | +  unsigned concept_p : 1;  /* var or fn */
> | +  /* 0 spare bit */
> |  };
>
> Hmm I don't understand the comment "var or fn".
> If it is declared a concept, how can it it be a var?

Copied from the other bits in the class. I think it means it applies
to either variables or functions. I left it that way in anticipation
of template variables.


Re: [c++-concepts]

2013-05-30 Thread Andrew Sutton
I'll clean it up and commit tomorrow morning.

> Once you've committed the patch, let me know so I can synchronize with
> trunk -- or is there another patch coming in this week?

I'm hoping to get all of the function-related functionality sent off
by tomorrow or Saturday. I found a showstopper in the class template,
and I think it will take some time to address.

Andrew


Re: [c++-concepts]

2013-05-30 Thread Andrew Sutton
I presented that at C++Now, so I hope so :) It lets me write:

template
  requires Input_iterator // no parens!
void f(T x);

Walter Brown also suggested this usage in his object alias paper.

In concepts lite, a concept is essentially an expression. Thus far,
we've packaged those expressions in constexpr functions (using
"concept" as a declaration specifier to impose additional
restrictions). Variable templates fall easily into this same set of
restrictions. Plus, no overloading.

Andrew

On Thu, May 30, 2013 at 3:34 PM, Jason Merrill  wrote:
> On 05/30/2013 03:17 PM, Andrew Sutton wrote:
>>>
>>> | -  /* 1 spare bit */
>>> | +  unsigned concept_p : 1;  /* var or fn */
>>> | +  /* 0 spare bit */
>>> |  };
>>>
>>> Hmm I don't understand the comment "var or fn".
>>> If it is declared a concept, how can it it be a var?
>>
>>
>> Copied from the other bits in the class. I think it means it applies
>> to either variables or functions. I left it that way in anticipation
>> of template variables.
>
>
> Can template variables be concepts?
>
> Jason
>



-- 
Andrew Sutton
andrew.n.sut...@gmail.com


Re: [c++-concepts]

2013-06-01 Thread Andrew Sutton
>   * Check against cxx11 dialect, not cxx0x.

This check is actually all over parser.c, the reason it shows up in
the patch is that I reverted a previous change that affected some code
that included it.

I'd feel better leaving it in, since its a change that could affect
some other part of the compiler.

Andrew


[c++-concepts] constraints

2013-06-01 Thread Andrew Sutton
This patch adds constraint checking and overloading for function
templates, class templates, and alias templates. This patch isn't as
big as it seems, it just touches the compiler in a lot of different
places.


2013-06-01  Andrew Sutton  
* gcc/cp/call.c (rejection_reason_code): Add rr_constraint_failure.
(template_constraint_failure): New.
(template_constraint_failure): Check declaration constraints
before other viable function criteria.
(add_template_candidate_real): Diagnose constraint failures,
and attach constraints to instantiated candidates.
(print_z_candidate): Diagnose constraint failures.
(get_actual_template): New.
(joust): Allow temploids to also participate in most specialied
when they have constraints.
* gcc/cp/constraint.cc (join_requirements): New
(conjoin_requirements): Join expressions correctly.
(disjoin_requirements): Join expressions correctly.
(is_checkable): Rename from is_constraint, check vs. concept flag.
(resolve_constraint_check): Fix.
(get_type_constraints): New.
(get_decl_constraints): New.
(get_constraints): New.
(suppress_template_processing): New.
(check_requirements): New.
(check_dependent_requirements): New.
(check_constraints): New.
(check_type_constraints): New.
(check_decl_constraints): New.
(check_template_constraints): New.
(equivalent_constraints): New.
(equivalently_constrained): New.
(more_constraints): New.
(more_constrianed): New.
(diagnose_constraint_failure): New.
* gcc/cp/class.c (are_constrained_member_overloads): New.
(add_method): Allow overloading of constrained member functions.
* gcc/cp/ptree.c (cxx_print_xnode): Print constraint info.
* gcc/cp/pt.c (local_specialization_stack): New.
(build_template_info): Incorporate template requirements
(check_explicit_specialization): Instantiate requirements for
template info.
(push_template_decl_real): Include constraints in template info.
(redeclare_class_template): Diagnose redeclaration with different
constraints.
(is_compatible_template_arg): New.
(convert_template_argument): Check constraints on template template
arguments.
(lookup_template_class_1): Check constraints on alias templates.
Keep constraints with instantiated types.
(instantiate_class_template_1): Check constraints on class templates.
(tsubst_decl): Instantiate and keep constraints with template info.
Also, allow dependent pack arguments to produce neww parameter
packs when instantiated.
(tsubst_copy): Handle REAL_TYPE and BOOLEAN_TYPE.
(tsubst_copy_and_build): PARM_DECLs can be instantiated as pack
expansions (used with requires expression).
(fn_type_unification): Check constraints for function templates.
(more_specialized_fn): Determine which candidate is more constrained.
(tsubst_constraint): New.
(substitute_requirements): New.
* gcc/cp/parser.c (cp_unevaluated): New.
* gcc/cp/tree.h (cp_unevaluated): New.
(local_specialization_stack): New.
(get_constraints): New.
(check_constraints): New.
(check_constraints): New.
(check_template_constraints): New.
(subst_template_constraints): New.
(equivalent_constraints): New.
(equivalently_constrained): New.
(more_constraints): New.
(more_constrained): New.
(diagnose_constraint_failure): New.
* gcc/cp/decl.c: (are_constrained_overloads): New.
(duplicate_decls): Allow constrained function overloads, and diagnose
attempts to overload concepts.
(grokfndecl): Supply empty constraints to build_template_info.
(cp_tree_node_structure): Add entry for CONSTRAINT_INFO.
(semantics.c): Create template_info for template template parameters
as a place to house constraints.
* gcc/cp/tree.c (bind_template_template_parm): Provide empty
constraints for bound template template parameters.
* gcc/cp/cxx-pretty-print.c (pp_cxx_template_declaration): Print the
template requirements.


reqs-2.patch
Description: Binary data


Re: [c++-concepts] code review

2013-06-06 Thread Andrew Sutton
Hi Jason,

Thanks for the comments. I just went ahead and fixed all the editorial
issues. Comments and questions below:


>> * gcc/system.h (cstdlib): Include  to avoid poisoned
>> declaration errors.
>
> Poisoned declarations of what?  This seems redundant with the #include
>  just below.

I never did understand why this happens. Compiling with GCC-4.6, I get
these errors originating in logic.cc from an include of .
This is what I get:

In file included from /usr/include/c++/4.6/bits/stl_algo.h:61:0,
 from /usr/include/c++/4.6/algorithm:63,
 from ../../c++-concepts/gcc/cp/logic.cc:45:
/usr/include/c++/4.6/cstdlib:76:8: error: attempt to use poisoned "calloc"
/usr/include/c++/4.6/cstdlib:83:8: error: attempt to use poisoned "malloc"
/usr/include/c++/4.6/cstdlib:89:8: error: attempt to use poisoned "realloc"
/usr/include/c++/4.6/cstdlib:112:11: error: attempt to use poisoned "calloc"
/usr/include/c++/4.6/cstdlib:119:11: error: attempt to use poisoned "malloc"
/usr/include/c++/4.6/cstdlib:127:11: error: attempt to use poisoned "realloc"


>> +  /* Concepts-related keywords */
>> +  { "assume",  RID_ASSUME, D_CXXONLY | D_CXX0X | D_CXXWARN },
>> +  { "axiom",   RID_AXIOM,  D_CXXONLY | D_CXX0X | D_CXXWARN },
>> +  { "concept", RID_CONCEPT,D_CXXONLY | D_CXX0X | D_CXXWARN },
>> +  { "forall",  RID_FORALL, D_CXXONLY | D_CXX0X | D_CXXWARN },
>> +  { "requires",RID_REQUIRES,   D_CXXONLY | D_CXX0X | D_CXXWARN },
>
>
> I don't see anything that limits these keywords to when concepts are
> enabled.  You probably want to add an additional mask that applies to these.

Ok. I'll add D_CXX_CONCEPTS and set it for all of reserved words.


>> +; Activate C++ concepts support.
>> +Variable
>> +bool flag_concepts
>
> You don't need to declare this separately.

I'm not quite sure what you mean. Separately from what?


>> +static tree
>> +resolve_constraint_check (tree ovl, tree args)
>
> This function seems to be trying to model a subset of overload resolution,
> which seems fragile to me; better to use the actual overload resolution code
> to decide which function the constraint expression calls, or at least
> resolve_nondeduced_context which handles SFINAE.

It is. I was a little hesitant to use the actual overload resolution
facility because of the restrictions for concepts. I think I was also
doing something a little different in previous version.

I'll take another look and see if either will work instead of my
homebrew solution.


>
>> +case CAST_EXPR:
>> +  return reduce_node (TREE_VALUE (TREE_OPERAND (t, 0)));
>
> Are we assuming that constraint expressions can't involve objects of literal
> class type?

For now, I think it's a reasonable restriction. We can relax this as
needed in the future.


>>  struct GTY(()) tree_template_info {
>>struct tree_common common;
>> +  tree constraint;
>>vec
>> *typedefs_needing_access_checking;
>>  };
>
>
> Why do we need constraint information in template_info?  I suppose this is
> the issue you raised in your mail last month:
>
>> I had expected there to be a template decl associated with underlying
>> class, but after print-bombing most of the instantiation, lookup, and
>> specialization processing routines, I couldn't find that one was ever
>> created for the type decl.
>
> This does seem like a shortcoming, that also led to the typedefs vec getting
> stuck into the template_info inappropriately.  I guess we should start
> building TEMPLATE_DECLs for partial specializations.

That's the long and short of it. Gaby suggested writing constraints
here so that, for any instantiation, you would have easy access to the
constraints for that declaration.


>> +struct GTY(()) tree_constraint_info {
>> +  struct tree_base base;
>> +  tree spelling;
>> +  tree requirements;
>> +  tree assumptions;
>> +};
>
>
> I'm confused by the relationship between the comment and the field names
> here.  Where do the conclusions come in?  Is "requirements (as a constant
> expression)" in the spelling or requirements field?

I must have forgotten to update the comments. I probably need to
re-think this structure a bit. The requirements field is the complete
set of requirement (shorthand constraints + requires clause). The
assumptions field is the analyzed requirements.

I was using the "spelling" field specifically for diagnostics, so I
could print exactly what was written. I think it might be better to
hang that off the template parameter list rather than the constraint
info.

I don't think "spelling" is used in the current patch other than initialization.


>> +  DECL_DECLARED_CONCEPT_P (decl) = true;
>> +  if (!check_concept_fn (decl))
>> +return NULL_TREE;
>> +}
>
>
> I think I'd rather deal with an invalid concept by not marking it as a
> concept, but still declaring it as a constexpr function.

Sounds reasonable.


>> +// Return the current list of assumed terms.
>>

Re: [c++-concepts] code review

2013-06-08 Thread Andrew Sutton
>> +C++ ObjC++ Var(flag_concepts, true)
>
> This line declares flag_concepts implicitly.

Ah... I see. Fixed.


>> That's the long and short of it. Gaby suggested writing constraints
>> here so that, for any instantiation, you would have easy access to the
>> constraints for that declaration.
>
> I'm not sure why you would care about the constraints for a particular
> instantiation; constraints only apply to the template, right?

In concepts lite, yes. Moving forward... I'm less certain. In the
context of separate checking, instantiated requirements may carry
lookup information into the current instantiation. But that's just
speculation.

I think I previously put constraint_info in lang_decl_min, right next
to template_info no less. It was easy to manage there, and initialized
as part of build_template_decl. But this obviously doesn't work for
partial specializations unless they get template_decls.

I'd be okay committing the current design with the caveat that it may
need to be rewritten in the not-so-distant future. I've already
written the other other way two or three times, so I'm familiar with
those changes.


>> branch_goal queues a copy of the current sub-goal, returning a
>> reference to that new branch. The insertion of the operands are done
>> on different sub-goals, giving the expected results.
>
> Right, I suppose I should have paid more attention to "This does not update
> the current goal"...

On the topic of logic.cc, I'm plan on rewriting this module to use a
set instead of lists. There will be some pretty substantial changes to
the internal interfaces.

Would it be reasonable to commit this now (since it works correctly),
and plan to rewrite it in the near future?


> template
> tree
> extract_goals (proof_state& s)
> ...
>  return extract_goals(s);
>
> but I suppose STL style is OK, too.


Huh. I didn't realize that could be inlined. Neat.


>> I was trying to write the parsing code a little more modularly so I
>> could keep my parse functions as small as possible. I use the facility
>> more heavily in the requires/validexpr code that's not included here.
>
>
> Hmm, to me it seems more modular to keep all of the code for handling e.g.
> "requires" in its own function rather than needing two different places to
> know how a requires clause starts.

I think I see where the problem is. cp_parser_requires_clause is
parsed non-optionally in a requires expression, but that's not
included in the patch. I factored out the explicit parsing (hence the
assertion) from the optional parsing.

I could remove the assertion. There's no path to that function that
does not first check that 'requires' has been found.


>>> Why don't you use 'release' and conjoin_requirements here?
>>
>>
>> Because there is no template parameter list that can provide
>> additional requirements in this declaration.
>
>
> OK, please add a comment to that effect.

On second thought, the absence of release() may actually have been a
bug. Comment added.


>>> The comment sounds more like tsubst_template_parms than
>>> coerce_template_parms.
>>
>>
>> It might be... I'll have to look. What I actually want to get is the
>> set of actual arguments that will be substituted for template
>> parameters given an initial set of arguments (lookup default
>> arguments, generate pack arguments, etc).
>
>
> Right, I think coerce_template_parms has the effect you want, I just don't
> think of it as doing substitution, so the comment and name could use a
> tweak.  If the function doesn't go away, that is.

Still looking at this.

What is the main entry point to overload resolution?

Andrew


Re: [c++-concepts] code review

2013-06-11 Thread Andrew Sutton
>> I think I previously put constraint_info in lang_decl_min, right next
>> to template_info no less. It was easy to manage there, and initialized
>> as part of build_template_decl. But this obviously doesn't work for
>> partial specializations unless they get template_decls.
>
>
> Right.  And we would want it to be specific to template_decls, not all decls
> that use lang_decl_min.

I'll have to check. I can't remember off the top of my head if
non-template member functions have a corresponding template_decl. I
think they do.

auto declarations will also get constraints in the future.


>> On the topic of logic.cc, I'm plan on rewriting this module to use a
>> set instead of lists. There will be some pretty substantial changes to
>> the internal interfaces.
>>
>> Would it be reasonable to commit this now (since it works correctly),
>> and plan to rewrite it in the near future?
>
>
> OK.

I was experimenting with this over the weekend. I'm just going to
rewrite it now, but without the optimizations I alluded to earlier.
They didn't pan out the way I'd have liked.

>> I think I see where the problem is. cp_parser_requires_clause is
>> parsed non-optionally in a requires expression, but that's not
>> included in the patch. I factored out the explicit parsing (hence the
>> assertion) from the optional parsing.
>
>
> The two situations seem pretty similar; you don't decide you're parsing a
> requires expression until you see the keyword either, right?
>
> The usual pattern in the parser is for a function to try to parse a
> particular construct and then return NULL_TREE if we're looking at something
> else; it seems most straightforward to do that in this case as well.

Yes, but I wasn't testing for the keyword prior to the call to
cp_parser_requires_clause_opt. That's not quite true, I was in for
member functions, but that was an oversight.

Changing to test for requires won't be hard.

>> What is the main entry point to overload resolution?
>
>
> Perhaps finish_call_expr is what you want.

After investigating, neither call_expr nor resolve_nondeduced_context
do what I need. I need a resolution of a call expression that does not
return overload sets, especially in the case where the initial call
expression is already dependent.

resolve_nondeduced_context looks like a good candidate to extend, but
I hesitate to modify since it's used in a number of different places,
and winnowing the overload set may not be appropriate in those
contexts.


Re: [c++-concepts] code review

2013-06-11 Thread Andrew Sutton
>> After investigating, neither call_expr nor resolve_nondeduced_context
>> do what I need. I need a resolution of a call expression that does not
>> return overload sets, especially in the case where the initial call
>> expression is already dependent.
>
>
> Does this have to do with restrictions on overloading of concept functions?


Very much so. I need a single function because I'm inlining its body
at the call site.

Andrew


  1   2   >