标签: compiler-bug

c ++数组零初始化:这是一个错误,还是这个正确?

注意:我们在这里谈论(据称)符合C++ 98的编译器.这不是C++ 11的问题.

我们在其中一个编译器中有一个奇怪的行为,我们不确定这是否正常或者这是否是编译器错误:

// This struct has a default constructor
struct AAA
{
   AAA() : value(0) {}
   int value ;
} ;

// This struct has a member of type AAA and an array of int, both surrounded
// by ints
struct BBB
{
   int m_a ;
   AAA m_b ;
   int m_c ;
   int m_d[42] ;
} ;
Run Code Online (Sandbox Code Playgroud)

当BBB初始化时:

BBB bbb = {0} ;
Run Code Online (Sandbox Code Playgroud)

我们期望BBB的所有POD成员(包括m_d,整数数组)被零初始化,并且要构建BBB的所有非POD成员.

这适用于AIX的本机编译器,在Linux/GCC-3.4上,在Windows/VisualC++上......但不适用于Solaris/SunStudio,其中只有非数组成员被零初始化.

我们在C++ 98标准(草案文档)中进行了一些研究,在那里我们发现了以下内容:

[12.6.1 - 2]

当聚合(无论是类还是数组)包含类类型的成员并由大括号括起的初始化列表(8.5.1)初始化时,每个这样的成员都由相应的赋值表达式进行复制初始化(见8.5).如果初始化列表中的初始值设定项少于聚合的成员,则未明确初始化的每个成员都应默认初始化(8.5).

然后:

[8.5 - 5]

对 …

c++ standards-compliance compiler-bug c++98

14
推荐指数
1
解决办法
992
查看次数

为什么variadic函数不能"吃掉"C++ 11中的list-initialization参数?

示例代码是:

#include <unordered_map>

int main() {
    std::unordered_map<int, std::pair<int, int>> map;

    map.emplace(1, {1, 1});

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

哪里emplace()有签名,如:

template <class... _Args>
pair<iterator, bool> emplace(_Args&&... __args);
Run Code Online (Sandbox Code Playgroud)

gcc说的功能expectes 0参数- 2提供的.该clang说,函数需要1个参数- 2提供的.

我甚至不明白 - 这段代码有什么问题?

c++ variadic-functions compiler-bug c++11 list-initialization

14
推荐指数
2
解决办法
506
查看次数

支撑初始化列表中是否允许使用显式转换运算符?

以下代码使用GCC 4.9.2编译,但不与Clang 3.5.0编译:

#include <string>

class Foo
{
public:
  explicit operator std::string() const;
};

std::string bar{Foo{}}; // Works in g++, fails in clang++
std::string baz(Foo{}); // Works in both
Run Code Online (Sandbox Code Playgroud)

clang ++说:

foo.cpp:9:13: error: no matching constructor for initialization of 'std::string'
      (aka 'basic_string<char>')
std::string bar{Foo{}};
            ^  ~~~~~~~
...: note: candidate constructor not viable: no known conversion from 'Foo' to
      'const std::basic_string<char> &' for 1st argument
      basic_string(const basic_string& __str);
      ^
Run Code Online (Sandbox Code Playgroud)

奇怪的是,如果std::string被替换为原始类型,它就可以工作int.

c++ gcc clang compiler-bug c++11

14
推荐指数
1
解决办法
475
查看次数

带有gcc 7.3的__atomic_fetch_or的意外x64程序集

我试图使用64位积分作为位图,并原子地获取/释放各个位的所有权.

为此,我编写了以下无锁代码:

#include <cstdint>
#include <atomic>

static constexpr std::uint64_t NO_INDEX = ~std::uint64_t(0);

class AtomicBitMap {
public:
    static constexpr std::uint64_t occupied() noexcept {
        return ~std::uint64_t(0);
    }

    std::uint64_t acquire() noexcept {
        while (true) {
            auto map = mData.load(std::memory_order_relaxed);
            if (map == occupied()) {
                return NO_INDEX;
            }

            std::uint64_t index = __builtin_ctzl(~map);
            auto previous =
                mData.fetch_or(bit(index), std::memory_order_relaxed);
            if ((previous & bit(index)) == 0) {
                return index;
            }
        }
    }

private:
    static constexpr std::uint64_t bit(std::uint64_t index) noexcept {
        return std::uint64_t(1) << index;
    }

    std::atomic_uint64_t mData{ …
Run Code Online (Sandbox Code Playgroud)

c++ assembly gcc x86-64 compiler-bug

14
推荐指数
1
解决办法
457
查看次数

按元素地址排序

我偶然发现了一种情况,库std::vector<T>使用用户提供的比较对象对容器(例如)进行排序。对于一种特定情况,用户实际上不想对容器进行排序,但排序是无条件发生的。

因此,为了尽量避免这种情况,我想尝试使用根据元素地址排序的比较对象。等价地,我们有:

std::vector nums{1, 5, 4};
auto cmp = [](auto& a, auto& b) { return &a < &b; };
std::sort(nums.begin(), nums.end(), cmp);
Run Code Online (Sandbox Code Playgroud)

这是“有效的”,因为std::vector<T>元素以与向量中元素相同的顺序存储在(连续)内存位置中。最终结果是,nums即使在排序之后,向量似乎也没有被改变。

但是,一旦我替换std::vector<T>std::array<T, N>,我就会遇到分段冲突(请参阅https://gcc.godbolt.org/z/9srehdbhG)。

我的第一个想法是我违反了https://en.cppreference.com/w/cpp/algorithm/sort中列出的类型要求:

  • RandomIt必须满足ValueSwappableLegacyRandomAccessIterator的要求。
  • 解除引用的类型必须满足MoveAssignableMoveConstructibleRandomIt的要求。
  • Compare必须满足Compare的要求。

我的假设是元素的地址在整个排序过程中保持稳定 - 这几乎肯定是错误的。

那么,std::sort()我违反了哪些要求/先决条件?

c++ language-lawyer compiler-bug

14
推荐指数
1
解决办法
518
查看次数

成员函数重载决议涉及"使用"别名的英特尔C++编译器错误?

#include <cstddef>

template<typename T, T... Is>
struct Bar { };

template<size_t... Is>
using Baz = Bar<size_t, Is...>;

struct Foo {
  template<size_t... Is>
  void NoAlias(Bar<size_t, Is...>) { }

  template<size_t... Is>
  void Alias(Baz<Is...>) { }
};

template<typename T, T... Is>
void foo(Bar<T, Is...>) { }

template<size_t... Is>
void bar(Bar<size_t, Is...>) { }

int main() {
  // All these work fine
  foo(Bar<size_t, 4, 2>());
  foo(Baz<4, 2>());
  bar(Bar<size_t, 4, 2>());
  bar(Baz<4, 2>());
  Foo().NoAlias(Bar<size_t, 4, 2>());
  Foo().NoAlias(Baz<4, 2>());

  // But these two give error on …
Run Code Online (Sandbox Code Playgroud)

c++ icc compiler-bug c++11

13
推荐指数
1
解决办法
436
查看次数

模板类中结构的 C++ 编译器问题

以下代码不能用 gcc 或 clang 编译。

template<class T>
class foo{};

template<class T>
class template_class_with_struct
{
    void my_method() {
        if(this->b.foo < 1);
    };

    struct bar
    {
        long foo;
    } b;
};
Run Code Online (Sandbox Code Playgroud)

错误信息是

error: type/value mismatch at argument 1 in template parameter list for 'template<class T> class foo'    
    8 |         if(this->b.foo < 1);
Run Code Online (Sandbox Code Playgroud)

该错误是由模板类 foo 引起的。当编写 <= 而不是 < 1 时,它也会编译。

任何提示赞赏?

CompilerExplorer 链接https://godbolt.org/z/v6Tygo

c++ templates compiler-errors compiler-bug

13
推荐指数
1
解决办法
171
查看次数

thread_local + std::thread 销毁时死锁

有谁知道这是什么类型的UB吗?使用 MSVC 19.29.30148 构建时,以下代码在jthread销毁时死锁,有时在 std::cout 之后死锁,有时在之前死锁。这在某种程度上与 thread_local 有关,但我看不出问题是什么。它似乎在其他编译器和平台下工作得很好。

#include <thread>
#include <memory>
#include <iostream>

int main(void)
{
    std::thread t2(
        [&] {
            thread_local std::jthread asd([] {
                    std::cout << "ASD" << std::endl;
                    });
        });
    if (t2.joinable()) { t2.join(); }
}
Run Code Online (Sandbox Code Playgroud)

更新:在静态和动态运行时均可重现

c++ multithreading msvcrt compiler-bug c++20

13
推荐指数
0
解决办法
362
查看次数

Clang和二进制折叠表达式 - 空参数包的诅咒

特别是Clang 3.6.0,目前由Coliru主持.

所有这些片段都来自:

int main() {
    foo();
    std::cout << "\n----\n";
    foo(1, 2, 3);
}
Run Code Online (Sandbox Code Playgroud)

以下代码:

template <class... Args>
void foo(Args... args) {
    std::cout << ... << args;
}
Run Code Online (Sandbox Code Playgroud)

触发以下编译错误:

main.cpp:7:17: error: expected ';' after expression
    std::cout << ... << args;
                ^
                ;
main.cpp:7:15: error: expected expression
    std::cout << ... << args;
              ^
Run Code Online (Sandbox Code Playgroud)

所以我试着在表达式周围添加括号:

(std::cout << ... << args);
Run Code Online (Sandbox Code Playgroud)

它有效,但会触发警告:

main.cpp:7:6: warning: expression result unused [-Wunused-value]
    (std::cout << ... << args);
     ^~~~~~~~~
main.cpp:11:5: note: in instantiation of function template specialization 'foo<>' …
Run Code Online (Sandbox Code Playgroud)

c++ clang compiler-bug fold-expression c++17

12
推荐指数
1
解决办法
971
查看次数

[[maybe_unused]] 在成员变量上,GCC 警告(错误地?)该属性被忽略

在以下示例中

struct Foo {
    [[maybe_unused]] int member = 1;
    void bar() {
        [[maybe_unused]] int local = 0;
    }
};

int main(int argc, char* argv[]) {
    Foo f{};
    f.bar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

GCC 发出警告,其中 Clang 和 MSVC 没有:

warning: 'maybe_unused' attribute ignored [-Wattributes]
     [[maybe_unused]] int member = 1;
Run Code Online (Sandbox Code Playgroud)

据我所知,这应该是合法的(并且不会被编译器忽略)。根据标准

10.6.7 可能未使用的属性 [dcl.attr.unused]
...
2. 该属性可以应用于类的声明、typedef-name、变量、非静态数据成员、函数、枚举,或枚举器。
...

我讨厌在“编译器错误”锤子上摇摆不定,但我不确定在这种情况下还有什么可能。

有没有人有任何见解?

c++ compiler-warnings compiler-bug c++17

12
推荐指数
2
解决办法
3223
查看次数