https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91388
Bug ID: 91388 Summary: -Wreturn-type "no return statement" warning in function that is already ill-formed Product: gcc Version: 9.1.1 Status: UNCONFIRMED Keywords: diagnostic Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org Target Milestone: --- template<typename T> struct copyable; template<typename T> T func(const T& t) { static_assert(copyable<T>::value); return t; } struct NoCopy { NoCopy() { } NoCopy(const NoCopy&) = delete; }; template<> struct copyable<NoCopy> { static constexpr bool value = false; }; int main() { NoCopy nc; func(nc); } This produces the following diagnostics: nc.cc:20:10: required from here nc.cc:6:30: error: static assertion failed 6 | static_assert(copyable<T>::value); | ^~~~~ nc.cc:7:10: error: use of deleted function 'NoCopy::NoCopy(const NoCopy&)' 7 | return t; | ^ nc.cc:12:3: note: declared here 12 | NoCopy(const NoCopy&) = delete; | ^~~~~~ As the author of func<T> I have already added a static assertion to check if the return statement will be well-formed, so the second error is redundant (and I'd prefer for my users to not see it, the static assertion is for their benefit). So I try writing the function like this instead: template<typename T> T func(const T& t) { static_assert(copyable<T>::value); if constexpr (copyable<T>::value) return t; } Now the compiler says: nc.cc: In instantiation of 'T func(const T&) [with T = NoCopy]': nc.cc:22:10: required from here nc.cc:6:30: error: static assertion failed 6 | static_assert(copyable<T>::value); | ^~~~~ nc.cc:10:1: warning: no return statement in function returning non-void [-Wreturn-type] 10 | } | ^ To suppress the warning I need to do: template<typename T> T func(const T& t) { static_assert(copyable<T>::value); if constexpr (copyable<T>::value) return t; __builtin_unreachable(); } I don't think it should be necessary to mark it unreachable. The fact the static assertion failed means it's already guaranteed to be unreachable, because it's not even compilable! Could the -Wreturn-type warning be suppressed when the function is already ill-formed? I note that clang's -Wreturn-type diagnostic is phrased "warning: control reaches end of non-void function" and isn't given for ill-formed functions. That makes sense because control cannot reach the end of a function that cannot possibly execute.