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相关推荐

  1. STL笔记(5)条款49:学习破解有关STL的编译器诊断信息

    STL笔记(5)条款49:学习破解有关STL的编译器诊断信息 条款49:学习破解有关STL的编译器诊断信息 用一个特定的大小定义一个vector是完全合法的, vector<int> v( ...

  2. XP环境下调试诊断工具drwtsn32的使用说明

    我们在使用程序过程中,经常会遇到如下的警告 在点击确定之后,出错的程序便退出了,这是由于当 Windows中出现程序错误时,系统将搜索错误处理程序.程序错误处理程序处理程序运行过程中出现的错误.如果系 ...

  3. 嵌入式系统调试诊断方法

    嵌入式系统开发过程实际上就是一个调试诊断的过程,而且调试诊断将一直伴随着一个产品的终身,即使是最成熟的产品也偶尔会出现这样或那样的问题,这都需要开发人员去诊断.排查.       嵌入式系统的调试包括 ...

  4. Script:收集UNDO诊断信息

    以下脚本可以用于收集Automatic Undo Management的必要诊断信息,以sysdba身份运行: spool Undo_Diag.out ttitle off set pages 999 ...

  5. 模型诊断(Model Diagnostics)是什么?具体包含哪些内容?

    模型诊断(Model Diagnostics)是什么?具体包含哪些内容? 如何确定模型调优的方向与思路呢?这就需要对模型进行诊断的技术. 过拟合.欠拟合判断是模型诊断中至关重要的一步.常见的方法如交叉 ...

  6. linux下使用syslog日志调试程序快速的调试代码信息的过程

    linux下使用syslog日志调试程序快速的调试代码信息的过程 环境背景:ubuntu 20.0.4 开发环境:QtCreator 功能:查看函数是否调用成功:函数调用执行的过程等等: 1.使用头文 ...

  7. InterDev 调试错误信息: Unable to set server into correct debugging state automatically....的解决办法...

    InterDev 调试错误信息: Unable to set server into correct debugging state automatically.... 权威解决方法了: 1.安装 v ...

  8. Script:收集Exadata诊断信息

    以下汇总的command 可以用于收集Exadata数据库一体机的诊断信息:   实例相关参数v$parameter Exadata相关的统计信息 v$sysstat 与Exadata相关的一些动态性 ...

  9. 车载诊断系列 —— 车辆诊断(Vehicle Diagnostics)

    车载诊断系列 -- 车辆诊断(Vehicle Diagnostics) 大家好,我是穿拖鞋的汉子! 今天是2023年1月28日,春节假期开工第一天.晚上下班得空在电脑前,对以往工作内容做一个汇总,也算 ...

最新文章

  1. 计算机应用为什么要学机械制图,机械制图为什么这么难学?
  2. 数据结构与算法:04 C#面向对象设计 II
  3. ARINC818(FC-AV)协议详解
  4. wamp xampp mysql端口冲突,xampp安装后apache 80端口被占用的解决方法
  5. 复盘人生第一次科研经历
  6. Single Image Haze Removal Using Dark Channel Prior(使用暗通道先验去除单张图像雾霾)
  7. Android连接mumu模拟器
  8. feign.exception Connection reset executing
  9. 关于修改双系统默认启动项设置
  10. 【三年面试五年模拟】算法工程师的独孤九剑秘籍(第十式)
  11. 百度搜索引擎工作原理解读
  12. 小啊呜产品读书笔记001:《邱岳的产品手记-03》第04+05讲 如何当好AI时代的产品经理 06讲 产品案例分析·TheGuardian的文本之美
  13. 基本逻辑符号与数学符号列表
  14. 投资理财-赚取平均收益
  15. 基本数据类型一题解析:已知m=11,n=41,输出m和n的2次方、3次方、4次方。(附代码)
  16. 学游戏设计要什么学历_学历低学游戏动作设计好就业吗
  17. 关于web项目播放AMR格式音频的问题
  18. python如何输出结果至剪贴板_将“print”的输出直接复制到剪贴板
  19. java后台图片大小kb查看_java 根据图片地址获取到图片的大小,单位kb或者Mb
  20. Android TextView的属性与应用

热门文章

  1. java entries_Java ZipFile entries()用法及代码示例
  2. c语言中的右移是逻辑右移还是算术右移的问题
  3. 再探Direct3D流水线
  4. 【论文阅读】TimbreTron : A WaveNet (Cycle GAN(CQT(audio ))) pipeline for musical timbre transfer
  5. Github推荐--PC端下载bilibili视频
  6. js 获取图片经纬度及写经纬度
  7. 计算机微软云同步怎样安装软件,在windows10/8/7系统安装和设置OneDrive 同步文件...
  8. 仿今日头条项目——首页(文章搜索)
  9. php生成推广二维码海报、合成图片demo
  10. Centos 7安装tig报错:include/tig/tig.h:83:31: fatal error: ncursesw/curses.h: No such file or directory