我注意到g++有点过于严格的抱怨crossed initialization,我想知道为什么这些误报错误只能通过在编译时查看程序的SSA形式来消除.
让我举一个非常简单的例子:
#include <cstdlib>
int main ()
{
goto end;
int i = 0; // unused variable declaration
end:
return EXIT_SUCCESS;
}
Run Code Online (Sandbox Code Playgroud)
使用g++ -Wall -Wextra -o example1 example1.cc(g++4.8.1)编译时,编译器会给出以下错误消息:
example1.cc: In function ‘int main()’:
example1.cc:10:2: error: jump to label ‘end’ [-fpermissive]
end:
^
example1.cc:6:8: error: from here [-fpermissive]
goto end;
^
example1.cc:8:7: error: crosses initialization of ‘int i’
int i = 0;
^
example1.cc:8:7: warning: unused variable ‘i’ [-Wunused-variable]
Run Code Online (Sandbox Code Playgroud)
因此,它会引发一个实际没有风险的错误,因为该变量未被使用(编译器显然同时具有这两个信息,并且不能将它组合起来推断错误是误报).
更奇怪的是,我希望LLVM在分析程序方面更有效率.所以,我尝试clang++ …
关于此主题的先前问题:
这是我最近提出的问题的后续跟进: clang:没有外线虚拟方法定义(纯抽象C++类) ,并且被标记为此问题的副本:clang的-Wweak-含义是什么?虚函数表?.我不认为那回答了我的问题,所以在这里我专注于困扰我的事情,但尚未得到回答.
我的情景:
我正在尝试使用Clang-3.5编译以下简单的C++代码:
test.h:
class A
{
public:
A();
virtual ~A() = 0;
};
Run Code Online (Sandbox Code Playgroud)
test.cc
#include "test.h"
A::A() {;}
A::~A() {;}
Run Code Online (Sandbox Code Playgroud)
我用来编译它的命令(Linux,uname -r:3.16.0-4-amd64):
$clang-3.5 -Wweak-vtables -std=c++11 -c test.cc
Run Code Online (Sandbox Code Playgroud)
而我得到的错误:
./test.h:1:7: warning: 'A' has no out-of-line virtual method definitions; its vtable will be emitted in every translation unit [-Wweak-vtables]
Run Code Online (Sandbox Code Playgroud)
当A类不是纯抽象时,上面的代码构建得很好.以下代码不会发出警告,唯一的变化是A类不再是抽象的:
test2.h:
class A
{
public:
A();
virtual ~A();
};
Run Code Online (Sandbox Code Playgroud)
test2.cc
#include "test2.h"
A::A() {;}
A::~A() {;}
Run Code Online (Sandbox Code Playgroud)
我的问题
上面的代码在Clang中触发警告的纯抽象类有什么特别之处?
请考虑以下代码:
class A {
private:
int a;
public:
A(int a) : a(a) { }
};
class B : public A {
private:
int b;
bool init() {
b = 0;
return true;
}
public:
// init() is a hack to initialize b before A()
// B() : b(0), A(b) {} yields -Wreorder
// B() : A((b = 0)) {} no warning (but this one doesn't work so well with non-pod (pointer) types)
B() : A(init() ? b : 0) {} …Run Code Online (Sandbox Code Playgroud) 虽然,例如,std::add_pointer是一元,但GCC 7.0.0(20160608)和Clang 3.9.0都接受以下代码:
template <typename ...Ts>
struct tc1 {
using a = std::add_pointer<Ts...>;
};
Run Code Online (Sandbox Code Playgroud)
但是,虽然以下代码被Clang接受,但GCC拒绝了:
template <typename ...Ts>
struct tc2 {
template <typename ...Us>
using b = std::add_pointer<Ts...,Us...>;
};
Run Code Online (Sandbox Code Playgroud)
这是有效的C++吗?从语法上讲,我可以想象当包装是空的时候逗号是一个问题,但可能在其他场合被删除了; 例如,std::common_type接受零个或多个参数,以下任何一个编译器都没有问题:
template <typename ...Ts>
struct tc3 {
template <typename ...Us>
using c = std::common_type<Ts...,Us...>;
};
Run Code Online (Sandbox Code Playgroud) 我们正在使用clang -fmodule和-fcxx-module启用模块支持,如http://clang.llvm.org/docs/Modules.html中所述.通过为我们的核心库定义模块映射,我们已经看到了构建时间的显着改进.
但是,我们有一些库头文件使用编译指示来禁用某些行的警告,例如:
template <typename TFloat>
static bool exactlyEqual(TFloat lhs, TFloat rhs)
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
return lhs == rhs;
#pragma clang diagnostic pop
}
Run Code Online (Sandbox Code Playgroud)
当这头拉在为预编译的模块,它似乎铿锵的内部表示不保留编译信息和警告仍然发出.由于我们将警告视为错误,因此导致编译失败.有些人可能会争辩说float-equal完全禁用,但我们还有其他一些具有不同警告的情况,我们不希望全局禁用.
我们已经在使用-Wno-system-headers,-isystem所以图书馆的客户端通常不会看到这样的警告(即使没有编译指示),但是当标头作为模块导入时,这似乎不起作用.此外,我们仍然会对库内部的代码发出这些警告,其中包含标头作为非系统标头(即不使用-isystem/使用双引号),因为模块预编译和导入也发生在这里.
我尝试使用_Pragma(...)而不是#pragma没有任何影响.
是否有其他方法有条件地忽略来自预编译的clang模块的标题中的警告?
更新:我已经把一个样本项目多达上https://github.com/MikeWeller/ClangModuleWarnings其重现问题
更新:似乎[system]模块属性将禁止所有警告.然而,这甚至会抑制我们在构建库本身时想要看到的警告,并且我们不希望制作所有模块系统模块.如果我们在构建库本身时找到了不使用库模块映射的方法,这可能是可以接受的,但我们仍然希望对非系统模块进行某些警告.
我有一个非常古老的(和巨大的)Win32项目,该项目使用NULL指针进行大量检查,通过强制转换为指向解除引用的指针.像这样:
int* x = NULL; //somewhere
//... code
if (NULL == &(*(int*)x) //somewhere else
return;
Run Code Online (Sandbox Code Playgroud)
是的,我知道这段代码很愚蠢,需要重构.但由于代码量很大,这是不可能的.现在我需要在Xcode的MacOS Sierra下编译这个项目,这会导致很大的问题......事实证明,在发布模式下(使用代码优化),条件以不正确的行为执行(因为解除引用NULL而被称为未定义的行为指针).
根据GCC的这个文档,有一个选项-fno-delete-null-pointer-checks,但是当启用O1,O2或O3优化时,它似乎不适用于LLVM.所以问题是:如何强制LLVM 8.0编译器允许这样的解引用?
UPDATE.检查问题的真实工作示例.
//somewhere 1
class carr
{
public:
carr(int length)
{
xarr = new void*[length];
for (int i = 0; i < length; i++)
xarr[i] = NULL;
}
//some other fields and methods
void** xarr;
int& operator[](int i)
{
return *(int*)xarr[i];
}
};
//somewhere 2
carr m(5);
bool something(int i)
{
int* el = &m[i]; …Run Code Online (Sandbox Code Playgroud) 在C++中使用模板时,任何错误都会导致编译器发出大量输出.在大多数情况下,当我处理某些信息时,大部分信息都是噪音,我必须滚动查找我感兴趣的信息,例如:
std::string,写为std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >或扩展的typedef/alias声明.我更希望将它们展开以便于阅读.是否有可能在g ++或clang中减少任何这种更短/更简单的输出?
显然,信息可能很重要,但是我宁愿再次编译更详细,默认情况下保持简短.
在这个问题中:
我们有一些关于如何让典型的 C++ 编译器在编译时打印类型名称的建议。但是,它们依赖于触发编译错误。
我的问题:我可以让 C++ 编译器在不停止编译的情况下打印类型的名称吗?
一般来说,答案是“可能不是”,因为一个有效的程序可以编译成它的目标对象,而无需在任何地方打印任何内容,所以我特别询问 GCC 和 clang,可能使用预处理器指令、编译器内置程序或任何编译器- 特定的技巧。
笔记:
using/typedef语句、模板参数值、可变参数模板等后面打印类型。如果类型明确可用,您可以使用类似的东西#message "my type is unsigned long long"(如@NutCracker 建议的那样)。但这不是问题的内容。考虑以下代码片段:
using A = void(*)(int);
A foo(const void* ptr)
{
return reinterpret_cast<A>(ptr);
}
Run Code Online (Sandbox Code Playgroud)
GCC 10 喜欢这个就好了。但是,clang++-10 说这是一个错误!
<source>:5:12: error: reinterpret_cast from 'const void *' to 'A' (aka 'void
(*)(int)') casts away qualifiers
return reinterpret_cast<A>(ptr);
^~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
函数在 C++(和 C)中是不可变的,并且没有“const 函数”。那么为什么 clang++ 在这里抱怨呢?
c++ function-pointers const-correctness reinterpret-cast clang++
以下代码不能在 clang 中编译(在 GCC 中可以):
struct A{
int a;
};
auto test(){
constexpr A x{10};
return []{
return x; // <-- here x is A: clang doesn't compile
}();
}
Run Code Online (Sandbox Code Playgroud)
Clang 的错误是变量 'x' 不能在没有指定捕获默认值的 lambda 中隐式捕获,但我认为 constexpr 变量总是被捕获。
如果 x 是 int,则代码编译:
auto test(){
constexpr int x{10};
return []{
return x; // <-- here x is int: clang is ok
}();
}
Run Code Online (Sandbox Code Playgroud)
有趣的是,以下代码也可以编译:
auto test(){
constexpr A x{10};
return []{
return x.a;
}();
}
Run Code Online (Sandbox Code Playgroud)
叮当正确吗?如果是这样,理由是什么?我正在使用 -std=c++17
- 编辑 …
c++ ×10
clang++ ×10
g++ ×4
clang ×2
llvm-clang ×2
c++11 ×1
c++17 ×1
compile-time ×1
constexpr ×1
constructor ×1
debug-print ×1
dereference ×1
lambda ×1
null-pointer ×1
templates ×1