"Control reaches end on non-void function" with do { return 结果; } 而(条件);

"Control reaches end on non-void function" with do { return result; } while(condition);

我有以下功能(简化示例):

QByteArray DecompressBytes(const QByteArray& content){
  /* function body (with other return expressions) */

  do { return content; } while(content.size() != 0);
}

为测试添加了最后一行,替换了使用的宏。 Visual Studio 没有发现此代码有问题,但 g++ 生成

warning: control reaches end of non-void function [-Wreturn-type]

将最后一行更改为 return content; 会删除警告。
我的问题:为什么编译器以这种方式运行,代码的形式应该是什么以避免任何警告?

最后一行是 ASSERT_FAIL("must be unreachable", content)ASSERT_FAIL 扩展为 do { ... } while(false) 模式,另一个宏替换 while 以禁止非布尔表达式,所以结果表达式就像 do { qt_assert_x("", "", 42); return content; } while(::helper::bool_verify(false));

g++ 版本 5.3.0,与 MinGW(标准 Qt 设置)一起使用。

更新: 在尝试注释代码的不同部分后(因为上面的纯示例不允许重现问题),出现了一些非常奇怪的东西:

QByteArray DecompressBytes(const QByteArray& content){
  QByteArray decompressed; //no 'unused variable' warning
  do { return content; } while(content.size() != 0);
} //produces warning above

QByteArray DecompressBytes2(const QByteArray& content){
  //QByteArray decompressed;
  do { return content; } while(content.size() != 0);
} //doesn't produce warning

std::vector<char> DecompressBytes3(const std::vector<char>& content){
  std::vector<char> decompressed; //no 'unused variable' warning

  do { return content; } while(content.size() != 0);
} //does produce warning

std::vector<char> DecompressBytes4(const std::vector<char>& content){
  int decompressed; //unused variable warning is given

  do { return content; } while(content.size() != 0);
} //doesn't produce warning

不确定这一切意味着什么。

这很奇怪。带有 Wall 标志的 GCC 4.9.2 不会抱怨这个类似的代码(我还没有安装 qt)

#include <vector>

std::vector<int> foo(const std::vector<int>& v)
{
    do { return v; } while( v.size() != 0 );
}

int main() {std::vector<int> v; foo(v);}

与 clang 4.2.1 相同。因此,我会说这是特定于您的安装的东西,如果我是您,我会在函数末尾添加一个虚拟 return 语句,或者使用一个标志来消除此警告。


更新:使用 GCC 重现了 OP 提供的最后两个新函数的行为,而 clang 仅针对 DecompressBytes4().

提出了 'unused variable'

一个可能的解释是 你那里的这个 实际上并没有真正使用过。出现死代码消除,只留下 return 语句。

然而,当我们使用一个额外的变量时,死代码消除机制不会以同样的方式工作,一些信息被保留并且它看不到 return 语句。

通常死代码消除发生在后端,而警告则由前端提出。在这种情况下,这两个似乎没有很好地沟通! =)


PS - Dead code elimination 解释了为什么您也没有收到无法访问的警告。