This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/67070] [concepts] Concept with negation and disjunction not checked correctly


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67070

Jason Merrill <jason at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
   Last reconfirmed|                            |2015-07-31
     Ever confirmed|0                           |1

--- Comment #1 from Jason Merrill <jason at gcc dot gnu.org> ---
This issue is another consequence of my earlier observation about the !
operator, that it produces a single predicate.

Reduced:

template <class T> concept bool A
  = requires { typename T::Type; } && T::Type::value;

template <class T> requires !A<T>
void f() { }

struct B { };

int main()
{
  f<B>();
}

Here f has a single atomic predicate constraint,

  !(requires { typename T::Type } && T::Type::value)

Substitution into this constraint fails because B has no member Type, and
template argument substitution doesn't stop after substituting into the
requires-expression.  Since argument substitution fails, the predicate
constraint is not satisfied.

We can make this work by moving the second reference to T::Type inside the
requires-expression:

template <class T> concept bool A
  = requires {
      typename T::Type;
      requires T::Type::value;
    };

template <class T> requires !A<T>
void f() { }

struct B { };

int main()
{
  f<B>();
}

Your testcase has this problem with Dereferenceable and Range, though fixing
that doesn't make it work; I expect there's something else similar going on.

This is a very subtle point.  It seems to me that it would be better if
creating the normal form of a constaint stops substituting into concept bodies
once it's clear that we're inside an atomic constraint.  So f would have a
single atomic predicate constraint

 !A<T>

and then when we consider this later we try to satisfy A<B>, which fails, so
f's constraint is satisfied and the testcase succeeds.  Though this does create
an inconsistency in argument substitution behavior across the ! operator, which
might be confusing.

Any thoughts, Andrew?


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]