Are there cases of complilers not being able to diagnose missing return?

大憨熊 提交于 2020-04-13 03:56:32

问题


I did some research to find out why a missing return cannot be an error but is undefined behavior instead. I found this comment in a bug report that uses the following example to illustrate why it cannot be an error:

   template<typename T>
   T maybe_call(std::function<T(void)> f) {
           if (f)
                   return f();
           else
                   abort_program();

           // Cannot write a return here, because we have no way to create a value of t
   }

Note that this example is completely valid code. It has no return on all branches, but still there is no UB. That explains why not having a return on all branches is UB, not an error. The example could be "fixed" to declare abort_program(); as [[noreturn]] to make it less of a counter argument. I doubt that compilers would have problems to correctly diagnose this example. If missing a return would be turned into an error, rules would maybe have to change a bit, because only with the [[noreturn]] the above example can be diagnosed correctly.

However, what I am looking for is a different example where the compiler cannot detect a missing return. That comment also mentions that cases exists that cannot be diagnosed by the compiler, but I fail to find such an example.

If the warning would be reliable (false positives like the one above aside) I could treat the warning as error to be on the safe side.

Are there really cases where a compiler cannot detect a missing return? Is it only in pathological code, or can it happen in every day code too? Can I rely on the warning?

To make it answerable, lets concentrate on gcc(latest version): In what case gcc fails to warn for a missing return?


回答1:


It is difficult to prove the non-existence of something, but having a hard time to find an example is convincing enough to see that only pathological code would cause the compiler to not warn about a missing return.

First my line of thinking was to construct a convoluted example along the line of:

int fun() {
    goto exit;
    return 1;
    exit: ;      
}

However, no matter how hard I try, gcc will warn about such code. The more I think about it, the more I get convinced that the problem is not that there can be code where the compiler will not warn, but rather false postives. If the example in the question is changed to

   template<typename T>
   T maybe_call(std::function<T(void)> f) {
           if (f)
                   return f();
           else
                   maybe_abort_program();

           // Cannot write a return here, because we have no way to create a value of t
   }

Then it would be up to the compiler to decide whether maybe_abort_program eventually returns and that is the halting problem which cannot be decided in all cases. Changing the name of the function of course changes nothing, but it is just to highlight that even thought that function could be marked as [[noreturn]], not marking it as such the code can still be valid (or not) and the compiler cannot reliably diagnose that.

However, compilers can warn about such cases. And after experimenting a bit I did not find any example where the compiler does not warn. Hence my conclusion is: I can (to some extend) rely on the warning.




回答2:


There is no reason for any such case to exist.

Every code path in a function in a well-defined program should contain only data manipulation (which cannot terminate the function's execution), internal flow (loops etc that are self-contained in the function by definition), return statements which end the function and throws/longjmps/exits/aborts which also end the function. These are all trivially visible to the compiler.

Other than that, it's just function calls, to which the same applies recursively.

The example/bug you mention here is literally the opposite: getting the warning because you didn't write a return, and you're relying on a called function to perform a throw/longjmp/exit/abort, which the compiler may not know about, and your function would have undefined behaviour if the called function doesn't perform that… and you did not use a compiler intrinsic to signal that your code path is "unreachable". Usually I much prefer the intrinsic to turning off -Werror; it can even give you performance benefits!



来源:https://stackoverflow.com/questions/60966763/are-there-cases-of-complilers-not-being-able-to-diagnose-missing-return

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!