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