“控制到达非 void 函数末尾” with do { return result; while(条件);

Abs*_*ion 5 c++ gcc gcc-warning

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

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

  do { return content; } while(content.size() != 0);
}
Run Code Online (Sandbox Code Playgroud)

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

警告:控制到达非 void 函数的末尾 [-Wreturn-type]

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

最后一行过去是扩展为ASSERT_FAIL("must be unreachable", content)模式,并用另一个宏替换以禁止非布尔表达式,因此生成的表达式类似于. ASSERT_FAILdo { ... } while(false)whiledo { 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
Run Code Online (Sandbox Code Playgroud)

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

gsa*_*ras 4

真奇怪。带有 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);}
Run Code Online (Sandbox Code Playgroud)

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


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

一种可能的解释是,这种 you have there 并没有真正在实践中使用。发生死代码消除,只留下 return 语句。

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

通常死代码消除发生在后端,而警告则由前端发出。这样看来,两人的沟通并不顺畅啊!=)


PS -死代码消除解释了为什么您也不会收到无法访问的警告。