zephyr: Zephyr does not define minimal C++ language standard requirement and does not track it
Describe the bug Zephyr defines C11 as minimal supported standard for C language in C language support - language standards. Similar documentation article: C++ language support does not have “language standard” section. Roadmap #31281 also does not say a word about minimal requirements. Thus, minimal C++ version supported is unknown. This is a serious problem since:
- C++ language standards have much more changes between releases than C language.
- Custom toolchains for embedded systems often concentrate on C language support (due to its popularity) leaving C++ language with old standard (like dreadful C++98).
Concrete problem encountered:
SOF project uses Cadence Xtensa toolchain “xt-xcc” that is based on GNU 4.2.0 compiler for Intel Meteorlake audio firmware.
Meteorlake board has some C++ code that uses Zephyr #include <zephyr/sys/util.h> that provides C/C++ interropt helpers at the time of writing. “xt-xcc” is obsolete for some time and latest support language is C++98 standard.
Everything was working fine in our CI until PR #53405 , where author added constexpr keyword usage in commit deab09d7a6b0c51a52ffd8bd03f17e04cf39c25c .
Author @cfriedt in that PR claims (selective quote):
There should be a announcement for this and the code that suddenly requires new C++
As mentioned above, this is all in line with Zephyr’s suggested ISO C and C++ standards (C11, C++11).
Proof of wrong:
Fuction template definition __z_log2_impl from include/zephyr/sys/util.h in some conditions returns value A and in other conditions value B. According to C++ standard ISO/IEC 14882:2011 §7.1.5.3:
The definition of a constexpr function shall satisfy the following constraints:
- it shall not be virtual (10.3);
- its return type shall be a literal type;
- each of its parameter types shall be a literal type;
- its function-body shall be = delete, = default, or a compound-statement that contains only
- null statements,
- static_assert-declarations
- typedef declarations and alias-declarations that do not define classes or enumerations,
- using-declarations,
- using-directives,
- and exactly one return statement;
- every constructor call and implicit conversion used in initializing the return value (6.6.3, 8.5) shall be one of those allowed in a constant expression (5.19).
Also, cppreference.com - constexpr confirms this: Quote marked “(until C++14)”:
the function body must be either deleted or defaulted or contain only the following:
- null statements (plain semicolons)
- static_assert declarations
- typedef declarations and alias declarations that do not define classes or enumerations
- using declarations
- using directives
- if the function is not a constructor, exactly one return statement
To Reproduce Steps to reproduce the behavior:
- Open my minimal reproduction project with Compiler Explorer: https://godbolt.org/z/78sWY65v4
- Play around with compiler version and C++ standard. Note: compiler x86-64 gcc 12.2 compiles minimal example using C++11 without a warning! Change compiler to: x86-64 gcc 11.3 to receive an error (related to multiple return statements in constexpr function):
header.h:17:1: error: body of ‘constexpr’ function ‘constexpr int __z_log2_impl(T) [with T = int]’ not a return-statement 17 | } | ^
- Change CMake line:
set_property(TARGET output.s PROPERTY CXX_STANDARD 11)toset_property(TARGET output.s PROPERTY CXX_STANDARD 14)and watch how everything compiles successfully.
Expected behavior
- Zephyr defines minimal C++ language standard in the official documentation. Right now it is C++14 if we do not roll back PR #53405 (probably - remaining C++ code needs verification too!)
- Developers know, and check the C++ standard of the code they wright! Please note, that modern compilers GCC, Clang, MSVC tend to provide “backward compatibility” to old C++ standards what results in non-conforming code being compiled without an issue! If the compiler supports C++17 or C++20 it is possible that it will compile the code marked -std=c++11 that should not compile with that standard due to compiler extensions they provide! We need to watch the conformance carefully, maybe some static analysis tools?
Impact SOF project has to urgently upgrade toolchain to new Cadence Xtensa “xt-clang” based on clang, that allows to use up to C++17 standard. If we do not do this, we are unable upgrade Zephyr revisions since our code will not build! Luckily, we had been preparing for toolchain change in https://github.com/thesofproject/sof/pull/7027 for some time and have only 2 .cpp source files at the time of writing.
Logs and console output Compiling with xt-xcc: xt-xcc.log Compiling with xt-clang -std=c++11: xt-clang C++11.log
Environment (please complete the following information):
- OS: Windows, Linux
Additional context N/A
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 1
- Comments: 16 (8 by maintainers)
Commits related to this issue
- doc: Clarify C++ standards support We weren't explicit about what we mean by "C++ support" as it relates to standards versions, and it's been causing some friction in the tree vs. some of our cruftie... — committed to andyross/zephyr by andyross a year ago
- doc: Clarify C++ standards support We weren't explicit about what we mean by "C++ support" as it relates to standards versions, and it's been causing some friction in the tree vs. some of our cruftie... — committed to andyross/zephyr by andyross a year ago
- doc: Clarify C++ standards support We weren't explicit about what we mean by "C++ support" as it relates to standards versions, and it's been causing some friction in the tree vs. some of our cruftie... — committed to andyross/zephyr by andyross a year ago
- doc: Clarify C++ standards support We weren't explicit about what we mean by "C++ support" as it relates to standards versions, and it's been causing some friction in the tree vs. some of our cruftie... — committed to andyross/zephyr by andyross a year ago
- doc: Clarify C++ standards support We weren't explicit about what we mean by "C++ support" as it relates to standards versions, and it's been causing some friction in the tree vs. some of our cruftie... — committed to andyross/zephyr by andyross a year ago
- doc: Clarify C++ standards support We weren't explicit about what we mean by "C++ support" as it relates to standards versions, and it's been causing some friction in the tree vs. some of our cruftie... — committed to nordicjm/zephyr by andyross a year ago
Hm… as of right now we guarantee that all the OS headers build correctly with C++98 compilers (specifically gcc and clang with -std=c++98), and we’re testing this along with all the other . It’s true it was a hole, but I’m pretty sure it’s been plugged. Obviously the discussion as to when to deprecate C++98 will be contentious, but for now at least that’s the requirement.
Which is to say: if you push a PR right now using
alignofor rvalue references or whatever inside an#ifdef __cplusplus, it will fail in CI. I think that’s what you want, no?(Note that there are other issues with C++ support at the toolchain level, like “how to link in the standard library” that are quite a bit farther behind. So while the OS has support lots of platforms won’t quite build C++98 correctly even if their compilers technically support it; xcc and xt-clang are both in this category for now.)
Yeah, those problems are fixed as of #55290
Please open a new bug if you find a way to add non-C++98 code to an OS header without doing proper version detection.
I reopen this issue because it looks to me that you may missed the key point I am trying to show here. This statement:
Is not a resolution to problem with using C++. I agree that new language feature are appealing, but please note what I wrote in the issue description:
What if the zephyr application that uses some custom toolchain X to build embedded projects does not have a compiler supporting C++11 or newer? You basically block them from using your services (Zephyr APIs). @andyross, filling up documentation with “We support C++ standard whatever found in the given file you compile” is not a solution either. I would rather call it “discrediting a problem” than solving it. This problem is not related to C, because Zephyr does great job of hiding C language features under #ifdef macros. Example: What would happen to all zephyr applications if you suddenly add to very commonly used header (like some util header) alignof keyword (supported since C11). All zephyr applications using C99 would stop to work and would be forced to use C11 compiler right? You basically do the same for C++ right now, and cover the issue with a blanked - do not do this.
@aborisovich - no harsh feelings. I’m glad that we can work together to make things better.
Please let me know if you need any help.
@cfriedt I never, ever meant to discredit anyone. I assume that as obvious thing, that we developers work with mutual respect. Bugs, unspecified behaviors are constant part of our work. Moreover, I strongly approve what you do - C++ is a very needed language in Zephyr and I hope it will be replacing or complimenting C in future. When I wrote “you are doing something wrong” I meat it as a quote, not as an expression targeting you directly. By this quote I meant “Zephyr project systems providing API compatibility”. I wanted to indicate importance of the problem I described above and potentially severe impact, so we can harden the processes in Zephyr.
@aborisovich - can you extract just the relevant portion of your error from the log and put it into a markdown code block, so that the error is a bit more obvious / searchable?
It’s a bit difficult to pinpoint where the actual error is and it would help if the issue were more concise. This would help others try to fix your issue without having access to your compiler.
Can you provide a way to reproduce using
westortwister?Your issue can likely be solved relatively easily with a simple code change. Additional static analysis would not solve any aspect of the actual problem. It would just describe it differently.
And please, again, critique the code, not the author 😃 You’re not here to discredit me, right? You’re here to hopefully get help to solve your problem.