c2rust icon indicating copy to clipboard operation
c2rust copied to clipboard

`stdatomic.h` raises missing types for `AstNode { ... __ATOMIC_SEQ_CST }`

Open chrysn opened this issue 5 years ago • 3 comments

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.)

chrysn avatar Sep 03 '20 17:09 chrysn

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.)

thedataking avatar Sep 03 '20 20:09 thedataking

_Atomic quantifier 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.

chrysn avatar Sep 04 '20 20:09 chrysn

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.

chrysn avatar Sep 18 '20 08:09 chrysn