在使用 clang++ 的 C++ 中,是否可以根据隐式 \xe2\x80\x98this\xe2\x80\x99 参数上的地址空间限定符重载方法?如果是这样,语法是什么?
\n\n该来源建议我可以将地址空间限定符放在参数列表之后、大括号之前(类似于在 \'this\' 上使用 const 限定符)。我尝试了以下方法,但失败了;clang 认为我正在尝试设置方法的地址空间,而不是“this”:
\n\n // Does not work.\n struct SomeClass\n {\n // method for \'this\' in default address space\n void doit();\n // method for \'this\' in address space 300.\n void doit() __attribute__((address_space(300)); // clang rejects this syntax\n }\nRun Code Online (Sandbox Code Playgroud)\n\n我发现的最接近的是 clang 让我根据其显式形式参数的地址空间(而不是 \'this\' )重载方法。例如,下面的代码将打印 \xe2\x80\x9c1\\n2\\n\xe2\x80\x9d。
\n\n// Similar, but does not solve my problem:\n#include <cstdio>\n\nstruct SomeClass\n{\n void doit(void *v) { printf("1\\n"); }\n void doit(void …Run Code Online (Sandbox Code Playgroud) 我正在尝试调试一些 C++11 代码,而 LLDB 没有帮助。代码大致如下:
void f(my_type dt) {
try {
g(h(dt));
}
catch ( /* reasonable exception type here */ ) {
}
}
Run Code Online (Sandbox Code Playgroud)
当我在该行上放置断点时g(h(dt)),LLDB 坚持认为 的值dt不可用。它肯定不能被忽略,因为它用于实现h某些数据库查询的输入。
我使用 CMake,它使用以下标志进行编译:
CXX_FLAGS = -g -O0 -fPIC -std=c++11 -stdlib=libc++ -Wall
Run Code Online (Sandbox Code Playgroud)
我确认(使用make VERBOSE=true)这些标志确实用于构建项目。据我所知,应包含完整的调试信息并关闭所有优化。事实显然并非如此。我还可以添加哪些其他标志来强制 Clang 保持所有参数和变量在整个调用堆栈中可用?
不幸的是,使用小文件和函数的小测试用例不会重现此问题:大多数时候,变量会按我的预期保留。
我正在运行 Yosemite 的 Mac 上工作。
$ clang++ --version
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin14.1.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud) 我碰巧发现GCC和Clang在以下代码的编译上有所不同:
struct Foo
{
int mem = 42;
};
int main()
{
constexpr Foo foo;
static_assert(__builtin_constant_p(foo));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我用g++ -std=c++17和编译clang++ -std=c++17。
特别是,
g++-9 (Homebrew GCC 9.3.0_1) 9.3.0编译,而Apple clang version 11.0.3 (clang-1103.0.32.62)无法编译,抱怨说error: static_assert failed due to requirement '__builtin_constant_p(foo)'
static_assert(__builtin_constant_p(foo));
^ ~~~~~~~~~~~~~~~~~~~~~~~~~
Run Code Online (Sandbox Code Playgroud)
我没有发现任何关于__builtin_constant_p.
为了 __builtin_constant_p
您可以使用内置函数 __builtin_constant_p 来确定某个值在编译时是否已知为常量...
叮当 说
Clang 支持许多与 GCC 语法相同的内置库函数,包括 __builtin_nan、__builtin_constant_p、__builtin_choose_expr、__builtin_types_compatible_p、__builtin_assume_aligned、__sync_fetch_and_add 等。
问题:虽然我知道__builtin_constant_p是一个编译器扩展,但哪个应该是正确的?
以下代码未链接 Clang 10,但在 GCC 和 Clang 9 上成功:
#include <queue>
template <typename T>
class A
{
public:
void f();
private:
std::queue<int> q;
};
template <typename T>
void A<T>::f()
{
q = {};
}
template class A<int>;
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我从编译器得到的是:
/opt/compiler-explorer/gcc-9.3.0/lib/gcc/x86_64-linux-gnu/9.3.0/../../../../x86_64-linux-gnu/bin/ld: /tmp/example-f70f65.o: in function `A<int>::f()':
/home/ce/<source>:16: undefined reference to `std::queue<int, std::deque<int, std::allocator<int> > >::~queue()'
clang-10: error: linker command failed with exit code 1 (use -v to see invocation)
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud)
如果我替换std::queue为std::vector, …
今天我想测试一下,Clang 如何转换两个函数的递归幂,并注意到即使使用已知指数,即使使用 constexpr 也不会优化递归。
#include <array>
constexpr unsigned int pow2_recursive(unsigned int exp) {
if(exp == 0) return 1;
return 2 * pow2_recursive(exp-1);
}
unsigned int pow2_5() {
return pow2_recursive(5);
}
Run Code Online (Sandbox Code Playgroud)
pow2_5 被编译为对 pow2_recursive 的调用。
pow2_5(): # @pow2_5()
mov edi, 5
jmp pow2_recursive(unsigned int) # TAILCALL
Run Code Online (Sandbox Code Playgroud)
但是,当我在需要在编译时知道结果的上下文中使用结果时,它将在编译时正确计算结果。
unsigned int pow2_5_arr() {
std::array<int, pow2_recursive(5)> a;
return a.size();
}
Run Code Online (Sandbox Code Playgroud)
被编译为
pow2_5_arr(): # @pow2_5_arr()
mov eax, 32
ret
Run Code Online (Sandbox Code Playgroud)
以下是 Godbolt 中完整示例的链接:https ://godbolt.org/z/fcKef1
那么,我在这里错过了什么吗?有什么可以在运行时改变结果的原因吗,pow2_5 不能像 pow2_5_arr 一样优化?
我正在使用最近批准的 C++20 标准功能std::construct_at()并试图更熟悉它们......
我已经根据CppReference.com的示例构建了一个示例:
#include <memory>
struct S {
int a;
int b;
};
int main() {
std::allocator<S> alloc;
S * s = alloc.allocate(1);
std::construct_at(s, 42, 43); // GCC 10.2 OK Clang 12 NOT
std::destroy_at(s);
alloc.deallocate(s, 1);
s = nullptr;
}
Run Code Online (Sandbox Code Playgroud)
上面的代码使用最新的稳定 GCC 构建得很好:
gcc-10.2 test.cpp -std=c++2a -lstdc++
但是我无法使用 Clang 12(主干)或 10(稳定)编译它。
clang-12 test.cpp -std=c++20 -stdlib=libc++
有错误:
test.cpp:11:5: error: no matching function for call to 'construct_at'
std::construct_at(s, 42, 43); // GCC 10.2 OK Clang …Run Code Online (Sandbox Code Playgroud) 我一直在对工作中的一些代码进行性能优化,并偶然发现了一些奇怪的行为,我将其归结为下面的简单 C++ 代码片段:
#include <stdint.h>
void Foo(uint8_t*& out)
{
out[0] = 1;
out[1] = 2;
out[2] = 3;
out[3] = 4;
}
Run Code Online (Sandbox Code Playgroud)
然后,我铛(在Windows上)用下面的编译:clang -S -O3 -masm=intel test.cpp。这导致以下程序集:
mov rax, qword ptr [rcx]
mov byte ptr [rax], 1
mov rax, qword ptr [rcx]
mov byte ptr [rax + 1], 2
mov rax, qword ptr [rcx]
mov byte ptr [rax + 2], 3
mov rax, qword ptr [rcx]
mov byte ptr [rax + 3], 4
ret
Run Code Online (Sandbox Code Playgroud)
为什么 clang 生成的代码反复将out …
我正在查看 clang 模块的驱动程序测试用例:https : //github.com/llvm-mirror/clang/blob/master/test/Driver/modules.cpp
它包括生成 .pcm.o 文件的步骤。我想知道它们是干什么用的。
给定一个 c++20 模块
// a-m.cc
module;
#include <iostream>
export module a;
export void do_a() { std::cout << "A\n"; }
Run Code Online (Sandbox Code Playgroud)
您可以使用编译它
clang++ -std=c++20 -x c++-module --precompile a-m.cc -o a.pcm
Run Code Online (Sandbox Code Playgroud)
它生成预编译的模块文件a.pcm。
但是也有将 .pcm 文件编译为 .o 文件的步骤。
从驱动程序测试:
clang++ -std=c++20 a.pcm -S -o a.pcm.o
Run Code Online (Sandbox Code Playgroud)
如何使用 .pcm.o 文件?
如果我写一个主程序
// main.cc
import a;
int main() {
do_a();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译
clang++ -std=c++20 -c main.cc -fmodule-file=a=a.pcm
Run Code Online (Sandbox Code Playgroud)
然后尝试与 .pcm.o 链接,我得到
clang++ main.o …Run Code Online (Sandbox Code Playgroud) Clang error : invalid operands to binary expression ('const auto' and 'int')
Run Code Online (Sandbox Code Playgroud)
语境 :
简单的问题:
这是一个最小的复制案例(可在 Godbolt 上获得)
template <typename ... Ts>
struct foo
{
constexpr inline static auto value = 42;
};
template <typename ... Ts>
struct bar
{
template <typename U>
constexpr static inline auto foo_value = foo<Ts...>::value; // Error here
// nb : replacing `auto` with `int` remove the error
};
static_assert(bar<int>::foo_value<int> == …Run Code Online (Sandbox Code Playgroud) clang-11使用-pedantic以下代码段编译时,最新版本的 clang (since ) 会发出警告:
namespace foo {
template <int A>
struct Bar {
~Bar();
};
} // namespace foo
template <int A>
foo::Bar<A>::~Bar(){}
Run Code Online (Sandbox Code Playgroud)
生成的警告(和错误-Werror)是:
<source>:10:12: error: ISO C++ requires the name after '::~' to be found in the same scope as the name before '::~' [-Werror,-Wdtor-name]
foo::Bar<A>::~Bar(){}
~~~~~~~~~~~^~
::Bar
Run Code Online (Sandbox Code Playgroud)
clang是我见过的第一个发出此诊断的编译器,据我所知,上面写的内容是完全有效的 C++。似乎抑制这种情况的两种不同方法是在同一名称空间内定义 或 显式限定析构函数名称——例如:
<source>:10:12: error: ISO C++ requires the name after '::~' to be found in the same scope …Run Code Online (Sandbox Code Playgroud)