c++
clang-format and single-line statements
The Google C++ Style is widely adopted by projects. It contains a brace omission guideline in Looping and branching statements:
…For historical reasons, we allow one exception to the above rules: the curly braces for the controlled statement or the line breaks inside the curly braces may be omitted if as a result the entire statement appears on either a single line (in which case there is a space between the closing parenthesis and the controlled statement) or on two lines (in which case there is a line break after the closing parenthesis and there are no braces).
C++ exit-time destructors
In ISO C++ standards, [basic.start.term] specifies that:
Constructed objects ([dcl.init]) with static storage duration are destroyed and functions registered with std::atexit are called as part of a call to std::exit ([support.start.term]). The call to std::exit is sequenced before the destructions and the registered functions. [Note 1: Returning from main invokes std::exit ([basic.start.main]). — end note]
For example, consider the following code:
struct A { ~A(); } a;
The destructor for object a will be registered for execution at program termination.
…C++ standard library ABI compatibility
Updated in 2023-11.
For a user who only uses one C++ standard library, such as libc++, there are typically three compatibility goals, each with increasing compatibility requirements:
- Can the program, built with a specific version of libc++, work with an upgraded libc++ shared object (DSO)?
- Can an executable and its DSOs be compiled with different versions of libc++ headers?
- Can two relocatable object files, compiled with different versions of libc++ headers, be linked into the same executable or DSO?
If we replace "different libc++ versions" with a mixture of libc++ and libstdc++, we encounter additional goals:
- Can the program, built with a specific version of libstdc++, work with an upgraded libstdc++ DSO?
- Can an executable, built with libc++, link against DSOs that were built with libstdc++?
- Can two relocatable object files, compiled with libc++ and libstdc++, or two libstdc++ versions, be linked into the same executable or DSO?
Considering static linking raises another interesting question:
If libc++ is statically linked into b.so, can it be used with a.out that links against a different version of libc++?
Let's focus on the first three questions, which specifically pertain to libc++.
C standard library headers in C++
Updated in 2024-01.
In ISO C++ standards, [support.c.headers.general] says:
Source files that are not intended to also be valid ISO C should not use any of the C headers.
Then, [depr.c.headers] describes how a C header name.h is transformed to the corresponding C++ cname header. There is a helpful example:
[ Example: The header
assuredly provides its declarations and definitions within the namespace std. It may also provide these names within the global namespace. The header <stdlib.h> assuredly provides the same declarations and definitions within the global namespace, much as in the C Standard. It may also provide these names within the namespace std. — end example ]
"may also" in the wording allows implementations to provide mix-and-match, e.g. #include <stdlib.h> may provide std::exit and #include <cstdlib> may provide ::exit.
libstdc++ chooses to enable global namespace declarations with C++ cname header.
For example, #include <cstdlib> also includes the corresponding C header stdlib.h and we get declarations in both the global namespace and the namespace std.
. /usr/include/c++/12/cstdlib
.. /usr/include/stdlib.h
The preprocessed output looks like:
extern void exit (int __status) noexcept (true) __attribute__ ((__noreturn__));
extern "C++"
{
namespace std __attribute__ ((__visibility__ ("default")))
{
using ::exit;
}
}
The compiler knows that the declarations in the namespace std are identical to the ones in the global namespace.
The compiler recognizes some library functions and can optimize them. By using the compiler can optimize some C library functions in the namespace std (e.g. many std::mem* and std::str* functions).
For some C standard library headers, libstdc++ provides wrappers (libstdc++-v3/include/c_compatibility/) which take precedence over the glibc headers.
The configuration of libstdc++ uses --enable-cheaders=c_global by default.
if GLIBCXX_C_HEADERS_C_GLOBAL in libstdc++-v3/include/Makefile.am describes that the 6 wrappers (complex.h, fenv.h, tgmath.h, math.h, stdatomic.h, stdlib.h) shadow the C library headers of the same name.
For example, #include <stdlib.h> includes the wrapper stdlib.h which includes cstdlib, therefore bringing exit into the namespace std.
. /usr/include/c++/12/stdlib.h
.. /usr/include/c++/12/cstdlib
... /usr/include/stdlib.h…
C++ exception handling ABI
Updated in 2024-11.
I wrote an article a few weeks ago to introduce stack unwinding in detail. Today I will introduce C++ exception handling, an application of stack unwinding. Exception handling has a variety of ABI (interoperability of C++ implementations), the most widely used of which is Itanium C++ ABI: Exception Handling
…C++ language server ccls一周年
2018年4月1日我写了ccls: a fork of the C++ language server cquery,宣告ccls诞生。如今一周年,有必要记录下这一年的点点滴滴。
…2018-09-09 ccls最近更新
加了一些initialization options,参见https://github.com/MaskRay/ccls/tree/master/src/config.h。
…$ccls/navigate和index.multiVersion
忙碌的Labor Day长周末。Growth hacking(希望Hudson River Trading用上无进展,和前clangd、Eclipse CDT开发者交谈、cdt-lsp计划,给LanguageClient-neovim vim-lsp加wiki页面成功),增加了少量stargazers。学习clangd并悄悄改typo、摸索musl的开发模式,希望r2走上正途(C11/C99),LeetCode第一次用上std::adjacent_find……
gcc中sqrt实现
对于sqrt(3);,Visual Studio会报告有歧义的重载函数调用,而gcc却能把这个解释为对sqrt(double)的调用。研究了一下gcc的实现,发现sqrt其实是《C++ Templates: The Complete Guide》中提到的type function,使用了名为SFINAE (substitution failure is not an error)的技术。这里是给出一个使用该技术的sqrt的简易实现: