Skip to main content

IAR Embedded Workbench for Arm 9.70.x

Overview—Standard C++

In this section:

The IAR C++ implementation fully complies with the ISO/IEC 14882:2014 C++ (“C++14”) or 14882:2017 C++ (“C++17”) standard, except for source code that depends on thread-related system headers, or the filesystem header. In IAR user documentation, the ISO/IEC 14882:2017 C++ standard is referred to as Standard C++.

Atomic operations are available for cores where the instruction set supports them. See Atomic operations.

The IAR C/C++ compiler accepts source code written in the C++17 standard or a superset thereof.

  • When using the DLIB C++14 library, those features of C++17 that require library support are not available.

  • When using the Libc++ C++17 library, all features of C++17 are available, unless otherwise noted. In addition, some features of C++20 are also available, see Supported C++20 features.

For an overview of the differences between the various versions of the C++ standard, see the Wikipedia articles C++20, C++17, C++14, C++11, or C++ (for information about C++98).

Note

There is also a set of C++ Standard Template Library (STL) headers from an older version of the DLIB library (DLIB5). They have fewer features, but can in some cases result in significantly smaller code for map/set and vector. See the documentation in the file arm/doc/HelpDLIB5.html.

Supported C++20 features

The IAR C/C++ compiler accepts source code written in the C++17 standard or a superset thereof. However, when using the Libc++ library, some features of C++20 are also available, and support for more C++20 features is continuously added.

At the time of writing, the following C++20 features are supported when using the Libc++ library:

  • Concepts (including abbreviated function template declarations)

  • Three-way comparison (also known as the spaceship operator) <=>

  • constinit and consteval

  • constexpr relaxations. The following is allowed in constant expressions:

    • virtual functions

    • try-catch blocks

    • dynamic_cast and polymorphic typeid

    • changing the active member of a union

    • transient allocation

    • trivial default initialization

    • unevaluated asm-declarations

  • Lambdas

    • Default constructible and assignable stateless lambdas

    • Lambdas in unevaluated contexts

    • Template syntax for generic lambdas

  • explicit (bool)

  • Relaxed typename: using typename is optional in more contexts

  • Library support for std::is_constant_evaluated, std::bit_cast, std::identity, std::type_identity, std::common_reference , and std::remove_cvref

Note that __cplusplus is still defined to 201703L (but individual feature testing macros are updated according to their respective supported level. For example, __cpp_constexpr is defined to 202002L).

There are some limitations in the current C++20 support:

  • std::strong_ordering with long double is not supported.

  • Issues related to concepts: CA104 of P2103R0 (Clarify declaration matching and partial ordering requiring substitution into constraints) and P2113R0 (Partial ordering of rewritten operator candidates resulting from constrained templates).

  • Issues related to constexpr: CWG 1581 (When are constexpr member functions defined?).

Modes for exceptions and RTTI support

Both exceptions and runtime type information result in increased code size simply by being included in your application. You might want to disable either or both of these features to avoid this increase:

  • Support for runtime type information constructs can be disabled by using the compiler option ‑‑no_rtti

  • Support for exceptions can be disabled by using the compiler option ‑‑no_exceptions

Even if support is enabled while compiling, the linker can avoid including the extra code and tables in the final application. If no part of your application actually throws an exception, the code and tables supporting the use of exceptions are not included in the application code image. Also, if dynamic runtime type information constructs (dynamic_cast/typeid) are not used with polymorphic types, the objects needed to support them are not included in the application code image. To control this behavior, use the linker options ‑‑no_exceptions, ‑‑force_exceptions, and ‑‑no_dynamic_rtti_elimination.

Disabling exception support

When you use the compiler option ‑‑no_exceptions, the following will generate a compiler error:

  • throw expressions

  • try-catch statements

  • Exception specifications on function definitions.

In addition, the extra code and tables needed to handle destruction of objects with auto storage duration when an exception is propagated through a function will not be generated when the compiler option ‑‑no_exceptions is used.

All functionality in system header files not directly involving exceptions is supported when the compiler option ‑‑no_exceptions is used.

The linker will produce an error if you try to link C++ modules compiled with exception support with modules compiled without exception support

For more information, see ‑‑no_exceptions.

Disabling RTTI support

When you use the compiler option ‑‑no_rtti, the following will generate a compiler error:

  • The typeid operator

  • The dynamic_cast operator.

Note

If ‑‑no_rtti is used but exception support is enabled, most RTTI support is still included in the compiler output object file because it is needed for exceptions to work.

For more information, see ‑‑no_rtti.

Exception handling

Exception handling can be divided into three parts:

  • Exception raise mechanisms—in C++ they are the throw and rethrow expressions.

  • Exception catch mechanisms—in C++ they are the trycatch statements, the exception specifications for a function, and the implicit catch to prevent an exception leaking out from main.

  • Information about currently active functions—if they have trycatch statements and the set of auto objects whose destructors need to be run if an exception is propagated through the function.

When an exception is raised, the function call stack is unwound, function by function, block by block. For each function or block, the destructors of auto objects that need destruction are run, and a check is made whether there is a catch handler for the exception. If there is, the execution will continue from that catch handler.

An application that mixes C++ code with assembler and C code, and that throws exceptions from one C++ function to another via assembler routines and C functions must use the linker option ‑‑exception_tables with the argument unwind.

The implementation of exceptions

Exceptions are implemented using a table method. For each function, the tables describe:

  • How to unwind the function, that is, how to find its caller on the stack and restore registers that need restoring

  • Which catch handlers that exist in the function

  • Whether the function has an exception specification and which exceptions it allows to propagate

  • The set of auto objects whose destructors must be run.

When an exception is raised, the runtime will proceed in two phases. The first phase will use the exception tables to search the stack for a function invocation containing a catch handler or exception specification that would cause stack unwinding to halt at that point. Once this point is found, the second phase is entered, doing the actual unwinding, and running the destructors of auto objects where that is needed.

The table method results in virtually no overhead in execution time or RAM usage when an exception is not actually thrown. It does incur a significant penalty in read-only memory usage for the tables and the extra code, and throwing and catching an exception is a relatively expensive operation.

The destruction of auto objects when the stack is being unwound as a result of an exception is implemented in code separated from the code that handles the normal operation of a function. This code, together with the code in catch handlers, is placed in a separate section (.exc.text) from the normal code (normally placed in .text). In some cases, for instance when there is fast and slow ROM memory, it can be advantageous to select on this difference when placing sections in the linker configuration file.