如何开启ICC/ICPC警告?

11

我在Linux上安装了英特尔编译器composer_xe_2013_sp1.3.174。我对icc警告感到困惑。将简单的程序main.c输入给icc,如下所示:

int main(int argc, char **argv) {
  int a = 1;
  unsigned int b = -22;
  if (b = a) {

  }
}

我使用命令icc -Wall main.c编译了文件。令人惊讶的是,这个命令在没有任何警告的情况下静默运行。我是否需要在icc上打开警告开关?谢谢。


7
@BLUEPIXY 在发帖之前应该先阅读问题内容... - code monkey
但是作为一个表达式的正确性。 - BLUEPIXY
2
@BLUEPIXY 我写这个是为了测试警告。 - Conghui He
1
当您添加-Wcheck时,是否会看到有关if语句中b=a赋值的发出警告? - Shmil The Cat
警告似乎并不必要。gcc和clang很友好,但我觉得有些多余了。例如_warning: suggest parentheses around assignment used as truth value_ 括号完全不必要。 - BLUEPIXY
显示剩余3条评论
3个回答

13

与Linux上的gcc不同,英特尔编译器没有很好的警告预设。主要的警告选项是-wn,其中n可以是0到5的数字。默认值为1,而4和5在Linux上没有意义。它还支持一些类似于-Wall-Wextra的gcc选项。然而:

  • -Wall与gcc相比非常简约,正如您所发现的
  • -w2-w3启用了一些有用的诊断信息,但也会产生大量垃圾邮件
  • -diag-disable:remark可以去除那些垃圾邮件,但也会去除许多有用的诊断信息

最终,-w3 -diag-disable:remark是英特尔编译器拥有的最佳预设,但它仍然比gcc -Wall更加简约。您需要从一个最小化的警告集开始并建立自己的警告集,或者从最大化的诊断开始,并使用-wd禁用任何让您感到烦恼的警告。

建立

第一种方法的主要缺点是,英特尔实际上没有记录大多数警告信息,因此很难知道可以启用哪些警告。但是,它支持许多GCC命令行标志,因此GCC文档是一个好的起点。例如,以下设置与g++ -Wall相当接近,这对于您想要在其中一个上开发并有机会使用另一个进行干净的构建非常方便:

icpc -Wall -Warray-bounds -Wchar-subscripts -Wcomment -Wenum-compare -Wformat -Wuninitialized -Wmaybe-uninitialized -Wmain -Wnarrowing -Wnonnull -Wparentheses -Wpointer-sign -Wreorder -Wreturn-type -Wsign-compare -Wsequence-point -Wtrigraphs -Wunused-function -Wunused-but-set-variable -Wunused-variable -Wwrite-strings

这不是与gcc -Wall完全匹配的内容。GCC和ICC在上述警告的实现上有所不同。我还无法找到与这些GCC警告相匹配的ICC选项:

-Wformat-contains-nul
-Wunused-label
-Wstrict-overflow
-Wvolatile-register-var

我故意将它们省略掉,因为ICC版本比GCC更加垃圾邮件式的。

-Wstrict-aliasing   So broad that any use of polymophism will cause this warning
-Wswitch            Requires a default even if you have cases for all enumeration values

简化

如果不考虑GCC的兼容性问题,学习ICC的警告最简单的方法就是启用所有警告,然后决定是否喜欢这些警告。如果不喜欢某个警告,可以使用其诊断号将其禁用,这通常比GCC的选项更具有细粒度。

icpc -w3 -wd1418,2259

以下是一些我曾经看到被禁用的诊断信息:

  • 383:值被复制到临时变量中,对临时变量进行了引用
  • 869:参数“*”从未被引用过
  • 981:操作数的计算顺序未指定
  • 1418:外部函数定义没有先前声明
  • 1572:浮点数等式和不等式比较不可靠
  • 2259:非指针转换可能丢失有效位
  • 11074:内联限制被最大尺寸(或最大总大小)所阻止
  • 11076:要获得完整报告,请使用-qopt-report=4 -qopt-report-phase ipo
  • 161:为无法识别的编译指令禁用警告

但我建议您将所有诊断都打开,然后逐渐删除对您的代码库有问题的那些。


仅仅为了明确,它甚至没有实现GCC所有警告,即使是对于它声称支持的GCC版本。例如,自4.0以来,GCC已经支持-Wvariadic-macros,但是如果您编写#pragma GCC diagnostic ignored "-Wvariadic-macros"(即使在#if __GNUC__ >= 4内部),ICC将在-w3处发出诊断(#2282:未识别的GCC指示)。 - nemequ

1
一般来说,对于你正在开发的小程序,最好的编译选项是-Wall -Wextra -std=c11 -pedantic。
与警告开关名称相反,Wall实际上并没有激活所有警告;你需要同时使用Wall和Wextra以获得大部分重要的警告。
-std开关设置代码使用的标准;最新的标准是C11,因此是std=c11。Pedantic是向编译器发出的信号,表示你想编写一个不使用编译器特定扩展的程序。Pedantic需要std开关,并将为任何不符合std指定的标准的语法等发出警告。最后,如果你想要错误而不是警告来指示编译器扩展的使用,请使用-pedantic-errors。
(* - pedantic不会警告使用类似conio.h的非标准库)
现在,如果你使用Wall Wextra std=c11 pedantic编译程序,你应该会收到1个警告:
警告:第4行-建议在truthy值周围加括号(10次中有9次,这意味着你在比较上下文中使用了=而不是==)。
如果你修复了那个警告,你将收到另一个警告:
警告:第4行-签名整数和无符号整数之间的比较没有转换。
将b转换为普通整数或添加显式的强制类型转换可以解决此警告。

你使用的是哪个版本的icc?我测试过的所有版本都没有在选项中列出-Wextra或-pedantic,并且似乎无论是否使用这些标志,都会生成相同的警告。 - pavon
3
此答案适用于gcc,而不适用于icc。 - Susam Pal
@pavon:-Wall -Wextra 早在 ICC13 上就可以使用了。Godbolt 没有更早的版本。所以 -pedantic 也是一样的。例如,-Wextra 可以启用未初始化对象的额外警告。C 中的返回语句不会被执行。Google 没有找到 ICC 警告选项的官方文档,但如果 ICC 支持 gcc 选项以实现兼容性,即使没有文档,这也不足为奇。 - Peter Cordes

0

最近我在使用CMake中的target_optionsicpc 2021.6.0 20220226,感觉非常满意。这些选项是我从多个来源收集而来的。欢迎提供更多的补充。

        target_compile_options(
            ${TEST_EXE}
            PRIVATE
                $<$<COMPILE_LANG_AND_ID:CUDA,NVIDIA>:
                    ...
                >
                $<$<AND:$<CXX_COMPILER_ID:GNU>,$<NOT:$<CUDA_COMPILER_ID:NVIDIA>>,$<NOT:$<CUDA_COMPILER_ID:Clang>>>:
                    ...
                >
                $<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CUDA_COMPILER_ID:Clang>>:
                    ...
                >
                $<$<CXX_COMPILER_ID:Intel>:  # also IntelLLVM, XL (ibm), XLClang (ibm)
                    -Werror
                    -Wall
                    -Wextra
                    -diag-disable=remark
                    -diag-error:3846
                    -diag-disable=1011  # disables warning missing return at the end of non-void function
                    -wd161
                    -Wabi
                    -Warray-bounds
                    -Wcast-qual
                    -Wchar-subscripts
                    -Wcomment
                    -Wdeprecated
                    -Wenum-compare
                    -Wextra-tokens
                    -Wformat
                    -Wformat=2
                    -Wformat-security
                    -Wic-pointer
                    -Wnarrowing
                    -Wno-return-type
                    -Wnon-virtual-dtor
                    -Wnonnull
                    -Wmaybe-uninitialized
                    -Wmain
                    -Wmissing-declarations
                    -Wmissing-prototypes
                    -Wmultichar
                    -Woverloaded-virtual
                    -Woverflow
                    -Wparentheses
                    -Wpointer-arith
                    -Wpointer-sign
                    -Wreorder
                    -Wreturn-type
                    -Wsequence-point
                    -Wshadow
                    -Wsign-compare
                    -Wshorten-64-to-32
                    -Wno-strict-aliasing
                    -Wstrict-prototypes
                    -Wtrigraphs
                    -Wtype-limits
                    -Wuninitialized
                    -Wunused
                    -Wunused-but-set-variable
                    -Wunused-function
                    -Wunused-parameter
                    -Wunused-variable
                    -Wwrite-strings
                >
                $<$<OR:$<CXX_COMPILER_ID:PGI>,$<CXX_COMPILER_ID:NVHPC>>:
                ...
                >
                $<$<CXX_COMPILER_ID:MSVC>:
                ...
                >
        )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接