Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC][libc++] Reworks clang-tidy selection. #81362

Merged
merged 2 commits into from
Mar 9, 2024

Conversation

mordante
Copy link
Member

@mordante mordante commented Feb 10, 2024

The current selection is done in the test scripts which gives the user no control where to find clang-tidy. The version selection itself is hard-coded and not based on the version of clang used.

This moves the selection to configuration time and tries to find a better match.

  • Mixing the version of clang-tidy and the clang libraries causes ODR violations. This results in practice in crashes or incorrect results.
  • Mixing the version of clang-tidy and the clang binary sometimes causes issues with supported diagnostic flags. For example, flags tested against clang 17 may not be available in clang-tidy 16.

Currently clang-tidy 18.1 can be used, it tests against the clang libraries version 18. This is caused by the new LLVM version numbering scheme.

The new selection tries to match the clang version or the version of the HEAD and the last 3 releases. (During the release period libc++ supports 4 versions instead of the typical 3 versions.)

libcxx/utils/libcxx/test/features.py Outdated Show resolved Hide resolved
cmake/Modules/LLVMVersion.cmake Outdated Show resolved Hide resolved
Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this! I have minor comments but let's ship this. We should separate the LLVM version setting out of this patch and it would be nice to remove LIBCXX_ENABLE_CLANG_TIDY as a follow-up too.

libcxx/test/tools/clang_tidy_checks/CMakeLists.txt Outdated Show resolved Hide resolved
libcxx/utils/libcxx/test/params.py Outdated Show resolved Hide resolved
libcxx/utils/libcxx/test/params.py Outdated Show resolved Hide resolved
The current selection is done in the test scipts which gives the user
no control where to find clang-tidy. The version selection itself is
hard-coded and not based on the version of clang used.

This moves the selection to configuration time and tries to find a better
match.
- Mixing the version of clang-tidy and the clang libraries causes ODR
  violations. This results in practice in crashes or incorrect results.
- Mixing the version of clang-tidy and the clang binaray sometimes causes
  issues with supported diagnotic flags. For example, flags tested against
  clang 17 may not be available in clang-tidy 16.

Currently clang-tidy 18.1 can be used, it tests against the clang
libraries version 18. This is a caused by the new LLVM version numbering
scheme.

The new selection tries to match the clang version or the version of the
HEAD and the last 3 releases. (During the release period libc++ supports 4
versions instead of the typical 3 versions.)
@mordante mordante force-pushed the users/mordante/clang-tidy_selection branch from 66e0331 to 1093af3 Compare March 9, 2024 11:32
@mordante mordante marked this pull request as ready for review March 9, 2024 17:03
@mordante mordante requested a review from a team as a code owner March 9, 2024 17:03
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Mar 9, 2024
@mordante mordante merged commit e19e860 into main Mar 9, 2024
52 of 54 checks passed
@mordante mordante deleted the users/mordante/clang-tidy_selection branch March 9, 2024 17:03
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 9, 2024

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

The current selection is done in the test scripts which gives the user no control where to find clang-tidy. The version selection itself is hard-coded and not based on the version of clang used.

This moves the selection to configuration time and tries to find a better match.

  • Mixing the version of clang-tidy and the clang libraries causes ODR violations. This results in practice in crashes or incorrect results.
  • Mixing the version of clang-tidy and the clang binary sometimes causes issues with supported diagnostic flags. For example, flags tested against clang 17 may not be available in clang-tidy 16.

Currently clang-tidy 18.1 can be used, it tests against the clang libraries version 18. This is caused by the new LLVM version numbering scheme.

The new selection tries to match the clang version or the version of the HEAD and the last 3 releases. (During the release period libc++ supports 4 versions instead of the typical 3 versions.)


Full diff: https://github.com/llvm/llvm-project/pull/81362.diff

4 Files Affected:

  • (modified) libcxx/test/tools/CMakeLists.txt (+5)
  • (modified) libcxx/test/tools/clang_tidy_checks/CMakeLists.txt (+4-4)
  • (modified) libcxx/utils/libcxx/test/features.py (-31)
  • (modified) libcxx/utils/libcxx/test/params.py (+42-1)
diff --git a/libcxx/test/tools/CMakeLists.txt b/libcxx/test/tools/CMakeLists.txt
index 10be63e8b50aa5..e30ad6cdd8201f 100644
--- a/libcxx/test/tools/CMakeLists.txt
+++ b/libcxx/test/tools/CMakeLists.txt
@@ -3,5 +3,10 @@ set(LIBCXX_TEST_TOOLS_PATH ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
 
 # TODO: Remove LIBCXX_ENABLE_CLANG_TIDY
 if(LIBCXX_ENABLE_CLANG_TIDY)
+  if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+    message(STATUS "Clang-tidy can only be used when building libc++ with "
+                   "a clang compiler.")
+    return()
+  endif()
   add_subdirectory(clang_tidy_checks)
 endif()
diff --git a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
index 978e7095216522..74905a0c3ed1c4 100644
--- a/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
+++ b/libcxx/test/tools/clang_tidy_checks/CMakeLists.txt
@@ -5,10 +5,10 @@
 set(LLVM_DIR_SAVE ${LLVM_DIR})
 set(Clang_DIR_SAVE ${Clang_DIR})
 
-find_package(Clang 18)
-if (NOT Clang_FOUND)
-  find_package(Clang 17)
-endif()
+# Since the Clang C++ ABI is not stable the Clang libraries and clang-tidy
+# versions must match. Otherwise there likely will be ODR-violations. This had
+# led to crashes and incorrect output of the clang-tidy based checks.
+find_package(Clang ${CMAKE_CXX_COMPILER_VERSION})
 
 set(SOURCES
     abi_tag_on_virtual.cpp
diff --git a/libcxx/utils/libcxx/test/features.py b/libcxx/utils/libcxx/test/features.py
index 6ef40755c59d97..3f0dc0c50a0d00 100644
--- a/libcxx/utils/libcxx/test/features.py
+++ b/libcxx/utils/libcxx/test/features.py
@@ -23,30 +23,6 @@
 _isMSVC = lambda cfg: "_MSC_VER" in compilerMacros(cfg)
 _msvcVersion = lambda cfg: (int(compilerMacros(cfg)["_MSC_VER"]) // 100, int(compilerMacros(cfg)["_MSC_VER"]) % 100)
 
-
-def _getSuitableClangTidy(cfg):
-    try:
-        # If we didn't build the libcxx-tidy plugin via CMake, we can't run the clang-tidy tests.
-        if runScriptExitCode(cfg, ["stat %{test-tools-dir}/clang_tidy_checks/libcxx-tidy.plugin"]) != 0:
-            return None
-
-        # TODO MODULES require ToT due module specific fixes.
-        if runScriptExitCode(cfg, ['clang-tidy-18 --version']) == 0:
-          return 'clang-tidy-18'
-
-        # TODO This should be the last stable release.
-        # LLVM RELEASE bump to latest stable version
-        if runScriptExitCode(cfg, ["clang-tidy-16 --version"]) == 0:
-            return "clang-tidy-16"
-
-        # LLVM RELEASE bump version
-        if int(re.search("[0-9]+", commandOutput(cfg, ["clang-tidy --version"])).group()) >= 16:
-            return "clang-tidy"
-
-    except ConfigurationRuntimeError:
-        return None
-
-
 def _getAndroidDeviceApi(cfg):
     return int(
         programOutput(
@@ -297,13 +273,6 @@ def _getAndroidDeviceApi(cfg):
         name="executor-has-no-bash",
         when=lambda cfg: runScriptExitCode(cfg, ["%{exec} bash -c 'bash --version'"]) != 0,
     ),
-    Feature(
-        name="has-clang-tidy",
-        when=lambda cfg: _getSuitableClangTidy(cfg) is not None,
-        actions=[
-            AddSubstitution("%{clang-tidy}", lambda cfg: _getSuitableClangTidy(cfg))
-        ],
-    ),
     # Whether module support for the platform is available.
     Feature(
         name="has-no-cxx-module-support",
diff --git a/libcxx/utils/libcxx/test/params.py b/libcxx/utils/libcxx/test/params.py
index 89d9f22e9dc6df..695e01115aa4ba 100644
--- a/libcxx/utils/libcxx/test/params.py
+++ b/libcxx/utils/libcxx/test/params.py
@@ -110,6 +110,37 @@ def getSizeOptimizationFlag(cfg):
         )
 
 
+def testClangTidy(cfg, version, executable):
+    try:
+        if version in commandOutput(cfg, [f"{executable} --version"]):
+            return executable
+    except ConfigurationRuntimeError:
+        return None
+
+
+def getSuitableClangTidy(cfg):
+    # If we didn't build the libcxx-tidy plugin via CMake, we can't run the clang-tidy tests.
+    if (
+        runScriptExitCode(
+            cfg, ["stat %{test-tools-dir}/clang_tidy_checks/libcxx-tidy.plugin"]
+        )
+        != 0
+    ):
+        return None
+
+    version = "{__clang_major__}.{__clang_minor__}.{__clang_patchlevel__}".format(
+        **compilerMacros(cfg)
+    )
+    exe = testClangTidy(
+        cfg, version, "clang-tidy-{__clang_major__}".format(**compilerMacros(cfg))
+    )
+
+    if not exe:
+        exe = testClangTidy(cfg, version, "clang-tidy")
+
+    return exe
+
+
 # fmt: off
 DEFAULT_PARAMETERS = [
     Parameter(
@@ -366,6 +397,16 @@ def getSizeOptimizationFlag(cfg):
         default=f"{shlex.quote(sys.executable)} {shlex.quote(str(Path(__file__).resolve().parent.parent.parent / 'run.py'))}",
         help="Custom executor to use instead of the configured default.",
         actions=lambda executor: [AddSubstitution("%{executor}", executor)],
-    )
+    ),
+    Parameter(
+        name='clang-tidy-executable',
+        type=str,
+        default=lambda cfg: getSuitableClangTidy(cfg),
+        help="Selects the clang-tidy executable to use.",
+        actions=lambda exe: [] if exe is None else [
+            AddFeature('has-clang-tidy'),
+            AddSubstitution('%{clang-tidy}', exe),
+        ]
+     ),
 ]
 # fmt: on

mordante added a commit to mordante/llvm-project that referenced this pull request Mar 14, 2024
The clang-tidy selection in CMake was refactored in
llvm#81362. During review it was
suggested to remove this CMake option.
mordante added a commit to mordante/llvm-project that referenced this pull request Mar 15, 2024
The clang-tidy selection in CMake was refactored in
llvm#81362. During review it was
suggested to remove this CMake option.
mordante added a commit to mordante/llvm-project that referenced this pull request Mar 18, 2024
The clang-tidy selection in CMake was refactored in
llvm#81362. During review it was
suggested to remove this CMake option.
mordante added a commit that referenced this pull request Mar 18, 2024
The clang-tidy selection in CMake was refactored in
#81362. During review it was
suggested to remove this CMake option.
mordante added a commit to mordante/llvm-project that referenced this pull request Mar 19, 2024
The clang-tidy selection in CMake was refactored in
llvm#81362. During review it was
suggested to remove this CMake option.
mordante added a commit to mordante/llvm-project that referenced this pull request Mar 20, 2024
The clang-tidy selection in CMake was refactored in
llvm#81362. During review it was
suggested to remove this CMake option.
chencha3 pushed a commit to chencha3/llvm-project that referenced this pull request Mar 23, 2024
The clang-tidy selection in CMake was refactored in
llvm#81362. During review it was
suggested to remove this CMake option.
EricWF added a commit that referenced this pull request Mar 25, 2024
This reverts commit 0bbada9.

The update of Clang in the CI broke due to the new LLVM version naming.
It needs to look for the clang 18.1 package instead of 18. Since it
couldn't find 18 it used 17 as fallback. This gives ODR violations which
caused the output for the module test to be wrong. (It didn't crash
which would be a lot more obvious to debug.)

The clang-tidy selection was fixed by
#81362. That patch also makes
clang-19 work with clang-tidy-19 out of the box.

The time-out have not been addressed; that is a CI issue and not an
issue with this test. They run in 200-ish s so they are slow but far
below the 1500s threshold. (Due to a dependency in this test it can't be
split in multiple tests.)
mordante added a commit to mordante/llvm-project that referenced this pull request Apr 12, 2024
The clang-tidy selection in CMake was refactored in
llvm#81362. During review it was
suggested to remove this CMake option.
mordante added a commit that referenced this pull request Apr 13, 2024
The clang-tidy selection in CMake was refactored in
#81362. During review it was
suggested to remove this CMake option.
bazuzi pushed a commit to bazuzi/llvm-project that referenced this pull request Apr 15, 2024
The clang-tidy selection in CMake was refactored in
llvm#81362. During review it was
suggested to remove this CMake option.
blueboxd pushed a commit to blueboxd/libcxx that referenced this pull request May 4, 2024
The clang-tidy selection in CMake was refactored in
llvm/llvm-project#81362. During review it was
suggested to remove this CMake option.

NOKEYCHECK=True
GitOrigin-RevId: 4109b18ee5de1346c2b89a5c89b86bae5c8631d3
nhasabni pushed a commit to nhasabni/llvm-project that referenced this pull request May 9, 2024
This reverts commit 0bbada9.

The update of Clang in the CI broke due to the new LLVM version naming.
It needs to look for the clang 18.1 package instead of 18. Since it
couldn't find 18 it used 17 as fallback. This gives ODR violations which
caused the output for the module test to be wrong. (It didn't crash
which would be a lot more obvious to debug.)

The clang-tidy selection was fixed by
llvm#81362. That patch also makes
clang-19 work with clang-tidy-19 out of the box.

The time-out have not been addressed; that is a CI issue and not an
issue with this test. They run in 200-ish s so they are slow but far
below the 1500s threshold. (Due to a dependency in this test it can't be
split in multiple tests.)
nhasabni pushed a commit to nhasabni/llvm-project that referenced this pull request May 9, 2024
This reverts commit 0bbada9.

The update of Clang in the CI broke due to the new LLVM version naming.
It needs to look for the clang 18.1 package instead of 18. Since it
couldn't find 18 it used 17 as fallback. This gives ODR violations which
caused the output for the module test to be wrong. (It didn't crash
which would be a lot more obvious to debug.)

The clang-tidy selection was fixed by
llvm#81362. That patch also makes
clang-19 work with clang-tidy-19 out of the box.

The time-out have not been addressed; that is a CI issue and not an
issue with this test. They run in 200-ish s so they are slow but far
below the 1500s threshold. (Due to a dependency in this test it can't be
split in multiple tests.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants