报错log:
drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c: In function 'rwnx_txq_vif_for_each_sta':
drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c:642:12: error: this statement may fall through [-Werror=implicit-fallthrough=]
642 | rwnx_vif = rwnx_vif->ap_vlan.master;
| ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
drivers/net/wireless/aic8800/aic8800_fdrv/rwnx_txq.c:643:2: note: here
643 | case NL80211_IFTYPE_AP:
| ^~~~
源码报错位置:
switch (RWNX_VIF_TYPE(rwnx_vif)) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
{
if (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE)
f(rwnx_vif->sta.tdls_sta, reason, rwnx_hw);
if (!WARN_ON(rwnx_vif->sta.ap == NULL))
f(rwnx_vif->sta.ap, reason, rwnx_hw);
break;
}
case NL80211_IFTYPE_AP_VLAN:
rwnx_vif = rwnx_vif->ap_vlan.master;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_P2P_GO:
{
struct rwnx_sta *sta;
list_for_each_entry(sta, &rwnx_vif->ap.sta_list, list) {
f(sta, reason, rwnx_hw);
}
break;
}
default:
BUG();
break;
}
可以看到是code中的 case NL80211_IFTYPE_AP 没有break而发生警告
警告不会导致编译报错,但是编译参数中定义了 -Werror 从而导致编译报错
解决方法:
一、找到makefile中的-Werror,删除它
二、加入break(这可能不满足代码预期)
三、使用:GCC pragma #pragma GCC diagnostic ignored "-Wimplicit-fallthrough",来禁用代码警告
如下示例(亲测有效):
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"switch (RWNX_VIF_TYPE(rwnx_vif)) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
{
if (rwnx_vif->tdls_status == TDLS_LINK_ACTIVE)
f(rwnx_vif->sta.tdls_sta, reason, rwnx_hw);
if (!WARN_ON(rwnx_vif->sta.ap == NULL))
f(rwnx_vif->sta.ap, reason, rwnx_hw);
break;
}
case NL80211_IFTYPE_AP_VLAN:
rwnx_vif = rwnx_vif->ap_vlan.master;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
case NL80211_IFTYPE_P2P_GO:
{
struct rwnx_sta *sta;
list_for_each_entry(sta, &rwnx_vif->ap.sta_list, list) {
f(sta, reason, rwnx_hw);
}
break;
}
default:
BUG();
break;
}
#pragma GCC diagnostic pop
注意:编译时,会在push和pop之间,禁用警告(此方法会导致此部分code调试困难,因为看不到警告)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
//内容
#pragma GCC diagnostic pop
四、使用__attribute__((__fallthrough__))(亲测有效,且kernel中很多地方在用);
在switch中不期望break的地方,加入__attribute__((__fallthrough__));
如下示例:
int main()
{
enum nl80211_iftype ss = NL80211_IFTYPE_UNSPECIFIED;
switch(ss){
case NL80211_IFTYPE_UNSPECIFIED:
printf("Hello, World! 11\n");
__attribute__((__fallthrough__));
case NL80211_IFTYPE_ADHOC:
printf("Hello, World! 222\n");
case NL80211_IFTYPE_STATION:
printf("Hello, World! 33\n");
break;
default:
printf("Hello, World! 55\n");
}
return 0;
}
kernel-5.10中,对此属性做了重定义,如下
kernel-5.10/include/linux/compiler_attributes.h
/*
* Add the pseudo keyword 'fallthrough' so case statement blocks
* must end with any of these keywords:
* break;
* fallthrough;
* goto <label>;
* return [expression];
*
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#Statement-Attributes
*/
#if __has_attribute(__fallthrough__)
# define fallthrough __attribute__((__fallthrough__))
#else
# define fallthrough do {} while (0) /* fallthrough */
#endif