禁用 g++“注意候选项是..”编译器消息

Posted

技术标签:

【中文标题】禁用 g++“注意候选项是..”编译器消息【英文标题】:Disable g++ "note candidates are.." compiler message 【发布时间】:2012-07-03 14:54:40 【问题描述】:

很多时候,当我编译有错字或其他类型不匹配的东西时,我会收到标准的“错误:'functionname' in ...”错误。这很棒。然后,特别是在函数和运算符重载的情况下,g++ 继续列出了 10 页的候选列表,它们只是可怕的海量模板定义。

错误信息很好,但有什么办法可以禁止它提示其他功能变体?

【问题讨论】:

等等,你想让错误信息有less信息吗? 它建议的函数定义隐藏在 10 层模板后面(尤其是使用 boost),这使得找到编译器实际识别错误行的位置变得更加困难。我希望它告诉我错误在哪里以及出了什么问题,但我真的不需要它来建议如何解决它。 通过 grep 进行管道传输,仅匹配包含 'error:' 的行? FWIW 我的开发环境具有“跳转到错误的行”作为一项功能,作为额外的奖励,它会在屏幕上显示候选列表的顶部。 使用clang。它有更好的错误消息。 @R.MartinhoFernandes 无用的信息可能不如没有信息有用,尤其是当您需要滚动浏览重复的文本页面以试图找出实际错误是什么时。 【参考方案1】:

据我所知,GCC 中没有编译标志可以在函数调用不明确的情况下禁用建议的候选。

您唯一的希望可能是修补 GCC 源代码。

深入研究(版本:4.7.1),我发现gcc/cp/pt.c 中似乎是相关功能:

void
print_candidates(tree fns)

  const char *str = NULL;
  print_candidates_1 (fns, false, &str);
  gcc_assert (str == NULL);

作为一个有根据的猜测,我认为您只需要注释掉函数体。

【讨论】:

+1 表示双 LOL。我首先认为这只是一个开玩笑的答案。然后我意识到使用 gcc 从源代码构建编译器是 common 的,并且有一次我知道这一点!现在唯一让我感到困惑的是明显的现代 C/C++ 函数头。我记得(但我可能错了)它曾经到处都是旧的 K&R C 语法? @Cheersandhth.-Alf 这是我第一次查看 GCC 代码库,对于这种规模的项目来说,它可能太干净了。至于 K&R C 语法,我还小 10 岁,甚至不知道它是什么 :) @Cheersandhth.-Alf 是的!代码发展了很多,自 2010 年 5 月以来甚至允许使用一些 C++ 功能。我同意代码库实际上非常清晰! 是的,我实际上正在考虑打补丁,然后根据我是否想要所有的混乱在打补丁和未打补丁之间切换。 嗯,为什么不在补丁版本中添加您自己的选项呢?不应该那么难,并且您将避免不断切换编译器。【参考方案2】:

-Wfatal-errors 做你想做的事吗?

它会在第一个错误之后停止所有错误,这与简单地抑制候选函数注释不同,但它会显着减少输出:

$ cat a.cc
void f()  
void f(int)  
void f(char)  

int main()

  f((void*)0);

$ g++ a.cc
a.cc: In function ‘int main()’:
a.cc:7: error: call of overloaded ‘f(void*)’ is ambiguous
a.cc:2: note: candidates are: void f(int) <near match>
a.cc:3: note:                 void f(char) <near match>
$ g++ a.cc -Wfatal-errors
a.cc: In function ‘int main()’:
a.cc:7: error: call of overloaded ‘f(void*)’ is ambiguous
compilation terminated due to -Wfatal-errors.

或者,如果您想修补 GCC,这会添加一个 -fno-candidate-functions 开关:

--- gcc/c-family/c.opt.orig 2012-07-11 16:37:29.373417154 +0000
+++ gcc/c-family/c.opt      2012-07-11 17:09:47.340418384 +0000
@@ -752,6 +752,10 @@
 fbuiltin-
 C ObjC C++ ObjC++ Joined

+fcandidate-functions
+C++ ObjC++ Var(flag_candidates) Init(1)
+-fno-candidate-functions Do not print candidate functions when overload resolution fails
+
 fcheck-new
 C++ ObjC++ Var(flag_check_new)
 Check the return value of new
--- gcc/cp/call.c.orig      2012-07-11 17:08:34.186424089 +0000
+++ gcc/cp/call.c   2012-07-11 17:09:51.843444951 +0000
@@ -3317,6 +3317,9 @@
   for (n_candidates = 0, cand1 = candidates; cand1; cand1 = cand1->next)
     n_candidates++;

+  if (!flag_candidates)
+    return;
+
   inform_n (loc, n_candidates, "candidate is:", "candidates are:");
   for (; candidates; candidates = candidates->next)
     print_z_candidate (loc, NULL, candidates);
--- gcc/cp/pt.c.orig        2012-07-11 16:37:35.658636650 +0000
+++ gcc/cp/pt.c     2012-07-11 17:10:20.910435942 +0000
@@ -1751,9 +1751,12 @@
 void
 print_candidates (tree fns)
 
-  const char *str = NULL;
-  print_candidates_1 (fns, false, &str);
-  gcc_assert (str == NULL);
+  if (flag_candidates)
+    
+      const char *str = NULL;
+      print_candidates_1 (fns, false, &str);
+      gcc_assert (str == NULL);
+    
 

 /* Returns the template (one of the functions given by TEMPLATE_ID)

【讨论】:

显然没有回答这个问题,但我猜这对许多人在这个问题中寻找的东西有用【参考方案3】:

我的回答没有补丁那么酷。如果你想要一个不那么冗长的错误信息,这个脚本将删除丑陋的代码,只为候选者留下行号。

g++ test.cc 2>&1 | sed 's/^\([^ ]*:[0-9]*: note\):.*/\1/'

所以,它可以在这样的脚本中使用:

#!/bin/bash
GXX=/usr/bin/g++
ARGS=()
i=0
show_notes=yes
for arg in "$@" ; do
    if [ "$arg" = "-fterse-notes" ] ; then
        show_notes=no
    elif [ "$arg" = "-fno-terse-notes" ] ; then
        show_notes=yes
    else
        ARGS[$i]="$arg"
        i=$[i+1]
    fi
done
if [ $show_notes = yes ] ; then
    exec $GXX "$ARGS[@]"
else
    exec $GXX "$ARGS[@]" 2>&1 | sed 's/^\([^ ]*:[0-9]*: note\):.*/\1/'
fi

如果此脚本的名称是 g++ 并且在您的路径中,它应该像您添加了一个名为 -fterse-notes 的命令行选项一样工作。

【讨论】:

你肯定只想在第一个 'else' 中增加 $i 吗? @cdyson37 已修复,谢谢!

以上是关于禁用 g++“注意候选项是..”编译器消息的主要内容,如果未能解决你的问题,请参考以下文章

禁用所有 gcc 警告

在makefile中创建静态库,使用linux g++编译器

使用 qmake 查找编译器供应商/版本

使用 g++ 编译,使用向量和数组库

Netbeans 中的“make [2]:g++:找不到命令”

针对特定版本的 armhf g++ 进行编译