Some compilers (pgi/nvc ) issue "missing return statement" warning for functions like below, while others (gcc, clang) do not issue warnings even with -Wall -Wextra -pedantic
:
Is the code below legal according to the standard?
This is a minimal reproducible example of my code that gives the warning. Simplifying it to, say, just a single function removes the warning.
// test.cpp
#include <climits>
#include <cstddef>
#include <cstdint>
template<class T, std::size_t N>
class Test
{
public:
class Inner;
private:
using base_t = std::uint64_t;
static constexpr std::size_t NB_ = sizeof(base_t) * CHAR_BIT;
static constexpr std::size_t NI_ = (N NB_ - 1) / NB_;
};
template<class T, std::size_t N>
class Test<T, N>::Inner
{
public:
Inner() : b_{0}, j_{0} {}
friend bool operator!= (Inner x, Inner y)
{
if constexpr(J_ > 0)
return x.j_ != y.j_ || x.b_ != y.b_;
else
return x.b_ != y.b_;
}
private:
static constexpr std::size_t J_ = NI_ - 1;
base_t b_;
std::size_t j_;
};
int main()
{
Test<int, 50>::Inner x, y;
x != y;
}
Compilation:
> nvc test.cpp -std=c 17
"test.cpp", line 31: warning: missing return statement at end of non-void function "operator!="
}
^
detected during instantiation of class "Test<T, N>::Inner [with T=int, N=50UL]" at line 42
CodePudding user response:
The C standard says this, see [stmt.return]/2:
Flowing off the end of a constructor, a destructor, or a function with a cv
void
return type is equivalent to areturn
with no operand. Otherwise, flowing off the end of a function other thanmain
results in undefined behavior.
Your operator !=
does exactly that. It never flows off the end of the function since all control paths end with a return
.
Hence the code is correct, and the compiler's diagnostic is wrong.
CodePudding user response:
Could those projects be set to compile as an earlier standard of C ?
Some older compilers don't like returns in the middle of code blocks (there are also those that don't like variable identifiers anywhere other than at the start of code blocks).
For those that do complain I just code as:
ret_type f(...)
{
ret_type result = DEFAULT_VALUE; //default value defined elsewhere
if (condition)
result = value_1; //presumed valid ret_type value
else
result = value_2; //presumed valid ret_type value
return result;
}