ARM GCC 6.3.1编译带最终else的非void函数为何报control reaches end错误?
问题描述
我使用版本为6.3.1的ARM/GNU C编译器,在-O0优化等级下进行交叉编译,有如下简单函数:
static uint8_t xyzzy(void) { if (<predicate one>) { return 1; } else if (<predicate two>) { return 2; } else { return 4; } }
编译时出现如下错误:
Error control reaches end of non-void function [-Werror=return-type]
请问是编译器无法识别这三个分支必然有一个会执行返回语句吗?还是我的理解存在偏差?对应的推荐修复方案是什么?
(注:本问题不是“Control reach end of non-void function”的重复问题,因为我的代码最后一个从句就是else。)
问题原因
这是GCC 6.x版本在-O0无优化等级下的已知缺陷,并非你的代码逻辑有问题。
-O0优化等级下GCC关闭了绝大多数静态分析优化,不会做完整的代码路径可达性推导,无法识别到你最后兜底的else分支已经覆盖了所有可能的执行路径,因此误判存在没有返回值的代码路径。
推荐修复方案
- 方案1:最简便的处理方式是在函数末尾加一行冗余的return语句,返回值和else分支的返回值保持一致即可,实际运行不会执行到这行代码,不会影响原有逻辑:
static uint8_t xyzzy(void) { if (<predicate one>) { return 1; } else if (<predicate two>) { return 2; } else { return 4; } return 4; // 冗余返回,消除GCC 6.x的误报 }
- 方案2:如果不想添加冗余代码,可以单独为该函数添加编译属性,屏蔽该函数的返回类型警告,不影响全局的警告检查,避免漏掉真正的返回值缺失问题:
__attribute__((optimize("-Wno-return-type"))) static uint8_t xyzzy(void) { // 原有代码不变 }
- 方案3:升级GCC编译器版本,更高版本的GCC已经修复了-O0等级下控制流分析的这个缺陷,不会再对这类明确覆盖全路径的代码误报该错误。
内容的提问来源于stack exchange,提问作者fearless_fool
相关产品推荐
相关产品推荐

