标签: clang++

在C++中过度"交叉变量初始化"错误?

我注意到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++ …

c++ g++ clang++

8
推荐指数
2
解决办法
5509
查看次数

Clang -Wweak-vtables和纯抽象类

关于此主题的先前问题:

这是我最近提出的问题的后续跟进: 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中触发警告的纯抽象类有什么特别之处?

c++ abstract-class clang llvm-clang clang++

8
推荐指数
1
解决办法
3103
查看次数

这是未定义的行为还是误报警告?

请考虑以下代码:

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)

c++ constructor undefined-behavior clang++

8
推荐指数
2
解决办法
321
查看次数

连接一元参数的模板参数包

虽然,例如,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)

c++ templates g++ c++11 clang++

8
推荐指数
1
解决办法
249
查看次数

如何忽略作为clang C++模块一部分的头文件中的警告?

我们正在使用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]模块属性将禁止所有警告.然而,这甚至会抑制我们在构建库本身时想要看到的警告,并且我们不希望制作所有模块系统模块.如果我们在构建库本身时找到了不使用库模块映射的方法,这可能是可以接受的,但我们仍然希望对非系统模块进行某些警告.

c++ clang llvm-clang clang++

8
推荐指数
0
解决办法
977
查看次数

强制允许取消引用NULL指针

我有一个非常古老的(和巨大的)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++ null-pointer undefined-behavior dereference clang++

8
推荐指数
1
解决办法
782
查看次数

更简单的c ++模板编译错误输出

在C++中使用模板时,任何错误都会导致编译器发出大量输出.在大多数情况下,当我处理某些信息时,大部分信息都是噪音,我必须滚动查找我感兴趣的信息,例如:

  • 列出每个候选模板.我很少使用这个长列表,它只会使输出混乱.
  • 扩展了模板特化的别名,例如std::string,写为std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >或扩展的typedef/alias声明.我更希望将它们展开以便于阅读.

是否有可能在g ++或clang中减少任何这种更短/更简单的输出?

显然,信息可能很重要,但是我宁愿再次编译更详细,默认情况下保持简短.

c++ compiler-errors g++ clang++

8
推荐指数
1
解决办法
118
查看次数

在编译时打印类型的名称而不中止编译?

在这个问题中:

在编译时打印模板类型名

我们有一些关于如何让典型的 C++ 编译器在编译时打印类型名称的建议。但是,它们依赖于触发编译错误。

我的问题:我可以让 C++ 编译器在停止编译的情况下打印类型的名称吗?

一般来说,答案是“可能不是”,因为一个有效的程序可以编译成它的目标对象,而无需在任何地方打印任何内容,所以我特别询问 GCC 和 clang,可能使用预处理器指令、编译器内置程序或任何编译器- 特定的技巧。

笔记:

  • 显然,挑战在于在using/typedef语句、模板参数值、可变参数模板等后面打印类型。如果类型明确可用,您可以使用类似的东西#message "my type is unsigned long long"(如@NutCracker 建议的那样)。但这不是问题的内容。
  • 依赖于 C++11 或更早版本的答案优先于需要 C++14/17/20。

c++ g++ compile-time debug-print clang++

8
推荐指数
1
解决办法
165
查看次数

clang 认为我需要指向“const 函数”吗?

GodBolt

考虑以下代码片段:

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++

8
推荐指数
1
解决办法
128
查看次数

未捕获 constexpr 变量

以下代码不能在 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++ lambda constexpr clang++ c++17

8
推荐指数
1
解决办法
101
查看次数