Explorar o código

Merge branch 'feature/universal_clang_toolchain_support' into 'master'

build: Adds support for universal Clang toolchain

Closes LLVM-79

See merge request espressif/esp-idf!20090
Alexey Gerenkov %!s(int64=3) %!d(string=hai) anos
pai
achega
8c2ae2f9bd
Modificáronse 46 ficheiros con 598 adicións e 80 borrados
  1. 5 0
      .gitlab-ci.yml
  2. 82 0
      .gitlab/ci/build.yml
  3. 22 0
      .gitlab/ci/rules.yml
  4. 13 3
      CMakeLists.txt
  5. 5 1
      components/bt/CMakeLists.txt
  6. 1 1
      components/bt/controller/esp32/bt.c
  7. 1 1
      components/bt/host/bluedroid/api/esp_gap_ble_api.c
  8. 4 4
      components/bt/host/bluedroid/stack/btm/btm_devctl.c
  9. 12 2
      components/cxx/CMakeLists.txt
  10. 4 4
      components/cxx/cxx_guards.cpp
  11. 3 2
      components/driver/test_apps/components/esp_serial_slave_link/essl_spi.c
  12. 4 0
      components/efuse/esp32c2/esp_efuse_utility.c
  13. 4 0
      components/efuse/esp32c3/esp_efuse_utility.c
  14. 4 0
      components/efuse/esp32c6/esp_efuse_utility.c
  15. 4 0
      components/efuse/esp32h4/esp_efuse_utility.c
  16. 4 0
      components/efuse/esp32s2/esp_efuse_utility.c
  17. 4 0
      components/efuse/esp32s3/esp_efuse_utility.c
  18. 1 1
      components/esp_system/port/arch/xtensa/panic_arch.c
  19. 12 0
      components/freertos/FreeRTOS-Kernel/portable/riscv/port.c
  20. 1 1
      components/mbedtls/port/sha/dma/sha.c
  21. 5 3
      components/riscv/project_include.cmake
  22. 0 1
      components/sdmmc/sdmmc_io.c
  23. 6 2
      components/spi_flash/spi_flash_hpm_enable.c
  24. 3 3
      components/touch_element/touch_element.c
  25. 1 1
      components/wpa_supplicant/src/rsn_supp/wpa.c
  26. 8 1
      components/xtensa/include/xtensa/core-macros.h
  27. 16 1
      components/xtensa/project_include.cmake
  28. 1 1
      docs/en/api-guides/tools/idf-clang-tidy.rst
  29. 1 1
      docs/en/api-guides/tools/idf-tools-notes.inc
  30. 1 1
      docs/zh_CN/api-guides/tools/idf-tools-notes.inc
  31. 7 2
      tools/ci/configure_ci_environment.sh
  32. 1 0
      tools/cmake/build.cmake
  33. 7 8
      tools/cmake/toolchain-clang-esp32.cmake
  34. 32 0
      tools/cmake/toolchain-clang-esp32c2.cmake
  35. 32 0
      tools/cmake/toolchain-clang-esp32c3.cmake
  36. 32 0
      tools/cmake/toolchain-clang-esp32c6.cmake
  37. 32 0
      tools/cmake/toolchain-clang-esp32h2.cmake
  38. 8 9
      tools/cmake/toolchain-clang-esp32s2.cmake
  39. 7 9
      tools/cmake/toolchain-clang-esp32s3.cmake
  40. 6 0
      tools/test_apps/.build-test-rules.yml
  41. 6 0
      tools/test_apps/system/cxx_pthread_bluetooth/CMakeLists.txt
  42. 51 0
      tools/test_apps/system/cxx_pthread_bluetooth/README.md
  43. 2 0
      tools/test_apps/system/cxx_pthread_bluetooth/main/CMakeLists.txt
  44. 108 0
      tools/test_apps/system/cxx_pthread_bluetooth/main/cpp_pthread.cpp
  45. 3 0
      tools/test_apps/system/cxx_pthread_bluetooth/sdkconfig.defaults
  46. 32 17
      tools/tools.json

+ 5 - 0
.gitlab-ci.yml

@@ -168,6 +168,11 @@ cache:
     fi
   fi
 
+  # Install esp-clang if necessary
+  if [[ "$IDF_TOOLCHAIN" == "clang" ]]; then
+    $IDF_PATH/tools/idf_tools.py --non-interactive install esp-clang
+  fi
+
   source ./export.sh
 
   # Custom OpenOCD

+ 82 - 0
.gitlab/ci/build.yml

@@ -81,6 +81,24 @@
         examples/bluetooth/hci/controller_hci_uart_esp32
         examples/wifi/iperf
 
+.build_cmake_clang_template:
+  extends:
+    - .build_cmake_template
+  variables:
+    IDF_TOOLCHAIN: clang
+    TEST_BUILD_OPTS_EXTRA: ""
+    TEST_DIR: tools/test_apps/system/cxx_pthread_bluetooth
+  script:
+    # CI specific options start from "--collect-size-info xxx". could ignore when running locally
+    - run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v
+      -t $IDF_TARGET
+      --copy-sdkconfig
+      --collect-size-info size_info.txt
+      --collect-app-info list_job_${CI_NODE_INDEX:-1}.json
+      --parallel-count ${CI_NODE_TOTAL:-1}
+      --parallel-index ${CI_NODE_INDEX:-1}
+      $TEST_BUILD_OPTS_EXTRA
+
 .build_pytest_template:
   extends:
     - .build_cmake_template
@@ -595,6 +613,70 @@ build_test_apps_esp32c6:
     IDF_TARGET: esp32c6
     TEST_DIR: tools/test_apps
 
+build_clang_test_apps_esp32:
+  extends:
+    - .build_cmake_clang_template
+    - .rules:build:custom_test-esp32
+  variables:
+    IDF_TARGET: esp32
+
+build_clang_test_apps_esp32s2:
+  extends:
+    - .build_cmake_clang_template
+    - .rules:build:custom_test-esp32s2
+  variables:
+    IDF_TARGET: esp32s2
+
+build_clang_test_apps_esp32s3:
+  extends:
+    - .build_cmake_clang_template
+    - .rules:build:custom_test-esp32s3
+  variables:
+    IDF_TARGET: esp32s3
+
+.build_clang_test_apps_riscv:
+  extends:
+    - .build_cmake_clang_template
+  variables:
+    # For RISCV clang generates '.linker-options' sections of type 'llvm_linker_options' in asm files.
+    # See (https://llvm.org/docs/Extensions.html#linker-options-section-linker-options).
+    # Binutils gas ignores them with warning.
+    # TODO: LLVM-112, Use integrated assembler.
+    TEST_BUILD_OPTS_EXTRA: "--ignore-warning-str 'Warning: unrecognized section type'"
+
+build_clang_test_apps_esp32c3:
+  extends:
+    - .build_clang_test_apps_riscv
+    - .rules:build:custom_test-esp32c3
+  variables:
+    IDF_TARGET: esp32c3
+
+build_clang_test_apps_esp32c2:
+  extends:
+    - .build_clang_test_apps_riscv
+    - .rules:build:custom_test-esp32c2
+  # spec files and nano libc are not supported yet by esp-clang
+  # TODO: LLVM-197
+  allow_failure: true
+  variables:
+    IDF_TARGET: esp32c2
+
+build_clang_test_apps_esp32c6:
+  extends:
+    - .build_clang_test_apps_riscv
+    - .rules:build:custom_test-esp32c6
+  # TODO: c6 builds fail in master due to missing headers
+  allow_failure: true
+  variables:
+    IDF_TARGET: esp32c6
+
+build_clang_test_apps_esp32h4:
+  extends:
+    - .build_clang_test_apps_riscv
+    - .rules:build:custom_test-esp32h4
+  variables:
+    IDF_TARGET: esp32h4
+
 .test_build_system_template:
   stage: host_test
   extends:

+ 22 - 0
.gitlab/ci/rules.yml

@@ -854,6 +854,28 @@
     - <<: *if-dev-push
       changes: *patterns-target_test-wifi
 
+.rules:build:custom_test-esp32h4:
+  rules:
+    - <<: *if-revert-branch
+      when: never
+    - <<: *if-protected
+    - <<: *if-label-build
+    - <<: *if-label-custom_test
+    - <<: *if-label-custom_test_esp32h4
+    - <<: *if-label-target_test
+    - <<: *if-dev-push
+      changes: *patterns-build_components
+    - <<: *if-dev-push
+      changes: *patterns-build_system
+    - <<: *if-dev-push
+      changes: *patterns-custom_test
+    - <<: *if-dev-push
+      changes: *patterns-downloadable-tools
+    - <<: *if-dev-push
+      changes: *patterns-target_test-i154
+    - <<: *if-dev-push
+      changes: *patterns-target_test-wifi
+
 .rules:build:custom_test-esp32s2:
   rules:
     - <<: *if-revert-branch

+ 13 - 3
CMakeLists.txt

@@ -102,8 +102,19 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
     # Disable Clang warnings for atomic operations with access size
     # more then 4 bytes
     list(APPEND compile_options "-Wno-atomic-alignment")
+    # several warnings in wpa_supplicant component
+    list(APPEND compile_options "-Wno-unused-but-set-variable")
     # Clang also produces many -Wunused-function warnings which GCC doesn't.
-    # However these aren't treated as errors.
+    list(APPEND compile_options "-Wno-unused-function")
+    # many warnings in bluedroid code
+    # warning: field 'hdr' with variable sized type 'BT_HDR' not at the end of a struct or class is a GNU extension
+    list(APPEND compile_options "-Wno-gnu-variable-sized-type-not-at-end")
+    # several warnings in bluedroid code
+    list(APPEND compile_options "-Wno-constant-logical-operand")
+    # warning: '_Static_assert' with no message is a C2x extension
+    list(APPEND compile_options "-Wno-c2x-extensions")
+    # warning on xMPU_SETTINGS for esp32s2 has size 0 for C and 1 for C++
+    list(APPEND compile_options "-Wno-extern-c-compat")
 endif()
 # More warnings may exist in unit tests and example projects.
 
@@ -171,7 +182,6 @@ endif()
 # GCC-specific options
 if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
     list(APPEND compile_options "-fstrict-volatile-bitfields"
-                                "-Wno-error=unused-but-set-variable"
                                 )
 endif()
 
@@ -205,7 +215,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU")
     list(APPEND compile_options "-fno-tree-switch-conversion")
 endif()
 
-if(CMAKE_C_COMPILER_ID MATCHES "LLVM")
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
     list(APPEND compile_options "-fno-use-cxa-atexit")
 endif()
 

+ 5 - 1
components/bt/CMakeLists.txt

@@ -734,7 +734,11 @@ if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE AND CONFIG_BT_NIMBLE_ENABLED)
 endif()
 
 if(NOT CMAKE_BUILD_EARLY_EXPANSION)
+    set(jump_table_opts "-fjump-tables")
+    if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang") )
+        set(jump_table_opts "${jump_table_opts} -ftree-switch-conversion")
+    endif()
     set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/host/bluedroid/bta/hf_ag/bta_ag_cmd.c"
                                 "${CMAKE_CURRENT_LIST_DIR}/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c"
-                                 PROPERTIES COMPILE_FLAGS "-fjump-tables -ftree-switch-conversion")
+                                PROPERTIES COMPILE_FLAGS "${jump_table_opts}")
 endif()

+ 1 - 1
components/bt/controller/esp32/bt.c

@@ -512,7 +512,7 @@ static xt_handler set_isr_hlevel_wrapper(int mask, xt_handler f, void *arg)
 static void IRAM_ATTR interrupt_hlevel_disable(void)
 {
     assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE);
-    assert(hli_cb.nested != ~0);
+    assert(hli_cb.nested != UCHAR_MAX);
     uint32_t status = hli_intr_disable();
     if (hli_cb.nested++ == 0) {
         hli_cb.status = status;

+ 1 - 1
components/bt/host/bluedroid/api/esp_gap_ble_api.c

@@ -550,7 +550,7 @@ esp_err_t esp_ble_gap_set_security_param(esp_ble_sm_param_t param_type,
     if((param_type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY) && ( value == NULL || len < sizeof(uint8_t) || len > sizeof(uint32_t))) {
         return ESP_ERR_INVALID_ARG;
     }
-    if((param_type == ESP_BLE_SM_SET_STATIC_PASSKEY)) {
+    if(param_type == ESP_BLE_SM_SET_STATIC_PASSKEY) {
         uint32_t passkey = 0;
         for(uint8_t i = 0; i < len; i++)
         {

+ 4 - 4
components/bt/host/bluedroid/stack/btm/btm_devctl.c

@@ -898,14 +898,14 @@ tBTM_STATUS BTM_EnableTestMode(void)
     }
 
     /* put device to connectable mode */
-    if (!BTM_SetConnectability(BTM_CONNECTABLE, BTM_DEFAULT_CONN_WINDOW,
-                               BTM_DEFAULT_CONN_INTERVAL) == BTM_SUCCESS) {
+    if (BTM_SetConnectability(BTM_CONNECTABLE, BTM_DEFAULT_CONN_WINDOW,
+                               BTM_DEFAULT_CONN_INTERVAL) != BTM_SUCCESS) {
         return BTM_NO_RESOURCES;
     }
 
     /* put device to discoverable mode */
-    if (!BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE, BTM_DEFAULT_DISC_WINDOW,
-                                BTM_DEFAULT_DISC_INTERVAL) == BTM_SUCCESS) {
+    if (BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE, BTM_DEFAULT_DISC_WINDOW,
+                                BTM_DEFAULT_DISC_INTERVAL) != BTM_SUCCESS) {
         return BTM_NO_RESOURCES;
     }
 

+ 12 - 2
components/cxx/CMakeLists.txt

@@ -40,7 +40,13 @@ if(NOT CONFIG_CXX_EXCEPTIONS)
     endforeach()
 endif()
 
-target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc)
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+    # libstdc++ depends on C library, so it should appear later in link order.
+    # Otherwise we get undefined references for esp-clang toolchain.
+    target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ c gcc)
+else()
+    target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc)
+endif()
 target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy")
 
 # Force libpthread to appear later than libstdc++ in link line since libstdc++ depends on libpthread.
@@ -50,7 +56,11 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy")
 idf_component_get_property(pthread pthread COMPONENT_LIB)
 idf_component_get_property(cxx cxx COMPONENT_LIB)
 add_library(stdcpp_pthread INTERFACE)
-target_link_libraries(stdcpp_pthread INTERFACE stdc++ $<TARGET_FILE:${pthread}>)
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+    target_link_libraries(stdcpp_pthread INTERFACE stdc++ c $<TARGET_FILE:${pthread}>)
+else()
+    target_link_libraries(stdcpp_pthread INTERFACE stdc++ $<TARGET_FILE:${pthread}>)
+endif()
 target_link_libraries(${COMPONENT_LIB} PUBLIC stdcpp_pthread)
 add_library(libgcc_cxx INTERFACE)
 target_link_libraries(libgcc_cxx INTERFACE gcc $<TARGET_FILE:${cxx}>)

+ 4 - 4
components/cxx/cxx_guards.cpp

@@ -26,8 +26,8 @@ static size_t s_static_init_max_waiting_count = 0;          //!< maximum ever va
 #endif
 
 extern "C" int __cxa_guard_acquire(__guard* pg);
-extern "C" void __cxa_guard_release(__guard* pg);
-extern "C" void __cxa_guard_abort(__guard* pg);
+extern "C" void __cxa_guard_release(__guard* pg) throw();
+extern "C" void __cxa_guard_abort(__guard* pg) throw();
 extern "C" void __cxa_guard_dummy(void);
 
 /**
@@ -167,7 +167,7 @@ extern "C" int __cxa_guard_acquire(__guard* pg)
     return ret;
 }
 
-extern "C" void __cxa_guard_release(__guard* pg)
+extern "C" void __cxa_guard_release(__guard* pg) throw()
 {
     guard_t* g = reinterpret_cast<guard_t*>(pg);
     const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;
@@ -189,7 +189,7 @@ extern "C" void __cxa_guard_release(__guard* pg)
     }
 }
 
-extern "C" void __cxa_guard_abort(__guard* pg)
+extern "C" void __cxa_guard_abort(__guard* pg) throw()
 {
     guard_t* g = reinterpret_cast<guard_t*>(pg);
     const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;

+ 3 - 2
components/driver/test_apps/components/esp_serial_slave_link/essl_spi.c

@@ -267,8 +267,9 @@ static esp_err_t essl_spi_update_tx_buffer_num(void *arg, uint32_t wait_ms);
 esp_err_t essl_spi_init_dev(essl_handle_t *out_handle, const essl_spi_config_t *init_config)
 {
     ESP_RETURN_ON_FALSE(init_config->spi, ESP_ERR_INVALID_STATE, TAG, "Check SPI initialization first");
-    ESP_RETURN_ON_FALSE(init_config->tx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, ESP_ERR_INVALID_ARG, TAG, "GPSPI supports %d-byte-width internal registers", SOC_SPI_MAXIMUM_BUFFER_SIZE);
-    ESP_RETURN_ON_FALSE(init_config->rx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, ESP_ERR_INVALID_ARG, TAG, "GPSPI supports %d-byte-width internal registers", SOC_SPI_MAXIMUM_BUFFER_SIZE);
+    // for esp32-s2 SOC_SPI_MAXIMUM_BUFFER_SIZE is 72, so compiler warns that comparisons of 'tx/rx_sync_reg' are always true
+    ESP_RETURN_ON_FALSE((uint32_t)init_config->tx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, ESP_ERR_INVALID_ARG, TAG, "GPSPI supports %d-byte-width internal registers", SOC_SPI_MAXIMUM_BUFFER_SIZE);
+    ESP_RETURN_ON_FALSE((uint32_t)init_config->rx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, ESP_ERR_INVALID_ARG, TAG, "GPSPI supports %d-byte-width internal registers", SOC_SPI_MAXIMUM_BUFFER_SIZE);
     ESP_RETURN_ON_FALSE(init_config->tx_sync_reg != init_config->rx_sync_reg, ESP_ERR_INVALID_ARG, TAG, "Should use different word of registers for synchronization");
 
     essl_spi_context_t *context = calloc(1, sizeof(essl_spi_context_t));

+ 4 - 0
components/efuse/esp32c2/esp_efuse_utility.c

@@ -102,7 +102,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 uint8_t block_rs[12];
                 efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                 memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
 #pragma GCC diagnostic pop
@@ -148,7 +150,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 if (!correct_written_data || coding_error_occurred) {
                     ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                     memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
 #pragma GCC diagnostic pop

+ 4 - 0
components/efuse/esp32c3/esp_efuse_utility.c

@@ -131,7 +131,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 uint8_t block_rs[12];
                 efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                 memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
 #pragma GCC diagnostic pop
@@ -177,7 +179,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 if (!correct_written_data || coding_error_occurred) {
                     ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                     memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
 #pragma GCC diagnostic pop

+ 4 - 0
components/efuse/esp32c6/esp_efuse_utility.c

@@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 uint8_t block_rs[12];
                 efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                 memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
 #pragma GCC diagnostic pop
@@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 if (!correct_written_data || coding_error_occurred) {
                     ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                     memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
 #pragma GCC diagnostic pop

+ 4 - 0
components/efuse/esp32h4/esp_efuse_utility.c

@@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 uint8_t block_rs[12];
                 efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                 memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
 #pragma GCC diagnostic pop
@@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 if (!correct_written_data || coding_error_occurred) {
                     ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                     memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
 #pragma GCC diagnostic pop

+ 4 - 0
components/efuse/esp32s2/esp_efuse_utility.c

@@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 uint8_t block_rs[12];
                 efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                 memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
 #pragma GCC diagnostic pop
@@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 if (!correct_written_data || coding_error_occurred) {
                     ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                     memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
 #pragma GCC diagnostic pop

+ 4 - 0
components/efuse/esp32s3/esp_efuse_utility.c

@@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 uint8_t block_rs[12];
                 efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                 memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
 #pragma GCC diagnostic pop
@@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
                 if (!correct_written_data || coding_error_occurred) {
                     ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
 #pragma GCC diagnostic push
+#ifndef __clang__
 #pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif
 #pragma GCC diagnostic ignored "-Warray-bounds"
                     memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
 #pragma GCC diagnostic pop

+ 1 - 1
components/esp_system/port/arch/xtensa/panic_arch.c

@@ -261,7 +261,7 @@ static inline void print_cache_err_details(const void *f)
 static inline void print_memprot_err_details(const void *f)
 {
     uint32_t *fault_addr;
-    uint32_t op_type, op_subtype;
+    uint32_t op_type = MEMPROT_OP_INVALID, op_subtype;
     const char *operation_type;
 
     mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();

+ 12 - 0
components/freertos/FreeRTOS-Kernel/portable/riscv/port.c

@@ -205,6 +205,17 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u
  */
 static void __attribute__((optimize("O1"), naked)) vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters)
 {
+#ifdef __clang__
+    // clang generates error "error: non-ASM statement in naked function is not supported"
+    // The reason for it is described at
+    // https://stackoverflow.com/questions/47316611/clang-error-non-asm-statement-in-naked-function-is-not-supported.
+    // GCC docs say that there is no guarantee that non-ASM statement in naked function will work:
+    // "Only basic asm statements can safely be included in naked functions (see Basic Asm).
+    //  While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be
+    //  depended upon to work reliably and are not supported."
+    // TODO: IDF-6347
+    #error CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER not supported yet when building with Clang!
+#else
     asm volatile(".cfi_undefined ra\n");
     extern void __attribute__((noreturn)) panic_abort(const char *details);
     static char DRAM_ATTR msg[80] = "FreeRTOS: FreeRTOS Task \"\0";
@@ -215,6 +226,7 @@ static void __attribute__((optimize("O1"), naked)) vPortTaskWrapper(TaskFunction
     strcat(msg, pcTaskName);
     strcat(msg, "\" should not return, Aborting now!");
     panic_abort(msg);
+#endif
 }
 #endif // CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
 

+ 1 - 1
components/mbedtls/port/sha/dma/sha.c

@@ -268,7 +268,7 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
         }
 
         ilen -= dma_chunk_len;
-        input += dma_chunk_len;
+        input = (uint8_t *)input + dma_chunk_len;
 
         // Only append buf to the first operation
         buf_len = 0;

+ 5 - 3
components/riscv/project_include.cmake

@@ -1,3 +1,5 @@
-set(compile_options "-nostartfiles")
-
-idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
+# avoid esp-clang "unused-command-line-argument" warning
+if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang") )
+    set(compile_options "-nostartfiles")
+    idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
+endif()

+ 0 - 1
components/sdmmc/sdmmc_io.c

@@ -429,7 +429,6 @@ static esp_err_t cis_tuple_func_manfid(const void* p, uint8_t* data, FILE* fp)
 static esp_err_t cis_tuple_func_end(const void* p, uint8_t* data, FILE* fp)
 {
     const cis_tuple_t* tuple = (const cis_tuple_t*)p;
-    data++;
     fprintf(fp, "TUPLE: %s\n", tuple->name);
     return ESP_OK;
 }

+ 6 - 2
components/spi_flash/spi_flash_hpm_enable.c

@@ -59,12 +59,14 @@ extern uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigne
 static esp_err_t spi_flash_hpm_probe_chip_with_cmd(uint32_t flash_id)
 {
     esp_err_t ret = ESP_OK;
+    uint32_t gd_sfdp;
+
     switch (flash_id) {
     /* The flash listed here should enter the HPM with command 0xA3 */
     case 0xC84016:
     case 0xC84017:
         // Read BYTE4 in SFDP, 0 means C series, 6 means E series
-        uint32_t gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
+        gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
         if (gd_sfdp == 0x0) {
             break;
         } else {
@@ -125,6 +127,8 @@ static esp_err_t spi_flash_high_performance_check_hpf_bit_5(void)
 static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id)
 {
     esp_err_t ret = ESP_OK;
+    uint32_t gd_sfdp;
+
     switch (flash_id) {
     /* The flash listed here should enter the HPM by adjusting dummy cycles */
     // XMC chips.
@@ -135,7 +139,7 @@ static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id)
     case 0xC84017:
     case 0xC84018:
         // Read BYTE4 in SFDP, 0 means C series, 6 means E series
-        uint32_t gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
+        gd_sfdp = bootloader_flash_read_sfdp(0x4, 1);
         if (gd_sfdp == 0x6) {
             break;
         } else {

+ 3 - 3
components/touch_element/touch_element.c

@@ -608,7 +608,7 @@ esp_err_t te_dev_set_threshold(te_dev_t *device)
         smo_val = te_read_smooth_signal(device->channel);
         ret = te_config_thresh(device->channel, device->sens * smo_val);
     }
-    ESP_LOGD(TE_DEBUG_TAG, "channel: %"PRIu8", smo_val: %"PRIu32, device->channel, smo_val);
+    ESP_LOGD(TE_DEBUG_TAG, "channel: %"PRIu8", smo_val: %"PRIu32, (uint8_t)device->channel, smo_val);
     return ret;
 }
 
@@ -906,14 +906,14 @@ static bool waterproof_channel_check(touch_pad_t channel_num)
     if (waterproof_shield_check_state()) {
         if (channel_num == waterproof_handle->shield_channel) {
             ESP_LOGE(TE_TAG, "TOUCH_PAD_NUM%"PRIu8" has been used for waterproof shield channel,"
-                     " please change the touch sensor channel or disable waterproof", channel_num);
+                     " please change the touch sensor channel or disable waterproof", (uint8_t)channel_num);
             return true;
         }
     }
     if (waterproof_guard_check_state()) {
         if (channel_num == waterproof_handle->guard_device->channel) {
             ESP_LOGE(TE_TAG, "TOUCH_PAD_NUM%"PRIu8" has been used for waterproof guard channel,"
-                     " please change the touch sensor channel or disable waterproof", channel_num);
+                     " please change the touch sensor channel or disable waterproof", (uint8_t)channel_num);
             return true;
         }
     }

+ 1 - 1
components/wpa_supplicant/src/rsn_supp/wpa.c

@@ -1643,7 +1643,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm,
     if (wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
         goto failed;
 
-    if ((WPA_SM_STATE(sm) == WPA_COMPLETED)) {
+    if (WPA_SM_STATE(sm) == WPA_COMPLETED) {
 #ifdef MSG_PRINT
         wpa_printf(MSG_DEBUG, "WPA: Group rekeying "
             "completed with " MACSTR " [GTK=%s]",

+ 8 - 1
components/xtensa/include/xtensa/core-macros.h

@@ -337,9 +337,16 @@
 # define XTHAL_GET_INTERRUPT()	({ int __interrupt; \
 				__asm__ __volatile__("rsr.interrupt %0" : "=a"(__interrupt)); \
 				__interrupt; })
+#ifdef __clang__
+// TODO: LLVM-195. Currently clang does not support INTSET alias for INTERRUPT special reg
+# define XTHAL_SET_INTSET(v)	do { int __interrupt = (int)(v); \
+			__asm__ __volatile__("wsr.interrupt %0" :: "a"(__interrupt):"memory"); \
+				} while(0)
+#else
 # define XTHAL_SET_INTSET(v)	do { int __interrupt = (int)(v); \
 			__asm__ __volatile__("wsr.intset %0" :: "a"(__interrupt):"memory"); \
 				} while(0)
+#endif
 # define XTHAL_SET_INTCLEAR(v)	do { int __interrupt = (int)(v); \
 			__asm__ __volatile__("wsr.intclear %0" :: "a"(__interrupt):"memory"); \
 				} while(0)
@@ -433,7 +440,7 @@ static inline unsigned  XTHAL_COMPARE_AND_SET( int *addr, int testval, int setva
 	    : "=a"(result) : "0" (setval), "a" (testval), "a" (addr)
 	    : "memory");
 #elif XCHAL_HAVE_INTERRUPTS
-    int tmp;
+    int tmp = 0; // clang complains on unitialized var
     __asm__ __volatile__ (
         "   rsil   %4, 15 \n"		// %4 == saved ps
         "   l32i   %0, %3, 0 \n"	// %0 == value to test, return val

+ 16 - 1
components/xtensa/project_include.cmake

@@ -1,5 +1,20 @@
 # Check toolchain is configured properly in cmake
-if(NOT ( ${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${CMAKE_C_COMPILER} MATCHES xtensa))
+if(CMAKE_C_COMPILER_ID MATCHES "Clang")
+    # without '--target' option 'clang -dumpmachine' prints default target arch and it might be not Xtensa
+    # so use `-print-targets` option
+    execute_process(
+        COMMAND ${CMAKE_C_COMPILER} -print-targets
+        OUTPUT_VARIABLE dump_machine
+    )
+else()
+    execute_process(
+        COMMAND ${CMAKE_C_COMPILER} -dumpmachine
+        OUTPUT_VARIABLE dump_machine
+    )
+endif()
+message("Compiler supported targets: ${dump_machine}")
+
+if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${dump_machine} MATCHES xtensa))
     message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project "
         "(or an invalid CMakeCache.txt file has been generated somehow)")
 endif()

+ 1 - 1
docs/en/api-guides/tools/idf-clang-tidy.rst

@@ -21,7 +21,7 @@ If you have never run this tool before, take the following steps to get this too
 
 #. Run the export scripts (``export.sh`` / ``export.bat`` / ... ) to set up the environment variables.
 #. Run ``pip install --upgrade pyclang`` to install this plugin. The extra commands would be activated in ``idf.py`` automatically.
-#. Run ``idf_tools.py install xtensa-clang`` to install the clang-tidy required binaries
+#. Run ``idf_tools.py install esp-clang`` to install the clang-tidy required binaries
 
    .. note::
 

+ 1 - 1
docs/en/api-guides/tools/idf-tools-notes.inc

@@ -48,7 +48,7 @@ On Linux and macOS, it is recommended to install CMake using the OS-specific pac
 
 ---
 
-.. tool-xtensa-clang-notes
+.. tool-esp-clang-notes
 
 
 ---

+ 1 - 1
docs/zh_CN/api-guides/tools/idf-tools-notes.inc

@@ -50,7 +50,7 @@ On Linux and macOS, it is recommended to install CMake using the OS package mana
 
 ---
 
-.. tool-xtensa-clang-notes
+.. tool-esp-clang-notes
 
 
 ---

+ 7 - 2
tools/ci/configure_ci_environment.sh

@@ -16,8 +16,13 @@ DEBUG_SHELL=${DEBUG_SHELL:-"0"}
 # Compiler flags to thoroughly check the IDF code in some CI jobs
 # (Depends on default options '-Wno-error=XXX' used in the IDF build system)
 
-PEDANTIC_FLAGS="-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function"
-export PEDANTIC_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes"
+if [ "$IDF_TOOLCHAIN" != "clang" ]; then
+    PEDANTIC_FLAGS="-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function"
+    export PEDANTIC_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes"
+else
+    export PEDANTIC_CFLAGS="-Werror"
+fi
+
 export PEDANTIC_CXXFLAGS="${PEDANTIC_FLAGS}"
 
 # ccache related settings.

+ 1 - 0
tools/cmake/build.cmake

@@ -102,6 +102,7 @@ function(__build_set_default_build_specifications)
                                     "-Werror=all"
                                     "-Wno-error=unused-function"
                                     "-Wno-error=unused-variable"
+                                    "-Wno-error=unused-but-set-variable"
                                     "-Wno-error=deprecated-declarations"
                                     "-Wextra"
                                     "-Wno-unused-parameter"

+ 7 - 8
tools/cmake/toolchain-clang-esp32.cmake

@@ -6,26 +6,25 @@ set(CMAKE_C_COMPILER clang)
 set(CMAKE_CXX_COMPILER clang++)
 set(CMAKE_ASM_COMPILER clang)
 
-set(CMAKE_AR xtensa-esp32-elf-ar)
-set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib)
+set(CMAKE_AR llvm-ar)
+set(CMAKE_RANLIB llvm-ranlib)
 set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump)
 
-# -freestanding is a hack to force Clang to use its own stdatomic.h,
-# without falling back to the (incompatible) GCC stdatomic.h
-# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18
-remove_duplicated_flags("--target=xtensa -mcpu=esp32 -ffreestanding ${CMAKE_C_FLAGS}"
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32 ${CMAKE_C_FLAGS}"
                         UNIQ_CMAKE_C_FLAGS)
 set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
     CACHE STRING "C Compiler Base Flags"
     FORCE)
 
-remove_duplicated_flags("--target=xtensa -mcpu=esp32 -ffreestanding ${CMAKE_CXX_FLAGS}"
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32 \
+                        ${CMAKE_CXX_FLAGS}"
                         UNIQ_CMAKE_CXX_FLAGS)
 set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
     CACHE STRING "C++ Compiler Base Flags"
     FORCE)
 
-remove_duplicated_flags("--target=xtensa -mcpu=esp32 ${CMAKE_ASM_FLAGS}" UNIQ_CMAKE_ASM_FLAGS)
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32 ${CMAKE_ASM_FLAGS}"
+                        UNIQ_CMAKE_ASM_FLAGS)
 set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
     CACHE STRING "Assembler Base Flags"
     FORCE)

+ 32 - 0
tools/cmake/toolchain-clang-esp32c2.cmake

@@ -0,0 +1,32 @@
+include($ENV{IDF_PATH}/tools/cmake/utilities.cmake)
+
+set(CMAKE_SYSTEM_NAME Generic)
+
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_CXX_COMPILER clang++)
+set(CMAKE_ASM_COMPILER clang)
+
+set(CMAKE_AR llvm-ar)
+set(CMAKE_RANLIB llvm-ranlib)
+set(CMAKE_OBJDUMP riscv32-esp-elf-objdump)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_C_FLAGS}"
+                        UNIQ_CMAKE_C_FLAGS)
+set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
+    CACHE STRING "C Compiler Base Flags"
+    FORCE)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_CXX_FLAGS}"
+                        UNIQ_CMAKE_CXX_FLAGS)
+set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
+    CACHE STRING "C++ Compiler Base Flags"
+    FORCE)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_ASM_FLAGS}"
+                        UNIQ_CMAKE_ASM_FLAGS)
+set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
+    CACHE STRING "Assembler Base Flags"
+    FORCE)

+ 32 - 0
tools/cmake/toolchain-clang-esp32c3.cmake

@@ -0,0 +1,32 @@
+include($ENV{IDF_PATH}/tools/cmake/utilities.cmake)
+
+set(CMAKE_SYSTEM_NAME Generic)
+
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_CXX_COMPILER clang++)
+set(CMAKE_ASM_COMPILER clang)
+
+set(CMAKE_AR llvm-ar)
+set(CMAKE_RANLIB llvm-ranlib)
+set(CMAKE_OBJDUMP riscv32-esp-elf-objdump)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_C_FLAGS}"
+                        UNIQ_CMAKE_C_FLAGS)
+set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
+    CACHE STRING "C Compiler Base Flags"
+    FORCE)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_CXX_FLAGS}"
+                        UNIQ_CMAKE_CXX_FLAGS)
+set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
+    CACHE STRING "C++ Compiler Base Flags"
+    FORCE)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_ASM_FLAGS}"
+                        UNIQ_CMAKE_ASM_FLAGS)
+set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
+    CACHE STRING "Assembler Base Flags"
+    FORCE)

+ 32 - 0
tools/cmake/toolchain-clang-esp32c6.cmake

@@ -0,0 +1,32 @@
+include($ENV{IDF_PATH}/tools/cmake/utilities.cmake)
+
+set(CMAKE_SYSTEM_NAME Generic)
+
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_CXX_COMPILER clang++)
+set(CMAKE_ASM_COMPILER clang)
+
+set(CMAKE_AR llvm-ar)
+set(CMAKE_RANLIB llvm-ranlib)
+set(CMAKE_OBJDUMP riscv32-esp-elf-objdump)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imac -mabi=ilp32 \
+                        ${CMAKE_C_FLAGS}"
+                        UNIQ_CMAKE_C_FLAGS)
+set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
+    CACHE STRING "C Compiler Base Flags"
+    FORCE)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imac -mabi=ilp32 \
+                        ${CMAKE_CXX_FLAGS}"
+                        UNIQ_CMAKE_CXX_FLAGS)
+set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
+    CACHE STRING "C++ Compiler Base Flags"
+    FORCE)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imac -mabi=ilp32 \
+                        ${CMAKE_ASM_FLAGS}"
+                        UNIQ_CMAKE_ASM_FLAGS)
+set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
+    CACHE STRING "Assembler Base Flags"
+    FORCE)

+ 32 - 0
tools/cmake/toolchain-clang-esp32h2.cmake

@@ -0,0 +1,32 @@
+include($ENV{IDF_PATH}/tools/cmake/utilities.cmake)
+
+set(CMAKE_SYSTEM_NAME Generic)
+
+set(CMAKE_C_COMPILER clang)
+set(CMAKE_CXX_COMPILER clang++)
+set(CMAKE_ASM_COMPILER clang)
+
+set(CMAKE_AR llvm-ar)
+set(CMAKE_RANLIB llvm-ranlib)
+set(CMAKE_OBJDUMP riscv32-esp-elf-objdump)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_C_FLAGS}"
+                        UNIQ_CMAKE_C_FLAGS)
+set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
+    CACHE STRING "C Compiler Base Flags"
+    FORCE)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_CXX_FLAGS}"
+                        UNIQ_CMAKE_CXX_FLAGS)
+set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
+    CACHE STRING "C++ Compiler Base Flags"
+    FORCE)
+
+remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \
+                        ${CMAKE_ASM_FLAGS}"
+                        UNIQ_CMAKE_ASM_FLAGS)
+set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
+    CACHE STRING "Assembler Base Flags"
+    FORCE)

+ 8 - 9
tools/cmake/toolchain-clang-esp32s2.cmake

@@ -6,26 +6,25 @@ set(CMAKE_C_COMPILER clang)
 set(CMAKE_CXX_COMPILER clang++)
 set(CMAKE_ASM_COMPILER clang)
 
-set(CMAKE_AR xtensa-esp32-elf-ar)
-set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib)
-set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump)
 
-# -freestanding is a hack to force Clang to use its own stdatomic.h,
-# without falling back to the (incompatible) GCC stdatomic.h
-# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18
-remove_duplicated_flags("--target=xtensa -mcpu=esp32s2 -ffreestanding ${CMAKE_C_FLAGS}"
+set(CMAKE_AR llvm-ar)
+set(CMAKE_RANLIB llvm-ranlib)
+set(CMAKE_OBJDUMP xtensa-esp32s2-elf-objdump)
+
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s2 ${CMAKE_C_FLAGS}"
                         UNIQ_CMAKE_C_FLAGS)
 set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
     CACHE STRING "C Compiler Base Flags"
     FORCE)
 
-remove_duplicated_flags("--target=xtensa -mcpu=esp32s2 -ffreestanding ${CMAKE_CXX_FLAGS}"
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s2 \
+                        ${CMAKE_CXX_FLAGS}"
                         UNIQ_CMAKE_CXX_FLAGS)
 set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
     CACHE STRING "C++ Compiler Base Flags"
     FORCE)
 
-remove_duplicated_flags("--target=xtensa -mcpu=esp32s2 ${CMAKE_ASM_FLAGS}"
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s2 ${CMAKE_ASM_FLAGS}"
                         UNIQ_CMAKE_ASM_FLAGS)
 set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
     CACHE STRING "Assembler Base Flags"

+ 7 - 9
tools/cmake/toolchain-clang-esp32s3.cmake

@@ -6,26 +6,24 @@ set(CMAKE_C_COMPILER clang)
 set(CMAKE_CXX_COMPILER clang++)
 set(CMAKE_ASM_COMPILER clang)
 
-set(CMAKE_AR xtensa-esp32-elf-ar)
-set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib)
-set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump)
+set(CMAKE_AR llvm-ar)
+set(CMAKE_RANLIB llvm-ranlib)
+set(CMAKE_OBJDUMP xtensa-esp32s3-elf-objdump)
 
-# -freestanding is a hack to force Clang to use its own stdatomic.h,
-# without falling back to the (incompatible) GCC stdatomic.h
-# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18
-remove_duplicated_flags("--target=xtensa -mcpu=esp32s3 -ffreestanding ${CMAKE_C_FLAGS}"
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s3 ${CMAKE_C_FLAGS}"
                         UNIQ_CMAKE_C_FLAGS)
 set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
     CACHE STRING "C Compiler Base Flags"
     FORCE)
 
-remove_duplicated_flags("--target=xtensa -mcpu=esp32s3 -ffreestanding ${CMAKE_CXX_FLAGS}"
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s3 \
+                        ${CMAKE_CXX_FLAGS}"
                         UNIQ_CMAKE_CXX_FLAGS)
 set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
     CACHE STRING "C++ Compiler Base Flags"
     FORCE)
 
-remove_duplicated_flags("--target=xtensa -mcpu=esp32s3 ${CMAKE_ASM_FLAGS}"
+remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s3 ${CMAKE_ASM_FLAGS}"
                         UNIQ_CMAKE_ASM_FLAGS)
 set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
     CACHE STRING "Assembler Base Flags"

+ 6 - 0
tools/test_apps/.build-test-rules.yml

@@ -95,6 +95,12 @@ tools/test_apps/system/cxx_no_except:
       temporary: true
       reason: the other targets are not tested yet
 
+tools/test_apps/system/cxx_pthread_bluetooth:
+  enable:
+    - if: IDF_TARGET in ["esp32", "esp32c2", "esp32c3", "esp32s2", "esp32s3"]
+      temporary: true
+      reason: the other targets are not supported yet
+
 tools/test_apps/system/eh_frame:
   enable:
     - if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32h4"]

+ 6 - 0
tools/test_apps/system/cxx_pthread_bluetooth/CMakeLists.txt

@@ -0,0 +1,6 @@
+# The following lines of boilerplate have to be in your project's CMakeLists
+# in this exact order for cmake to work correctly
+cmake_minimum_required(VERSION 3.16)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+project(cpp_pthread)

+ 51 - 0
tools/test_apps/system/cxx_pthread_bluetooth/README.md

@@ -0,0 +1,51 @@
+| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
+| ----------------- | ----- | -------- | -------- | -------- | -------- |
+
+# C++ pthread Example
+
+(See the README.md file in the upper level 'examples' directory for more information about examples.)
+
+Support for the [C++ threads](http://www.cplusplus.com/reference/thread/thread/) in ESP-IDF is implemented on top of the [ESP-pthread](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/esp_pthread.html#overview) component. Thus, C++ threads created using the standard thread class constructor will automatically inherit the current ESP-pthread configuration. This example demonstrates how to leverage the thread configuration functions provided by ESP-pthread (e.g., `esp_pthread_get_default_config()` and `esp_pthread_set_cfg()`) to modify the stack sizes, priorities, names, and core affinities of the C++ threads.
+
+**Note: Due to the use of the C++ threads, this example is written in C++ instead of C.**
+
+## How to use example
+
+### Hardware Required
+
+This example should be able to run on any commonly available ESP32 development board.
+
+### Configure the project
+
+```
+idf.py menuconfig
+```
+
+* The default ESP-pthread configuration may also be modified under `Component config > PThreads`
+
+### Build and Flash
+
+Build the project and flash it to the board, then run monitor tool to view serial output:
+
+```
+idf.py -p PORT flash monitor
+```
+
+(Replace PORT with the name of the serial port to use.)
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
+
+## Example Output
+
+The following log output should appear when the example runs (note that the bootloader log has been omitted).
+
+```
+...
+I (380) Thread 1: Core id: 0, prio: 5, minimum free stack: 2068 bytes.
+I (0) pthread: This thread (with the default name) may run on any core.Core id: 1, prio: 5, minimum free stack: 2056 bytes.
+I (390) Thread 1: This is the INHERITING thread with the same parameters as our parent, including name. Core id: 0, prio: 5, minimum free stack: 2092 bytes.
+I (410) Thread 2: Core id: 1, prio: 5, minimum free stack: 2088 bytes.
+I (410) main: core id: 0, prio: 1, minimum free stack: 2928 bytes.
+```

+ 2 - 0
tools/test_apps/system/cxx_pthread_bluetooth/main/CMakeLists.txt

@@ -0,0 +1,2 @@
+idf_component_register(SRCS "cpp_pthread.cpp"
+                    INCLUDE_DIRS ".")

+ 108 - 0
tools/test_apps/system/cxx_pthread_bluetooth/main/cpp_pthread.cpp

@@ -0,0 +1,108 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+#include <iostream>
+#include <thread>
+#include <chrono>
+#include <memory>
+#include <string>
+#include <sstream>
+#include <esp_pthread.h>
+#include <freertos/FreeRTOS.h>
+#include <freertos/task.h>
+#include <esp_log.h>
+
+using namespace std::chrono;
+
+const auto sleep_time = seconds
+{
+    5
+};
+
+void print_thread_info(const char *extra = nullptr)
+{
+    std::stringstream ss;
+    if (extra) {
+        ss << extra;
+    }
+    ss << "Core id: " << xPortGetCoreID()
+       << ", prio: " << uxTaskPriorityGet(nullptr)
+       << ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
+    ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str());
+}
+
+void thread_func_inherited()
+{
+    while (true) {
+        print_thread_info("This is the INHERITING thread with the same parameters as our parent, including name. ");
+        std::this_thread::sleep_for(sleep_time);
+    }
+}
+
+void spawn_another_thread()
+{
+    // Create a new thread, it will inherit our configuration
+    std::thread inherits(thread_func_inherited);
+
+    while (true) {
+        print_thread_info();
+        std::this_thread::sleep_for(sleep_time);
+    }
+}
+
+void thread_func_any_core()
+{
+    while (true) {
+        print_thread_info("This thread (with the default name) may run on any core.");
+        std::this_thread::sleep_for(sleep_time);
+    }
+}
+
+void thread_func()
+{
+    while (true) {
+        print_thread_info();
+        std::this_thread::sleep_for(sleep_time);
+    }
+}
+
+esp_pthread_cfg_t create_config(const char *name, int core_id, int stack, int prio)
+{
+    auto cfg = esp_pthread_get_default_config();
+    cfg.thread_name = name;
+    cfg.pin_to_core = core_id;
+    cfg.stack_size = stack;
+    cfg.prio = prio;
+    return cfg;
+}
+
+extern "C" void app_main(void)
+{
+    // Create a thread using deafult values that can run on any core
+    auto cfg = esp_pthread_get_default_config();
+    esp_pthread_set_cfg(&cfg);
+    std::thread any_core(thread_func_any_core);
+
+    // Create a thread on core 0 that spawns another thread, they will both have the same name etc.
+    cfg = create_config("Thread 1", 0, 3 * 1024, 5);
+    cfg.inherit_cfg = true;
+    esp_pthread_set_cfg(&cfg);
+    std::thread thread_1(spawn_another_thread);
+
+    // Create a thread on core 1.
+    cfg = create_config("Thread 2", 1, 3 * 1024, 5);
+    esp_pthread_set_cfg(&cfg);
+    std::thread thread_2(thread_func);
+
+    // Let the main task do something too
+    while (true) {
+        std::stringstream ss;
+        ss << "core id: " << xPortGetCoreID()
+           << ", prio: " << uxTaskPriorityGet(nullptr)
+           << ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
+        ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str());
+        std::this_thread::sleep_for(sleep_time);
+    }
+}

+ 3 - 0
tools/test_apps/system/cxx_pthread_bluetooth/sdkconfig.defaults

@@ -0,0 +1,3 @@
+CONFIG_PARTITION_TABLE_OFFSET=0x9000
+CONFIG_BT_ENABLED=y
+CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=n

+ 32 - 17
tools/tools.json

@@ -371,10 +371,10 @@
       ]
     },
     {
-      "description": "LLVM for Xtensa (ESP32, ESP32-S2) based on clang",
+      "description": "Toolchain for all Espressif chips based on clang",
       "export_paths": [
         [
-          "xtensa-esp32-elf-clang",
+          "esp-clang",
           "bin"
         ]
       ],
@@ -382,10 +382,15 @@
       "info_url": "https://github.com/espressif/llvm-project",
       "install": "on_request",
       "license": "Apache-2.0",
-      "name": "xtensa-clang",
+      "name": "esp-clang",
       "supported_targets": [
         "esp32",
-        "esp32s2"
+        "esp32s2",
+        "esp32s3",
+        "esp32c3",
+        "esp32h4",
+        "esp32c2",
+        "esp32c6"
       ],
       "version_cmd": [
         "clang",
@@ -396,26 +401,36 @@
       "versions": [
         {
           "linux-amd64": {
-            "sha256": "b0148627912dacf4a4cab4596ba9467cb8dd771522ca27b9526bc57b88ff366f",
-            "size": 125101504,
-            "url": "https://github.com/espressif/llvm-project/releases/download/esp-14.0.0-20220415/xtensa-esp32-elf-llvm14_0_0-esp-14.0.0-20220415-linux-amd64.tar.xz"
+            "sha256": "30379631cc1cdf6526940494964371a90aa7a940c4ff7333d9ffab35e6c0f978",
+            "size": 198800680,
+            "url": "https://github.com/espressif/llvm-project/releases/download/esp-15.0.0-20221014/llvm-esp-15.0.0-20221014-linux-amd64.tar.xz"
+          },
+          "linux-arm64": {
+            "sha256": "c40c1c1d7ee94fc5967641aaffcbca263018b2df4f1d4249636c1adff0e35542",
+            "size": 204969304,
+            "url": "https://github.com/espressif/llvm-project/releases/download/esp-15.0.0-20221014/llvm-esp-15.0.0-20221014-linux-arm64.tar.xz"
+          },
+          "linux-armhf": {
+            "sha256": "3931c81cdaa44a47739663b647e68778d3ed9532d67096618d6901ae3adfb3c1",
+            "size": 196967420,
+            "url": "https://github.com/espressif/llvm-project/releases/download/esp-15.0.0-20221014/llvm-esp-15.0.0-20221014-linux-armhf.tar.xz"
           },
           "macos": {
-            "sha256": "1a78c598825ef168c0c5668aff7848825a7b9d014bffd1f2f2484ceea9df3841",
-            "size": 107100188,
-            "url": "https://github.com/espressif/llvm-project/releases/download/esp-14.0.0-20220415/xtensa-esp32-elf-llvm14_0_0-esp-14.0.0-20220415-macos.tar.xz"
+            "sha256": "e7066b1dd74cbd42c3e5d140013b0b357c190b5361a1c2fd92e29efa34305cff",
+            "size": 164130904,
+            "url": "https://github.com/espressif/llvm-project/releases/download/esp-15.0.0-20221014/llvm-esp-15.0.0-20221014-macos.tar.xz"
           },
           "macos-arm64": {
-            "sha256": "1a78c598825ef168c0c5668aff7848825a7b9d014bffd1f2f2484ceea9df3841",
-            "size": 107100188,
-            "url": "https://github.com/espressif/llvm-project/releases/download/esp-14.0.0-20220415/xtensa-esp32-elf-llvm14_0_0-esp-14.0.0-20220415-macos.tar.xz"
+            "sha256": "02b8af2bd934d4352da3743fc86c00d9258309d307c5af7f2be0cf85551535d3",
+            "size": 154036240,
+            "url": "https://github.com/espressif/llvm-project/releases/download/esp-15.0.0-20221014/llvm-esp-15.0.0-20221014-macos-arm64.tar.xz"
           },
-          "name": "14.0.0-38679f0333",
+          "name": "15.0.0-32e64117af",
           "status": "recommended",
           "win64": {
-            "sha256": "793e7bd9c40fcb9a4fababaaccf3e4c5b8d9554d406af1b1fbee51806bf8c5dd",
-            "size": 174294128,
-            "url": "https://github.com/espressif/llvm-project/releases/download/esp-14.0.0-20220415/xtensa-esp32-elf-llvm14_0_0-esp-14.0.0-20220415-win64.zip"
+            "sha256": "eba58ea6f9018c43748e938986f32c039a6dc49a384d994e9e515502b04c83f0",
+            "size": 230488412,
+            "url": "https://github.com/espressif/llvm-project/releases/download/esp-15.0.0-20221014/llvm-esp-15.0.0-20221014-win64.tar.xz"
           }
         }
       ]