Clang 8发行说明中有以下内容:
- 允许在MinGW上使用Address Sanitizer和Undefined Behavior Sanitizer。
但是,我无法弄清楚如何正确使用它们。
我将Clang 8.0.0与MSYS2 MinGW GCC结合使用。确切的细节在问题的底部。
我正在尝试编译以下最少的代码:
1.cpp
#include <iostream>
int main()
{
// Testing ubsan
int x = 0x7fffffff;
x++;
std::cout << x << std::endl;
// Testing asan
int *y = new int;
delete y;
std::cout << *y << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
以下是结果-fsanitize=address:
# /z/Lander/LLVM/bin/clang++ -target x86_64-w64-windows-gnu -fsanitize=address 1.cpp
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic-x86_64.dll.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No such file or directory
Z:\Lander\msys2\mingw64\bin\ld.exe: cannot find Z:\Lander\LLVM\lib\clang\8.0.0\lib\windows\libclang_rt.asan_dynamic_runtime_thunk-x86_64.a: No …Run Code Online (Sandbox Code Playgroud) 在 c++20 中玩弄文字、非类型模板参数,我发现 g++ 和 clang++ 不同意以下代码。
#include <algorithm>
template<size_t N>
struct StringLiteral {
constexpr StringLiteral(const char (&str)[N]) {
std::copy_n(str, N, value);
}
char value[N];
};
template <typename T, StringLiteral Name>
struct named{};
template <typename T>
struct is_named: std::false_type{};
template <typename T, size_t N, StringLiteral<N> Name>
struct is_named<named<T, Name>>: std::true_type{};
// This will fail with g++
static_assert(is_named<named<int, "ciao">>::value == true);
Run Code Online (Sandbox Code Playgroud)
在 Godbolt 上实时查看:https ://godbolt.org/z/f3afjd
首先也是最重要的,我什至不确定我是否以正确的方式做这件事:它是与泛型StringLiteral<N>类型匹配的方式,还是不是?如果不是,正确的方法是什么?
而且,为什么编译器不同意呢?谁有错误?
编辑:发现删除size_t N部分特化中的参数使两个编译器都同意,结果是预期的。像这样:
template <typename T, StringLiteral …Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
template <typename T> struct X
{
X(T) {}
void foo() {}
};
template <typename T> struct Y
{
int object = 0;
void bar()
{
X(object).foo();
}
};
Run Code Online (Sandbox Code Playgroud)
GCC 8.2编译它,而Clang 7吐出以下错误:
Run Code Online (Sandbox Code Playgroud)<source>:13:18: error: member reference base type 'X' is not a structure or union X(object).foo(); ~~~~~~~~~^~~~
对我来说这看起来像个错误.
条件非常具体:如果任一结构不是模板,或者object不是成员变量,或者不涉及CTAD(类模板参数推导),那么Clang也会编译代码.
这里发生了什么?它确实是一个Clang bug吗?
更重要的是,如何在没有摆脱CTAD的情况下以最小的变化编译代码?
唯一使用的标志是-std=c++17.
clang++ --version 是
Run Code Online (Sandbox Code Playgroud)clang version 7.0.0 (tags/RELEASE_700/final 342594) Target: x86_64-unknown-linux-gnu Thread model: posix
考虑以下代码:
#include <iostream>
#include <type_traits>
template <class T>
constexpr std::size_t type_hash(T) noexcept
{
// Compute a hash for the type
// DO SOMETHING SMART HERE
}
int main(int argc, char* argv[])
{
auto x = []{};
auto y = []{};
auto z = x;
std::cout << std::is_same_v<decltype(x), decltype(y)> << std::endl; // 0
std::cout << std::is_same_v<decltype(x), decltype(z)> << std::endl; // 1
constexpr std::size_t xhash = type_hash(x);
constexpr std::size_t yhash = type_hash(y);
constexpr std::size_t zhash = type_hash(z);
std::cout << (xhash == yhash) …Run Code Online (Sandbox Code Playgroud) 假设我有一个模板函数:
template <typename A, typename B>
A fancy_cast(B)
{
return {};
}
Run Code Online (Sandbox Code Playgroud)
预期的用法类似于fancy_cast<int>(1.f)。
但是,没有什么可以阻止用户手动指定第二个模板参数:fancy_cast<int, int>(1.f),这会引起问题。
如何防止typename B被指定并强制推断?
我想出了这个:
// Using this wrapper prevents the code from being
// ill-formed NDR due to [temp.res]/8.3
template <auto V> inline constexpr auto constant_value = V;
template <
typename A,
typename ...Dummy,
typename B,
typename = std::enable_if_t<constant_value<sizeof...(Dummy)> == 0>
>
A fancy_cast(B)
{
return {};
}
Run Code Online (Sandbox Code Playgroud)
它似乎可以工作,但是非常麻烦。有没有更好的办法?
这可能是不可能的,但我还是想问。我使用 Clangd 作为 VSCode 的自动完成引擎。它工作得很好,但有一个问题。
Clang 的官方 Windows 二进制文件依赖于 MSVC 标准库头。如果未安装 MSVC,Clang 和 Clangd 会抱怨缺少标头。
有一个标志使 Clang 使用 MinGW 的 libstdc++ ( --target=x86_64-w64-windows-gnu),我必须将其包含在compile_commands.json.
这个解决方案有效,但即使没有compile_commands.json.
有没有办法让 Clangd 假设--target=x86_64-w64-windows-gnu没有compile_commands.json?
我正在阅读这个 cppreference 页面,并在其中找到了以下代码:
template <class G>
concept uniform_random_bit_generator =
// ...
requires {
// ...
requires std::bool_constant<(G::min() < G::max())>::value;
};
Run Code Online (Sandbox Code Playgroud)
我很好奇为什么std::bool_constant在这里使用。是不是可以requires G::min() < G::max();直接使用,像这样:
template <class G>
concept uniform_random_bit_generator =
// ...
requires {
// ...
requires G::min() < G::max();
};
Run Code Online (Sandbox Code Playgroud) 我刚刚得到了一个有趣的比赛条件。考虑以下类:
#include <atomic>
#include <chrono>
#include <iostream>
#include <thread>
class A
{
std::thread th;
std::atomic_bool stop = false;
public:
A() = default;
A(const A &) = delete;
A &operator=(const A &) = delete;
~A()
{
stop.store(true);
th.join();
}
virtual void Step() = 0;
void Start()
{
th = std::thread([this]
{
while (true)
{
if (stop.load())
return;
// Just to help reproduce the race condition.
std::this_thread::sleep_for(std::chrono::milliseconds(50));
Step();
}
});
}
};
struct B : A
{
void Step() override
{
std::cout …Run Code Online (Sandbox Code Playgroud) 考虑这段代码:
#include <type_traits>
struct A {};
struct B
{
template <typename T, std::enable_if_t<!std::is_constructible_v<B, T &&>, std::nullptr_t> = nullptr>
B(T &&) {}
};
int main()
{
B b(A{});
}
Run Code Online (Sandbox Code Playgroud)
Clang、GCC 和 MSVC 都接受它。
这段代码是否有效,或者编译器应该拒绝它?
有趣的是,如果我使用requires而不是enable_if_t,GCC 和 Clang 开始拒绝它,而 MSVC 仍然接受。该错误归结为satisfaction of constraint depends on itself。
但同样的事情不应该导致第一个代码中的错误吗?或者这是未定义的?
#include <type_traits>
struct A {};
struct B
{
template <typename T>
requires(!std::is_constructible_v<B, T &&>)
B(T &&) {}
};
int main()
{
B b(A{});
}
Run Code Online (Sandbox Code Playgroud) 显然std::function::operator=(F &&f)是需要的行为完全一样std::function(std::forward<F>(f)).swap(*this);.
除非我遗漏了某些东西,否则这个定义会导致一些多余的移动:
#include <functional>
#include <iostream>
struct A
{
A() {std::cout << "A()\n";}
A(const A &) {std::cout << "A(const A &)\n";}
A(A &&) {std::cout << "A(A &&)\n";}
A &operator=(const A &) {std::cout << "A &operator=(const A &)\n"; return *this;}
A &operator=(A &&) {std::cout << "A &operator=(A &&)\n"; return *this;}
~A() {std::cout << "~A()\n";}
void operator()() const {}
};
int main()
{
std::function<void()> f;
f = A{};
}
Run Code Online (Sandbox Code Playgroud)
打印:
Run Code Online (Sandbox Code Playgroud)A() // Created by `A{}` …
c++ ×10
c++20 ×3
clang ×3
c++17 ×2
clang++ ×1
clangd ×1
compiler-bug ×1
g++ ×1
hash ×1
mingw-w64 ×1
polymorphism ×1
std-function ×1
stdthread ×1
template-argument-deduction ×1
ubsan ×1