如何使普通的C ++编译器打印出某一行所在的名称空间?

时间:2019-05-05 22:16:58

标签: c++ debugging compiler-errors namespaces nvcc

我试图找出一堆代码中缺少命名空间的右括号的地方(即获取:

At end of source: error: expected a "}"

错误)。也许有更聪明的方法可以解决此问题,但是-我想尝试在代码的不同点检查当前名称空间是什么。我不需要宏;而且我不需要字符串;而且我不需要在运行时会存在的东西。我只想让编译器以某种方式打印名称空间。如果它位于#error#warning或某些无法编译而产生名称空间错误的结构中,对我来说很好。

我想概括的例子:

namespace ns1 { }
namespace ns2 {
namespace ns3 {

// MAGIC GOES HERE

}

此源文件在某处缺少}。但是-我忘了关闭ns1吗?也许是ns2?我不记得了-它们离我感兴趣的行很远。所以我想插入一些神奇的东西,这将告诉我我现在所在的名称空间。好吧,对于这个例子,我可以写:

namespace ns1 { }
namespace ns2 {
namespace ns3 {

void ns_detector() { return 0; }

}

并在GCC 6.3中获得错误:

b.cpp: In function ‘void ns2::ns3::ns_detector()’:
b.cpp:5:29: error: return-statement with a value, in function returning 'void' [-fpermissive]
 void ns_detector() { return 0; }
                             ^
b.cpp: At global scope:
b.cpp:7:1: error: expected ‘}’ at end of input
 }
 ^

该错误的第一行告诉我我需要知道的内容:尚未关闭的是ns2。但是-这不是那么可靠。对于我使用nvcc编译的更长,更复杂的代码,使用“ nsdetector”功能只会给我类似的东西:

/path/to/file.cu(135): error: return value type does not match the function type

At end of source: error: expected a "}"

所以,我需要更坚固的东西。

注意:

  • 解决方案需要是固定的一段代码,然后将其粘贴到自己的代码中,在该代码中我要检查名称空间是什么,以及可能使用的其他编译器标志。
  • 该解决方案应适用于尽可能多的地址:gcc,clang,nvcc,msvc,icc。我特别关心nvcc(CUDA编译器)和gcc。
  • 除了在输出中寻找的名称空间和一些“标记文字”之外,我希望尽可能少的“噪音”。
  • 一些相关的问题:How to get string for current namespace in Macro

2 个答案:

答案 0 :(得分:1)

这将取决于编译器及其版本。当前适用于所有gcc,clang,icc和msvc的一种(让我们知道它是否适用于nvcc!)正在访问缺少的数据成员:

struct A { A() { this->a; } };

所有编译器都会报告错误,并带有限定名称,例如:

error: no member named 'a' in 'foo::bar::A'

因此,您可以轻松地对::A'::A"进行grep提取(所有这4个主要的编译器都将名称放在引号之间;否则,只需使用唯一的标识符即可,在其他任何地方都找不到等)。

答案 1 :(得分:1)

对@Acorn好的简单解决方案的一种(可能的)改进,可以多次使用,多次检测在同一文件中的多个位置:

#define CONCATENATE(s1, s2) s1##s2
#define EXPAND_THEN_CONCATENATE(s1, s2) CONCATENATE(s1, s2)
#define UNIQUE_IDENTIFIER(prefix) EXPAND_THEN_CONCATENATE(prefix, __LINE__)

#define DETECT_NAMESPACE \
struct UNIQUE_IDENTIFIER(namespace_detector_on_line_) { \
    void f() { look_at_the_class_name_above = 0; } \
};

现在,您应该可以在许多不同的行上编写DETECT_NAMESPACE了。此外,宏定义可以放在单独的文件中。

对于示例中的代码,这将给出:

b.cpp: In member function ‘void ns2::ns3::namespace_detector_on_line_13::f()’:
b.cpp:5:93: error: ‘look_at_the_class_name_above’ was not declared in this scope
 #define DETECT_NAMESPACE struct UNIQUE_IDENTIFIER(namespace_detector_on_line_) { void f() { look_at_the_class_name_above! = 0; } };
                                                                                             ^
b.cpp:13:1: note: in expansion of macro ‘DETECT_NAMESPACE’
 DETECT_NAMESPACE
 ^~~~~~~~~~~~~~~~
b.cpp: At global scope:
b.cpp:15:1: error: expected ‘}’ at end of input
 }