• A weird bug in Clang

    From Andrey Tarasevich@21:1/5 to All on Thu Sep 19 19:59:23 2024
    Seems to be reproducible in all Clang versions

    struct A {};

    template <typename = int> struct C
    {
    C() = default;
    C(const A &) {}
    C &operator =(const A &a) { return operator =(C(a)); }
    };

    int main()
    {
    A a;
    C<> c;
    c = a;
    }

    Results in

    error: no viable conversion from 'C<>' to 'const A'
    7 | C &operator =(const A &a) { return operator =(C(a)); }
    | ^~~~

    It appears that a user-declared converting assignment operator somehow suppressed the compiler-provided copy-assignment operator for `C<>`. The
    issue is only present when `C` is a template.

    The problem can be fixed by calling the compiler-provided
    copy-assignment operator through an explicit `this->`

    C &operator =(const A &a) { return this->operator =(C(a)); }

    or by adding an explicit declaration of the copy-assignment operator

    C &operator =(const C &) = default;

    Am I missing something obvious here? GCC and MSVC++ accept the original
    version of the code without any issues.

    --
    Best regards,
    Andrey

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Andrey Tarasevich@21:1/5 to Andrey Tarasevich on Fri Sep 20 07:12:39 2024
    On 09/19/24 7:59 PM, Andrey Tarasevich wrote:
      struct A {};

      template <typename = int> struct C
      {
        C() = default;
        C(const A &) {}
        C &operator =(const A &a) { return operator =(C(a)); }
      };

      int main()
      {
        A a;
        C<> c;
        c = a;
      }

    This significantly reduced version of the code sheds some light on the
    inner workings of the bug

    template <typename = int> struct C
    {
    C &foo(const C &c) { return operator =(c); }
    };

    int main()
    {
    C<> c;
    c.foo(c);
    }

    Clang complains with

    error: explicit qualification required to use member 'operator=' from dependent base class
    3 | C &foo(const C &c) { return operator =(c); }

    "Dependent base class"? What "dependent base class"? There are no base
    classes involved in this example.

    Apparently Clang decides that a reference to an implicitly-declared copy-assignment operator is an accidental reference to an operator from
    a base class (since it does not see an explicit declaration here). This
    also explains why `this->` provides a workaround.

    --
    Best regards,
    Andrey

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)