Clang开启-Wdangling-gsl时花括号初始化无警告,是否为编译器bug?
问题描述
参考如下代码片段:
#include <string> #include <string_view> int main() { auto str = std::string{}; auto sv1 = std::string_view(str + "!"); // <- 触发警告 :) std::string_view sv2(str + "!"); // <- 触发警告 :) std::string_view sv3 = str + "!"; // <- 触发警告 :) auto sv4 = std::string_view{str + "!"}; // <- 无警告 :( std::string_view sv5{str + "!"}; // <- 无警告 :( }
使用编译参数 -std=c++17 -Wdangling-gsl 编译,测试环境为Clang 12.0.1以及Compiler Explorer上的Clang trunk版本。
sv1、sv2、sv3三种写法中str + "!"都会触发如下警告:
Object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
但同样的表达式在sv4、sv5中使用{}初始化时,没有触发任何警告。
问:该情况是花括号初始化的预期行为?是Clang的bug?还是遗漏了什么要点?
解答
结论
这是Clang -Wdangling-gsl检查的实现缺陷,属于未覆盖场景的bug,不是C++标准规定的花括号初始化的预期行为。
具体说明
- 从C++语义层面判断,5种初始化写法没有本质差异:
str + "!"生成的临时std::string对象,会在完整表达式结束后销毁,所有构造出的std::string_view都会持有悬空指针,全部属于非法用法。 - 警告漏出的原因是Clang的
-Wdangling-gsl检查逻辑仅覆盖了小括号初始化、复制初始化的检测分支,暂时没有对花括号列表初始化的场景做对应校验,属于检查能力的漏判,和代码本身的语义无关。 - 目前该问题已经被上报到Clang的bug跟踪系统,后续版本大概率会补全该场景的检测能力。
使用建议
在该问题修复前,初始化std::string_view时无论采用哪种语法,都要手动确认被引用的对象生命周期长于std::string_view本身,不要完全依赖编译警告的提示。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

