Home > OS >  C error: non-void function does not return a value in all control paths [-Werror,-Wreturn-type]
C error: non-void function does not return a value in all control paths [-Werror,-Wreturn-type]

Time:12-26

I am writing a function to validate if the strlen of a string = 26 or not and returning a boolean value however I get an error message stating "error: non-void function does not return a value in all control paths [-Werror,-Wreturn-type]" despite there being no way for a value not to be returned. (i have tried it with just else instead of else if and get same error)

bool ValidateLength(string key, int argc)  
{
    if (strlen(key) != 26)
    {
        printf("Usage: ./substitution key\n");
        printf("Key must consist of 26 alphabetic characters.\n");
        return false;
    }
    else if (strlen(key) == 26)
    {
        return true;
    }
}

CodePudding user response:

Your block if/else if is overconstrained....

Have you tried this ?

bool ValidateLength(string key, int argc)  
{
    if (strlen(key) == 26)
        return true;

    printf("Usage: ./substitution key\n");
    printf("Key must consist of 26 alphabetic characters.\n");
    return false;
}

CodePudding user response:

Although GCC is able to analyze the code and determine that one of the cases is executed (as shown in the supplement below), presumably this analysis occurs only later in the compilation process. During the initial analysis, the code nominally contains three code paths. Three potential reasons for this come to mind:

  • Due to the way the compiler is constructed, warnings are generally reported early, and suppressing this warning based on later analysis would be difficult.
  • It was deemed useful to report this warning as it typically results from inadvertent program design rather than intentional coverage of all cases with a redundant test.
  • The opportunity to suppress the warning was overlooked.

Nonetheless, this is easy to work around. The code can be rewritten as either:

bool ValidateLength(string key, int argc)  
{
    if (strlen(key) != 26)
    {
        printf("Usage: ./substitution key\n");
        printf("Key must consist of 26 alphabetic characters.\n");
        return false;
    }
    else
    {
        return true;
    }
}

or:

bool ValidateLength(string key, int argc)  
{
    if (strlen(key) != 26)
    {
        printf("Usage: ./substitution key\n");
        printf("Key must consist of 26 alphabetic characters.\n");
        return false;
    }
    return true;
}

Although you report testing the former option, GCC will not report the warning in this case, so I believe your test was faulty, such as compiling code other than what you attempted to compile.

Supplement

Arguably, this is a shortcoming in the compiler. Looking at the assembly GCC 11.2 generates for this with -O3, we see it has in fact recognized that the union of all cases in the if and else if covers all possibilities: It has generated only two code paths, not three. It calls strlen once and either jumps to .L1 or falls through to the “then” code, which rejoins at .L1. Both paths return a value. So GCC knows there is no possible control path that does not return a value, but it reported the warning (elevated to an error) anyway.

Further, testing by changing the function return type to int and changing the returns to 0 in the “then” code, 1 in the “else if” code, and 2 outside that shows assembly code that only returns 0 or 1, proving GCC was not just collapsing the third path into “undefined behavior”; it outright eliminates it because it is not possible.

  • Related