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

            Bug ID: 69096
           Summary: [concepts] return type deduction before checking
                    constraint satisfaction
           Product: gcc
           Version: 6.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: Casey at Carter dot net
  Target Milestone: ---

Created attachment 37196
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=37196&action=edit
Test case

r231964 miscompiles this valid TU:

template <class R>
constexpr bool has_customization = false;
template <class R>
requires
  requires(R&& r) { iter_move((R&&)r); }
constexpr bool has_customization<R> = true;

template <class C>
struct basic_iterator
{
  C pos_;

  // template <int=42>
  friend decltype(auto) iter_move(const basic_iterator& i)
  requires
    requires { i.pos_.move(); }
  {
    return i.pos_.move();
  }
};

static_assert(!has_customization<basic_iterator<int>>);

which it diagnoses with:

~/gcc6-r231964/bin/g++ -std=c++1z foo.cpp -c
foo.cpp: In instantiation of ‘decltype(auto) iter_move(const
basic_iterator<int>&)’:
foo.cpp:5:30:   required from here
foo.cpp:18:19: error: request for member ‘move’ in
‘i.basic_iterator<int>::pos_’, which is of non-class type ‘const int’
     return i.pos_.move();
            ~~~~~~~^~~~

The program compiles correctly - the iter_move definition properly does not
participate in overload resolution - if:
* the "template <int=42>" line is uncommented so that iter_move is a function
template, or
* the return type is declared as int or void, presumably anything that doesn't
require return type deduction.

I speculate that the compiler is performing return type deduction *before*
checking for satisfaction of the associated constraints.

Reply via email to