Clang调试诊断信息Expressive Diagnostics
Clang调试诊断信息Expressive Diagnostics
除了快速和实用,目标是使 Clang用户友好。命令行编译器,使编译器生成的诊断(错误和警告消息)尽可能有用。有几种方法可以做到这一点。依据命令行编译器经验,将 Clang 输出与 GCC 4.9 的输出进行对比。
Column Numbers and Caret Diagnostics
首先,clang 生成的所有诊断,都包含完整的列号信息。clang 命令行编译器驱动程序使用此信息打印“点诊断”。(IDE 可以使用这些信息,显示内嵌错误标记)。可以很容易地准确理解特定代码段中的错误。
即使在字符串内部,点(绿色的“^”字符)准确地显示了问题。使得跳转到问题变得非常容易,当同一字符的多个实例,出现在一行上时,有所帮助。
$ clang -fsyntax-only format-strings.c
format-strings.c:91:13: warning: ‘.*’ specified field precision is missing a matching ‘int’ argument
printf("%.*d");
GCC 遵循 Clang 的做法,现在能够提供诊断列,在结果中包含源文本片段。但是,Clang 的列号要准确得多,指向有问题的格式说明符,不是解析器在检测到问题时,到达的)字符。默认情况下,Clang 的诊断是彩色的,更容易与附近的文本区分开来。
Range Highlighting for Related Text
Clang 捕获准确跟踪程序中表达式、语句和其它结构的范围信息,这些信息使诊断突出显示相关信息。下面有点荒谬的示例中,不需要查看原始源代码,可了解基于 Clang 错误的错误。clang 打印了一个点,确切地知道说明哪个加号。范围信息突出显示加号的左侧和右侧,编译器正在执行的内容一目了然。范围信息对于涉及优先级问题和许多其它情况非常有用。
$ gcc-4.9 -fsyntax-only t.c
t.c: In function ‘int f(int, int)’:
t.c:7:39: error: invalid operands to binary + (have ‘int’ and ‘struct A’)
return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);
^
$ clang -fsyntax-only t.c
t.c:7:39: error: invalid operands to binary expression (‘int’ and ‘struct A’)
return y + func(y ? ((SomeA.X + 40) + SomeA) / 42 + SomeA.X : SomeA.X);
~~~~~~~~~~~~~~ ^ ~~~~~
Precision in Wording
一个细节,尽力使clang 的诊断,准确包含有关错误和原因的相关信息。左边和右边的推断类型是什么,不会重复显而易见的内容(例如,一个“二进制+”)。
下面示例中,不仅会告诉有问题,还会确切地说明原因,告诉类型是什么(如果是一个复杂的子表达式,如调用重载函数)。这种对细节的关注,使得更容易理解和快速解决问题。
$ gcc-4.9 -fsyntax-only t.c
t.c:5:11: error: invalid type argument of unary ‘*’ (have ‘int’)
return *SomeA.X;
^
$ clang -fsyntax-only t.c
t.c:5:11: error: indirection requires pointer operand (‘int’ invalid)
int y = *SomeA.X;
^~~~~~~~
Typedef Preservation and Selective Unwrapping
许多程序员使用高级用户定义类型、typedef 和其它语法,引用程序中的类型。这可以缩写非常长的类型,在诊断中保留类型名很有用。然而,有时非常简单的 typedef,可以包装琐碎的类型,剥离 typedef,了解正在发生的事情。Clang 旨在很好地处理这两种情况。
以下示例显示在 C 中,保留 typedef 的重要性。
$ clang -fsyntax-only t.c
t.c:15:11: error: can’t convert between vector values of different size (’__m128’ and ‘int const *’)
myvec[1]/P;
~~~~~~~~^~
下例显示了编译器公开 typedef 的底层详细信息。如果用户对系统“pid_t”typedef 的定义方式感到困惑,Clang 会用“aka”帮助显示。
$ clang -fsyntax-only t.c
t.c:13:9: error: member reference base type ‘pid_t’ (aka ‘int’) is not a structure or union
myvar = myvar.x;
~~~~~ ^
在 C++ 中,类型保留包括保留写入类型名称的任何限定。如果采用一小段代码,例如:
namespace services {
struct WebService { };
}
namespace myapp {
namespace servers {
struct Server { };
}
}
using namespace myapp;
void addHTTPService(servers::Server const &server, ::services::WebService const http) {
server += http;
}
and then compile it, we see that Clang is both providing accurate information and is retaining the types as written by the user (e.g., “servers::Server”, “::services::WebService”):
编译后,看到 Clang 既提供了准确的信息,保留了用户编写的类型(例如,“servers::Server”、“::services::WebService”):
$ clang -fsyntax-only t.cpp
t.cpp:9:10: error: invalid operands to binary expression (‘servers::Server const’ and ‘::services::WebService const *’)
server += http;
~~~~~~ ^ ~~~~
自然地,类型保留扩展到模板的使用,在源代码中,Clang 保留有关特定模板特化(如std::vector),如何拼写的信息。例如:
$ clang -fsyntax-only t.cpp
t.cpp:12:7: error: incompatible type assigning ‘vector’, expected ‘std::string’ (aka ‘class std::basic_string’)
str = vec;
^ ~~~
Fix-it Hints
“Fix-it”提示为Fix-it源代码中的小、本地化问题提供建议。当 Clang 生成可以解决的特定问题的诊断时(例如,非标准或冗余语法、缺少关键字、常见错误等),可能以代码转换的形式提供特定指导,纠正错误问题。以下示例中,Clang 警告使用自 1993 年以来已被视为过时的 GCC 扩展。应删除带下划线的代码,然后替换为点线下方的代码(".x =" or “.y =”, respectively)。
$ clang t.c
t.c:5:28: warning: use of GNU old-style field designator extension
struct point origin = { x: 0.0, y: 0.0 };
~~ ^
.x =
t.c:5:36: warning: use of GNU old-style field designator extension
struct point origin = { x: 0.0, y: 0.0 };
~~ ^
.y =
“Fix-it”提示,对于解决常见的用户错误和误解最有用。例如,C++ 用户通常会忘记显式特化类模板的语法,如下例中的错误所示。同样,在描述问题后,Clang 提供了修复–添加 --template<>作为诊断的一部分。
$ clang t.cpp
t.cpp:9:3: error: template specialization requires ‘template<>’
struct iterator_traits<file_iterator> {
^
template<>
Template Type Diffing
模板类型可能很长且难以阅读。当错误消息的一部分时更是如此。Clang 不只是打印出类型名称,而是有足够的信息来删除公共元素并突出显示差异。为了更清楚地显示模板结构,模板类型也可以打印为缩进的文本树。
默认值:带有类型省略的模板差异
Default: template diff with type elision
t.cc:4:5: note: candidate function not viable: no known conversion from ‘vector<map<[…], float>>’ to ‘vector<map<[…], double>>’ for 1st argument;
-fno-elide-type: template diff without elision
t.cc:4:5: note: candidate function not viable: no known conversion from ‘vector<map<int, float>>’ to ‘vector<map<int, double>>’ for 1st argument;
-fdiagnostics-show-template-tree: template tree printing with elision
t.cc:4:5: note: candidate function not viable: no known conversion for 1st argument;
vector<
map<
[…],
[float != double]>>
-fdiagnostics-show-template-tree -fno-elide-type: template tree printing with no elision
t.cc:4:5: note: candidate function not viable: no known conversion for 1st argument;
vector<
map<
int,
[float != double]>>
Automatic Macro Expansion
许多错误,有时发生在深度嵌套的宏中。对于传统的编译器,需要深入研究宏的定义,了解是如何陷入困境的。下面简单示例,展示了 Clang 如何通过自动打印诊断信息和嵌套范围信息,通过宏实例化的,展示了其它一些部分,如何在更大的示例中工作。
$ clang -fsyntax-only t.c
t.c:80:3: error: invalid operands to binary expression (‘typeof§’ (aka ‘struct mystruct’) and ‘typeof(F)’ (aka ‘float’))
X = MYMAX(P, F);
^~~~~~~~~~~
t.c:76:94: note: expanded from:
#define MYMAX(A,B) extension ({ typeof(A) __a = (A); typeof(B) __b = (B); __a < __b ? __b : __a; })
~~~ ^ ~~~
Here’s another real world warning that occurs in the “window” Unix package (which implements the “wwopen” class of APIs):
这是在“window” Unix 包(实现了“wwopen”类 API)中出现的,另一个真实世界警告:
$ clang -fsyntax-only t.c
t.c:22:2: warning: type specifier missing, defaults to ‘int’
ILPAD();
^
t.c:17:17: note: expanded from:
#define ILPAD() PAD((NROW - tt.tt_row) * 10) / 1 ms per char */
^
t.c:14:2: note: expanded from:
register i;
^
在实践中,发现 Clang 对宏的处理,在多嵌套宏中比在简单宏中更有用。
Quality of Implementation and Attention to Detail
最后,投入了大量工作打磨小事,随着时间的推移累积起来,有助于提供出色的用户体验。
以下示例显示,从forgetting a 的简单情况中恢复;经过一个结构体定义,比GCC好得多。
$ cat t.cc
template
class a {};
struct b {}
a c;
$ gcc-4.9 t.cc
t.cc:4:8: error: invalid declarator before ‘c’
a c;
^
$ clang t.cc
t.cc:3:12: error: expected ‘;’ after struct
struct b {}
^
;
下面的例子表明,在 GCC 无法应对的复杂情况下,能很好地诊断和恢复缺少的 typename关键字。
$ cat t.cc
template void f(T::type) { }
struct A { };
void g()
{
A a;
f(a);
}
$ gcc-4.9 t.cc
t.cc:1:33: error: variable or field ‘f’ declared void
template void f(T::type) { }
^
t.cc: In function ‘void g()’:
t.cc:6:5: error: ‘f’ was not declared in this scope
f(a);
^
t.cc:6:8: error: expected primary-expression before ‘>’ token
f(a);
^
$ clang t.cc
t.cc:1:26: error: missing ‘typename’ prior to dependent type name ‘T::type’
template void f(T::type) { }
^~~~~~~
typename
t.cc:6:5: error: no matching function for call to ‘f’
f(a);
^~~~
t.cc:1:24: note: candidate template ignored: substitution failure [with T = A]: no type named ‘type’ in ‘A’
template void f(T::type) { }
^ ~~~~
这些细节中的每一个都是次要的,加起来可以提供更加精致的体验。
参考链接:
https://clang.llvm.org/diagnostics.html
Clang调试诊断信息Expressive Diagnostics相关推荐
- STL笔记(5)条款49:学习破解有关STL的编译器诊断信息
STL笔记(5)条款49:学习破解有关STL的编译器诊断信息 条款49:学习破解有关STL的编译器诊断信息 用一个特定的大小定义一个vector是完全合法的, vector<int> v( ...
- XP环境下调试诊断工具drwtsn32的使用说明
我们在使用程序过程中,经常会遇到如下的警告 在点击确定之后,出错的程序便退出了,这是由于当 Windows中出现程序错误时,系统将搜索错误处理程序.程序错误处理程序处理程序运行过程中出现的错误.如果系 ...
- 嵌入式系统调试诊断方法
嵌入式系统开发过程实际上就是一个调试诊断的过程,而且调试诊断将一直伴随着一个产品的终身,即使是最成熟的产品也偶尔会出现这样或那样的问题,这都需要开发人员去诊断.排查. 嵌入式系统的调试包括 ...
- Script:收集UNDO诊断信息
以下脚本可以用于收集Automatic Undo Management的必要诊断信息,以sysdba身份运行: spool Undo_Diag.out ttitle off set pages 999 ...
- 模型诊断(Model Diagnostics)是什么?具体包含哪些内容?
模型诊断(Model Diagnostics)是什么?具体包含哪些内容? 如何确定模型调优的方向与思路呢?这就需要对模型进行诊断的技术. 过拟合.欠拟合判断是模型诊断中至关重要的一步.常见的方法如交叉 ...
- linux下使用syslog日志调试程序快速的调试代码信息的过程
linux下使用syslog日志调试程序快速的调试代码信息的过程 环境背景:ubuntu 20.0.4 开发环境:QtCreator 功能:查看函数是否调用成功:函数调用执行的过程等等: 1.使用头文 ...
- InterDev 调试错误信息: Unable to set server into correct debugging state automatically....的解决办法...
InterDev 调试错误信息: Unable to set server into correct debugging state automatically.... 权威解决方法了: 1.安装 v ...
- Script:收集Exadata诊断信息
以下汇总的command 可以用于收集Exadata数据库一体机的诊断信息: 实例相关参数v$parameter Exadata相关的统计信息 v$sysstat 与Exadata相关的一些动态性 ...
- 车载诊断系列 —— 车辆诊断(Vehicle Diagnostics)
车载诊断系列 -- 车辆诊断(Vehicle Diagnostics) 大家好,我是穿拖鞋的汉子! 今天是2023年1月28日,春节假期开工第一天.晚上下班得空在电脑前,对以往工作内容做一个汇总,也算 ...
最新文章
- 计算机应用为什么要学机械制图,机械制图为什么这么难学?
- 数据结构与算法:04 C#面向对象设计 II
- ARINC818(FC-AV)协议详解
- wamp xampp mysql端口冲突,xampp安装后apache 80端口被占用的解决方法
- 复盘人生第一次科研经历
- Single Image Haze Removal Using Dark Channel Prior(使用暗通道先验去除单张图像雾霾)
- Android连接mumu模拟器
- feign.exception Connection reset executing
- 关于修改双系统默认启动项设置
- 【三年面试五年模拟】算法工程师的独孤九剑秘籍(第十式)
- 百度搜索引擎工作原理解读
- 小啊呜产品读书笔记001:《邱岳的产品手记-03》第04+05讲 如何当好AI时代的产品经理 06讲 产品案例分析·TheGuardian的文本之美
- 基本逻辑符号与数学符号列表
- 投资理财-赚取平均收益
- 基本数据类型一题解析:已知m=11,n=41,输出m和n的2次方、3次方、4次方。(附代码)
- 学游戏设计要什么学历_学历低学游戏动作设计好就业吗
- 关于web项目播放AMR格式音频的问题
- python如何输出结果至剪贴板_将“print”的输出直接复制到剪贴板
- java后台图片大小kb查看_java 根据图片地址获取到图片的大小,单位kb或者Mb
- Android TextView的属性与应用
热门文章
- java entries_Java ZipFile entries()用法及代码示例
- c语言中的右移是逻辑右移还是算术右移的问题
- 再探Direct3D流水线
- 【论文阅读】TimbreTron : A WaveNet (Cycle GAN(CQT(audio ))) pipeline for musical timbre transfer
- Github推荐--PC端下载bilibili视频
- js 获取图片经纬度及写经纬度
- 计算机微软云同步怎样安装软件,在windows10/8/7系统安装和设置OneDrive 同步文件...
- 仿今日头条项目——首页(文章搜索)
- php生成推广二维码海报、合成图片demo
- Centos 7安装tig报错:include/tig/tig.h:83:31: fatal error: ncursesw/curses.h: No such file or directory