> 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<tree, va_gc>
>> **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).  */
>> +      if (p && p->kind == cdk_function && p->declarator->kind == cdk_id)
>
>
> I think you can use function_declarator_p here.
>
>> +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?
>
>> +  /* A sentinel class that ensures that deferred access checks
>> +     are popped before a function returns.  */
>> +  struct deferring_access_check_sentinel
>> +  {
>> +    deferring_access_check_sentinel ()
>> +    {
>> +      push_deferring_access_checks (dk_deferred);
>> +    }
>> +    ~ deferring_access_check_sentinel ()
>> +    {
>> +      pop_deferring_access_checks ();
>> +    }
>> +  }
>
>
> Let's put this with the other RAII sentinels in cp-tree.h.
>
>> +                       Lifting of concept definitions
>
>
> Could we have a bit more description of what "lifting" means here?
>
>>
>> +/*---------------------------------------------------------------------------
>> +                        Constraint normalization
>>
>> +---------------------------------------------------------------------------*/
>
>
> You have two of these headers; I guess the first one should be
> "transformation" and could use more description.  On the second, I would
> retain the old comment
>
>> -// Normalize a template requirement to a logical formula written in terms
>> of
>> -// atomic propositions, returing the new expression.  If the expression
>> cannot
>> -// be normalized, a NULL_TREE is returned.
>
>
>> +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?
>
>> +   Note that this is the only place that we instantiate the
>> +   constraints. */
>> +bool
>> +check_constraints (tree ci, tree args)
>
>
> Except for tsubst_constraint?
>
>> +  ++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?
>
>> +   FIXME: This is defined in pt.c because it's garbage collection
>> +   code is not being generated for constraint.cc. */
>> +static GTY (()) hash_table<constr_hasher> *decl_constraints;
>
>
> I think you need to add constraint.cc to the gtfiles variable in
> cp/config-lang.in.  It also looks like the GTFILES_H rule in gcc/Makefile.in
> assumes that all sources have the .c extension, so that may need adjustment.
>
>> @@ -2454,6 +2454,8 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args,
>> bool d
>>               next = OVL_CHAIN (fn);
>> +              if (flag_concepts)
>> +                remove_constraints (OVL_FUNCTION (fn));
>
>
> I don't think we want to remove constraints here; this code is just
> discarding the OVERLOAD node, not the FUNCTION_DECL.
>
> Jason
>

Reply via email to