c++c++20compiler-warningsgcc-warning

Control reaches end of non-void function, except it doesn't?


I have some code that I simplified to this:

#include <iostream>
#include <string>


enum En
{
    one,
    two,
    three
};

auto get_str(int n, En en)
{
    if (n > 0)
    {
        return std::to_string(n);
    }

    switch (en)
    {
        case one:
            return std::string("one");
        case two:
            return std::string("two");
        case three:
            return std::string("three");
    }
}

int main()
{
    auto str = get_str(3, two);
    std::cout << str << '\n';
}

See on compiler explorer.

When I compile with GCC 14.2 or 13.3.0 (with or without -Wall -Wextra), it complains about get_str function: warning: control reaches end of non-void function [-Wreturn-type].

Clang 15.0 and above with -Wall -Wextra does not emit any warning. VS17.10 also complains: warning C4715: 'get_str': not all control paths return a value.

What causes Clang to disagree? What is the path that bypasses returns?


Solution

  • All compilers are correct in their own way. The relevant wording is in [dcl.enum] p8:

    For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type. Otherwise, the values of the enumeration are the values representable by a hypothetical integer type with minimal width M such that all enumerators can be represented. [...] It is possible to define an enumeration that has values not defined by any of its enumerators.

    What that means for your code is:

    When GCC warns you, it's correct. If En(3) is passed to get_str, control flows off the end of the function, and you get undefined behavior.

    When other compilers don't warn you, they're also correct. The standard doesn't require a warning to be emitted in this situation.

    There are a few possible workarounds here, which should silence the warning: