Home > front end >  warning: control reaches end of non-void function [-Wreturn-type] removed when declaring method inli
warning: control reaches end of non-void function [-Wreturn-type] removed when declaring method inli

Time:02-02

With this code

enum EnumTypes
{
    one,
    two
};

int enum_to_int(EnumTypes enum_type)
{
    switch(enum_type)
    {
        case one: return 1;
        case two: return 2;
    }
}

I get the following warning:

: In function 'int enum_to_int(EnumTypes)': :14:1: warning: control reaches end of non-void function [-Wreturn-type] 14 | }

, which I understand is a valid warning since enum_type could have some other value stored than one and two.

However, if I mark the method as inline as the following, the warning disappears.

enum EnumTypes
{
    one,
    two
};

inline int enum_to_int(EnumTypes enum_type)
{
    switch(enum_type)
    {
        case one: return 1;
        case two: return 2;
    }
}

Should there not be a warning if function is marked inline?

CodePudding user response:

inline does not guarantee that the function is inlined. It might be inlined or not. I did not manage to call the function and not get the warning. For example:

enum EnumTypes
{
    one,
    two
};

inline int enum_to_int(EnumTypes enum_type)
{
    switch(enum_type)
    {
        case EnumTypes::one: return 1;
        case EnumTypes::two: return 2;
    }
}

int main() {
    return enum_to_int(1);
}

Results in:

<source>: In function 'int main()':
<source>:17:24: error: invalid conversion from 'int' to 'EnumTypes' [-fpermissive]
   17 |     return enum_to_int(1);
      |                        ^
      |                        |
      |                        int
<source>:7:34: note:   initializing argument 1 of 'int enum_to_int(EnumTypes)'
    7 | inline int enum_to_int(EnumTypes enum_type)
      |                        ~~~~~~~~~~^~~~~~~~~
<source>: In function 'int enum_to_int(EnumTypes)':
<source>:14:1: warning: control reaches end of non-void function [-Wreturn-type]
   14 | }
      | ^
ASM generation compiler returned: 1
<source>: In function 'int main()':
<source>:17:24: error: invalid conversion from 'int' to 'EnumTypes' [-fpermissive]
   17 |     return enum_to_int(1);
      |                        ^
      |                        |
      |                        int
<source>:7:34: note:   initializing argument 1 of 'int enum_to_int(EnumTypes)'
    7 | inline int enum_to_int(EnumTypes enum_type)
      |                        ~~~~~~~~~~^~~~~~~~~
<source>: In function 'int enum_to_int(EnumTypes)':
<source>:14:1: warning: control reaches end of non-void function [-Wreturn-type]
   14 | }
      | ^
Execution build compiler returned: 1

UB is only triggered when the function is actually called. And there is no UB when 0 or 1 is passed. It might be intentional, that there is no return otherwise.

However, I would expect the warning nevertheless. It can be considered a bug.

CodePudding user response:

In contrast to a non-inline function with external linkage, an inline function or a function with internal linkage (static) is guaranteed to be defined in every translation unit (odr-)using the function (or else the program is ill-formed).

The compiler is therefore just being "lazy" and doesn't emit a definition for the inline function, since you don't (odr-)use it in the translation unit.

If you (odr-)use it in any way, it will be emitted and the checks wont be skipped. It is enough to take a pointer to the function:

auto ptr = &enum_to_int;

And then the warning will appear again.


It is probably reasonable that the compiler doesn't check the function for such issues in a translation unit where the definition doesn't need to be emitted. It is guaranteed that the program either doesn't use the function at all, in which case the problem doesn't really matter, or it is (odr-)used in another translation unit and the warning will be produced there.

Checking it in all translation units would probably just be wasted time.

  •  Tags:  
  • Related