【问题标题】:"Control reaches end on non-void function" with do { return result; } while(condition);“控制在非无效函数上结束”与 do { return result; } 而(条件);
【发布时间】:2017-08-09 02:49:30
【问题描述】:

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

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

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

添加了最后一行用于测试,替换了使用的宏。 Visual Studio 没有看到这段代码有问题,但是 g++ 生成了

警告:控制到达非空函数的结尾 [-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

不确定所有这些意味着什么。

【问题讨论】:

  • 我打了一个答案,但仔细检查你的例子,我很惊讶 g++ 在这种情况下发出警告。
  • 实际上它应该引发另一个警告,content.size() != 0 不可访问。所以这段代码还是有问题的。
  • 可能是 gcc 在 do..while 的流控制分析中没有特殊情况。条件可能是假的,所以循环可能不会运行......至少这是其他循环的有效推理。
  • @Slava 我相信我已经解释了while() 中的非常量表达式的来源。另外,我不记得曾经用这个习语看到过“无法访问的代码”警告。
  • @Abstraction 您的解释并没有使该代码不被破坏。我还说它应该发出警告,但它没有义务这样做。

标签: c++ gcc gcc-warning


【解决方案1】:

这很奇怪。带有 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() 提出了一个“未使用的变量”。

一种可能的解释是,您所拥有的 在实践中并未真正使用。发生死代码消除,只留下 return 语句。

但是,当我们使用一个额外的变量时,死代码消除机制就不能以同样的方式工作,一些信息被保留了,它看不到返回语句。

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


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

【讨论】:

  • 感谢您的研究。更新为显示我的问题的实际代码示例。你能试试最后两个吗?
  • 感谢@Abstraction 提出的好问题。有趣的东西,回答更新
猜你喜欢
  • 2015-01-10
  • 2018-05-16
  • 1970-01-01
  • 2012-04-07
  • 2011-01-27
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
  • 2020-01-21
相关资源
最近更新 更多