c2rust
c2rust copied to clipboard
`stdatomic.h` raises missing types for `AstNode { ... __ATOMIC_SEQ_CST }`
Whenever c2rust encounters stdatomic.h in my setup, it fails irrecoverably with messages like this:
warning: Missing type 94827692380208 for node: AstNode { tag: TagTypedefDecl, children: [], loc: SrcSpan { fileid: 81, begin_line: 97, begin_column: 1, end_line: 97, end_column: 37 }, type_id: Some(94827692380208), rvalue: LValue, macro_expansions: [], macro_expansion_text: Some("__ATOMIC_SEQ_CST"), extras: [Text("atomic_uint_least32_t"), Bool(false)] }
Exported Clang AST was invalid. Check warnings above for unimplemented features.
--> /usr/lib/llvm-10/lib/clang/10.0.1/include/stdatomic.h:97:1
[-Wclang-ast]
thread 'main' panicked at 'Could not find CTypeId(4932) in TypedAstContext', c2rust-transpile/src/c_ast/mod.rs:816:21
(The block from warning: to [-Wclang-ast] is repeated dozens of times; all earlier warnings are unrelated "macro redefined" ones).
As support for LLVM 10.0.1 is rather recent, it might be related to that. I'm using Rust nightly-2020-08-29, and LLVM 10.0.1 as in the above error messages..
Full compile_commands.json in case it's relevant
``` [ { "arguments": [ "any-cc", "-DTHREAD_STACKSIZE_MAIN=(THREAD_STACKSIZE_DEFAULT + 5000)", "-DDEVELHELP", "-Wall", "-Wextra", "-pedantic", "-g3", "-std=gnu11", "-m32", "-fstack-protector-all", "-ffunction-sections", "-fdata-sections", "-DDEBUG_ASSERT_VERBOSE", "-DRIOT_APPLICATION=shell_threads", "-DBOARD_NATIVE=native", "-DRIOT_BOARD=BOARD_NATIVE", "-DCPU_NATIVE=native", "-DRIOT_CPU=CPU_NATIVE", "-DMCU_NATIVE=native", "-DRIOT_MCU=MCU_NATIVE", "-fno-common", "-Wall", "-Wextra", "-Wmissing-include-dirs", "-fdiagnostics-color", "-Wstrict-prototypes", "-Wold-style-definition", "-gz", "-Wformat=2", "-include", "/home/chrysn/git/crates/riot-examples/shell_threads/bin/native/riotbuild/riotbuild.h", "-DRIOT_VERSION=2020.10-devel-1190-ga75d3", "-DMODULE_AUTO_INIT", "-DMODULE_AUTO_INIT_XTIMER", "-DMODULE_BOARD", "-DMODULE_CORE", "-DMODULE_CORE_IDLE_THREAD", "-DMODULE_CORE_INIT", "-DMODULE_CORE_MSG", "-DMODULE_CORE_PANIC", "-DMODULE_CPU", "-DMODULE_DIV", "-DMODULE_NATIVE_DRIVERS", "-DMODULE_NETDEV_REGISTER", "-DMODULE_PERIPH", "-DMODULE_PERIPH_COMMON", "-DMODULE_PERIPH_GPIO", "-DMODULE_PERIPH_GPIO_LINUX", "-DMODULE_PERIPH_INIT", "-DMODULE_PERIPH_INIT_GPIO", "-DMODULE_PERIPH_INIT_GPIO_LINUX", "-DMODULE_PERIPH_INIT_PM", "-DMODULE_PERIPH_INIT_TIMER", "-DMODULE_PERIPH_INIT_UART", "-DMODULE_PERIPH_PM", "-DMODULE_PERIPH_TIMER", "-DMODULE_PERIPH_UART", "-DMODULE_PS", "-DMODULE_SHELL", "-DMODULE_SHELL_COMMANDS", "-DMODULE_STDIN", "-DMODULE_STDIO_NATIVE", "-DMODULE_SYS", "-DMODULE_XTIMER", "-I/home/chrysn/git/crates/riot-examples/RIOT/core/include", "-I/home/chrysn/git/crates/riot-examples/RIOT/drivers/include", "-I/home/chrysn/git/crates/riot-examples/RIOT/sys/include", "-I/home/chrysn/git/crates/riot-examples/RIOT/boards/native/include", "-DNATIVE_INCLUDES", "-I/home/chrysn/git/crates/riot-examples/RIOT/boards/native/include/", "-I/home/chrysn/git/crates/riot-examples/RIOT/core/include/", "-I/home/chrysn/git/crates/riot-examples/RIOT/drivers/include/", "-I/home/chrysn/git/crates/riot-examples/RIOT/cpu/native/include", "-I/home/chrysn/git/crates/riot-examples/RIOT/sys/include", "-I/home/chrysn/git/crates/riot-examples/RIOT/cpu/native/include", "riot-c2rust.h" ], "directory": "/home/chrysn/git/crates/riot-examples/shell_threads/target/i686-unknown-linux-gnu/debug/build/riot-sys-4eef4926f1212a50/out", "file": "riot-c2rust.h" } ] ```I got stuck trying to drill down on this; from the lookup I'd have expected something atomic-ish to be registered earlier in TypedAstContext.c_types, but all those are populated using ConversionContext::add_type through ConversionContext::visit_node, and if anything unhandled had shown up there it should have fallen into the large match's _ => panic branch, which obviously didn't happen. (That's from a very high-altitude survey, though; there's countless details I can have missed here.)
The C11 _Atomic quantifier is not supported so that might be it. Of course, we should emit a proper error message. Can you point me to the code you are testing on or share a minimal test case that reproduces the issue?
(Also, please note that you must use the rust nightly version in rust-toolchain, otherwise c2rust will not build.)
_Atomicquantifier is not supported
That does explain things; it would be nice though if it'd be possible to get transpilation at least for functions that don't (maybe even transitively) depend on these types, even when a header is included that pulls in stdatomic. (In the RIOT-OS codebase I'm working with, that's maybe 20% of the headers).
Minimal example
As for minimal example, this is how I've managed to produce errors like the above:
compile_commands.json:
[{
"arguments": ["any-cc", "test.c"],
"file": "test.c",
"directory": "/tmp/minimal-transpile-example/"
}]
test.c:
#include <stdatomic.h>
Alternatively, indeed, the file can also be the first offending line from stdatomic, which is:
typedef _Atomic(char) atomic_char;
Command execution:
$ c2rust transpile compile_commands.json
Transpiling test.c
warning: Missing type 94736737888928 for node: AstNode { tag: TagTypedefDecl, children: [], loc: SrcSpan { fileid: 7, begin_line: 88, begin_column: 1, end_line: 88, end_column: 37 }, type_id: Some(94736737888928), rvalue: LValue, macro_expansions: [], macro_expansion_text: Some("__ATOMIC_SEQ_CST"), extras: [Text("atomic_ullong"), Bool(false)] }
Exported Clang AST was invalid. Check warnings above for unimplemented features.
--> /usr/lib/llvm-10/lib/clang/10.0.1/include/stdatomic.h:88:1
[-Wclang-ast]
[... repeated similar messages elided ...]
warning: Missing type 93859071368176 for node: AstNode { tag: TagTypedefDecl, children: [], loc: SrcSpan { fileid: 7, begin_line: 80, begin_column: 1, end_line: 80, end_column: 37 }, type_id: Some(93859071368176), rvalue: LValue, macro_expansions: [], macro_expansion_text: Some("__ATOMIC_SEQ_CST"), extras: [Text("atomic_uchar"), Bool(false)] }
Exported Clang AST was invalid. Check warnings above for unimplemented features.
--> /usr/lib/llvm-10/lib/clang/10.0.1/include/stdatomic.h:80:1
[-Wclang-ast]
thread 'main' panicked at 'Could not find CTypeId(177) in TypedAstContext', c2rust-transpile/src/c_ast/mod.rs:810:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Workaround
This exercise has led me to see that adding a #define _Atomic(x) x to the headers does work around the immediate problem -- with the downside that it will silently produce erroneous (non-atomic) code where atomics are actually used.
On the tour through the code for what'd be needed to actually implement this, I found that this is a two-staged error: If the test file just contains variables or fields like _Atomic(int) x = 1;, "all is fine" in that it hits an error like test.c:4:15: error: c2rust: C11 Atomics are not supported. Aborting.. Only when a typedef (like the one in stdatomic) is encountered where an _Atomic(x) "expression" is used in the typedef, then the shown errors crop up.
I'll treat this issue as revolving around the steps of how to get into a regular printC11AtomicError error case from the typedefs, and then have a look at what it'd take to actually make atomics usable.