diff --git a/docs/en/api-guides/cplusplus.rst b/docs/en/api-guides/cplusplus.rst index c188c467b1..a1c3b9e394 100644 --- a/docs/en/api-guides/cplusplus.rst +++ b/docs/en/api-guides/cplusplus.rst @@ -132,13 +132,14 @@ ESP-IDF expects the application entry point, ``app_main``, to be defined with C { } +.. _cplusplus_designated_initializers: Designated initializers ^^^^^^^^^^^^^^^^^^^^^^^ Many of the ESP-IDF components use :ref:`configuration structures ` as arguments to the initialization functions. ESP-IDF examples written in C routinely use `designated initializers `_ to fill these structures in a readable and a maintainable way. -C and C++ languages have different rules with regards to the designated initializers. For example, C++ language version C++20, currently the default in ESP-IDF, does not support out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays. Therefore, when porting ESP-IDF C examples to C++, some changes to the structure initializers may be necessary. See the `C++ aggregate initialization reference `_ for more details. +C and C++ languages have different rules with regards to the designated initializers. For example, C++ language version C++23, currently the default in ESP-IDF, does not support out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays. Therefore, when porting ESP-IDF C examples to C++, some changes to the structure initializers may be necessary. See the `C++ aggregate initialization reference `_ for more details. iostream diff --git a/docs/en/api-reference/api-conventions.rst b/docs/en/api-reference/api-conventions.rst index 9909ae183c..f90688ed05 100644 --- a/docs/en/api-reference/api-conventions.rst +++ b/docs/en/api-reference/api-conventions.rst @@ -55,7 +55,21 @@ Most ESP-IDF examples use C99 `designated initializers`_ for structure initializ /* Correct, fields .arg and .name are zero-initialized */ }; -C++ language doesn't support the designated initializers syntax until C++20. However, the GCC compiler partially supports it as an extension. When using ESP-IDF APIs in C++ code, you may consider using the following pattern:: +The C++ language supports designated initializers syntax, too, but the initializers must be in the order of declaration. When using ESP-IDF APIs in C++ code, you may consider using the following pattern:: + + /* Correct, fields .dispatch_method, .name and .skip_unhandled_events are zero-initialized */ + const esp_timer_create_args_t my_timer_args = { + .callback = &my_timer_callback, + .arg = &my_arg, + }; + + ///* Incorrect, .arg is declared after .callback in esp_timer_create_args_t */ + //const esp_timer_create_args_t my_timer_args = { + // .arg = &my_arg, + // .callback = &my_timer_callback, + //}; + +For more information on designated initializers, see :ref:`Designated initializers `. Note that C++ language versions older than C++20 (not the default in the current version of ESP-IDF) do not support designated initializers. If you have to compile code with an older C++ standard than C++20, you may use GCC extensions to produce the following pattern:: esp_timer_create_args_t my_timer_args = {}; /* All the fields are zero-initialized */ diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 0107b76fbe..70bb2d636c 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -127,14 +127,10 @@ function(__build_set_lang_version) if(NOT IDF_TARGET STREQUAL "linux") # Building for chip targets: we use a known version of the toolchain. # Use latest supported versions. - # Please update docs/en/api-guides/cplusplus.rst when changing this. + # Please update docs/en/api-guides/cplusplus.rst and + # tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp when changing this. set(c_std gnu17) - if(NOT ${env_idf_toolchain} STREQUAL "clang") - set(cxx_std gnu++23) - else() - # TODO: IDF-7241 - remove the exception for clang - set(cxx_std gnu++20) - endif() + set(cxx_std gnu++2b) else() enable_language(C CXX) # Building for Linux target, fall back to an older version of the standard @@ -154,7 +150,7 @@ function(__build_set_lang_version) "${preferred_c_versions}. Please upgrade the host compiler.") endif() - set(preferred_cxx_versions gnu++23 gnu++20 gnu++2a gnu++17 gnu++14) + set(preferred_cxx_versions gnu++2b gnu++20 gnu++2a gnu++17 gnu++14) set(ver_found FALSE) foreach(cxx_version ${preferred_cxx_versions}) check_cxx_compiler_flag("-std=${cxx_version}" ver_${cxx_version}_supported) diff --git a/tools/test_apps/system/cxx_build_test/README.md b/tools/test_apps/system/cxx_build_test/README.md index 5d06d766df..8d0f8f8c7f 100644 --- a/tools/test_apps/system/cxx_build_test/README.md +++ b/tools/test_apps/system/cxx_build_test/README.md @@ -3,8 +3,13 @@ # C++ build test -This build-only app can be used to check if certain headers, macros or features can be successfully compiled in a C++ source file. +This build-only app can be used to check if certain headers, macros or features can be successfully compiled in a C++ source file. It furthermore checks the current C++ language standard set in IDF is the expected one. -To add a new test, create a new file `main/test_.cpp` and add it to main/CMakeLists.txt. +## This App Broke My Build :( -If you need to check specific compiler flags, use `set_source_files_properties` CMake function to adjust the compilation flags for the given source file. +It is likely that one of the following situations occurred: +1. The language standard for IDF has been changed without changing the test in this application. +2. Code incompatible to C++ has been added to one of the public header files in IDF. Check the C++ documentation section [Combining C and C++ code](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/cplusplus.html#combining-c-and-c-code) for more details. + +## Adding New Test +Create a new file `main/test_.cpp` and add it to main/CMakeLists.txt. If you need to check specific compiler flags, use `set_source_files_properties` CMake function to adjust the compilation flags for the given source file. diff --git a/tools/test_apps/system/cxx_build_test/main/CMakeLists.txt b/tools/test_apps/system/cxx_build_test/main/CMakeLists.txt index 44110851e6..941c102217 100644 --- a/tools/test_apps/system/cxx_build_test/main/CMakeLists.txt +++ b/tools/test_apps/system/cxx_build_test/main/CMakeLists.txt @@ -1,6 +1,7 @@ idf_component_register(SRCS cxx_build_test_main.cpp test_soc_reg_macros.cpp test_esp_hw_support.cpp + test_cxx_standard.cpp INCLUDE_DIRS "." PRIV_REQUIRES driver REQUIRES soc) diff --git a/tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp b/tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp new file mode 100644 index 0000000000..0d6401a9cc --- /dev/null +++ b/tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp @@ -0,0 +1,10 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +/* + * Current (2023-05-04) value for -std=gnu++23 and -std=gnu++2b. + * If you change the C++ standard for IDF, you also need to change this. + */ +static_assert(__cplusplus == 202100L);