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

            Bug ID: 92477
           Summary: [[nodiscard]] method in a decltype expression causes
                    "warning: ignoring return value of"
           Product: gcc
           Version: 9.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: src at andyf dot de
  Target Milestone: ---

Hello,

consider this code:

class Test
{
public:
    [[nodiscard]] int Get() const { return 42; }
};

template<typename T>
auto UsedForSFINAE(const T& t) -> decltype(t.Get(), void())
{
}

template<typename T>
auto UsedAsReturnValue(const T& t) -> decltype(t.Get())
{
    return t.Get();
}

int main()
{
    Test t{};

    UsedForSFINAE(t);
    UsedAsReturnValue(t);
}


It tries to SFINAE out the UsedForSFINAE based on whether the type passed has a
method Get. The decltype expression in
UsedForSFINAE causes a warning in GCC with -Wall passed:

warning: ignoring return value of 'int Test::Get() const', declared with
attribute nodiscard [-Wunused-result]

    8 | auto UsedForSFINAE(const T& t) -> decltype(t.Get(), void())

<source>:4:23: note: declared here

    4 |     [[nodiscard]] int Get() const { return 42; }

      |                       ^~~

Clang on the other hand is fine with it (see https://godbolt.org/z/9U4ceB). The
warning goes away when t.Get() is casted to void. There is no warning, if the
decltype's resulting type is used as the return type (as for
UsedAsReturnValue).

I talked to Richard Smith about this last week at WG21 Belfast and he told me
that Clang is correct. Unfortunately, I don't recall his exact rational. I
think it was that in [dcl.type.decltype] is says "The operand of the decltype
specifier is an unevaluated operand (7.2)."


Bug 57857 looks a bit similar.

Cheers,
   Andreas

Reply via email to