Skip to content

[clang-tidy] Fix bugprone-incorrect-enable-if inserting duplicate typename#190899

Merged
localspook merged 2 commits into
llvm:mainfrom
localspook:incorrect-enable-if
Apr 10, 2026
Merged

[clang-tidy] Fix bugprone-incorrect-enable-if inserting duplicate typename#190899
localspook merged 2 commits into
llvm:mainfrom
localspook:incorrect-enable-if

Conversation

@localspook
Copy link
Copy Markdown
Member

@localspook localspook commented Apr 8, 2026

This PR resolves one of our FIXME's. Pre-C++20, this check turns

typename std::enable_if<...>

into

typename typename std::enable_if<...>::type

instead of

typename std::enable_if<...>::type

https://godbolt.org/z/4s4ozPsM3

@llvmbot
Copy link
Copy Markdown
Member

llvmbot commented Apr 8, 2026

@llvm/pr-subscribers-clang-tidy

@llvm/pr-subscribers-clang-tools-extra

Author: Victor Chernyakin (localspook)

Changes

This PR resolves one of our FIXME's. Pre-C++20, this check turns

typename std::enable_if&lt;...&gt;

into

typename typename std::enable_if&lt;...&gt;::type

instead of

typename std::enable_if&lt;...&gt;::type

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

3 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp (+4-5)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+6)
  • (modified) clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp (+6)
diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
index 6181ac84f36e3..5a592e10a599e 100644
--- a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
+++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp
@@ -47,8 +47,8 @@ void IncorrectEnableIfCheck::check(const MatchFinder::MatchResult &Result) {
       Result.Nodes.getNodeAs<TemplateSpecializationTypeLoc>(
           "enable_if_specialization");
 
-  if (!EnableIf || !EnableIfSpecializationLoc)
-    return;
+  assert(EnableIf);
+  assert(EnableIfSpecializationLoc);
 
   const SourceManager &SM = *Result.SourceManager;
   const SourceLocation RAngleLoc =
@@ -57,9 +57,8 @@ void IncorrectEnableIfCheck::check(const MatchFinder::MatchResult &Result) {
   auto Diag = diag(EnableIf->getBeginLoc(),
                    "incorrect std::enable_if usage detected; use "
                    "'typename std::enable_if<...>::type'");
-  // FIXME: This should handle the enable_if specialization already having an
-  // elaborated keyword.
-  if (!getLangOpts().CPlusPlus20) {
+  if (!getLangOpts().CPlusPlus20 &&
+      EnableIfSpecializationLoc->getElaboratedKeywordLoc().isInvalid()) {
     Diag << FixItHint::CreateInsertion(EnableIfSpecializationLoc->getBeginLoc(),
                                        "typename ");
   }
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index eb735e6e62ee4..4f5a219747bae 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -219,6 +219,12 @@ Changes in existing checks
   loss in overloads with transparent standard functors (e.g. ``std::plus<>``)
   for ``std::accumulate``, ``std::reduce``, and ``std::inner_product``.
 
+- Improved :doc:`bugprone-incorrect-enable-if
+  <clang-tidy/checks/bugprone/incorrect-enable-if>` check to not
+  insert an extraneous ``typename`` on code like
+  ``typename std::enable_if<...>``, where there's already a
+  ``typename`` and only the ``::type`` at the end is missing.
+
 - Improved :doc:`bugprone-inc-dec-in-conditions
   <clang-tidy/checks/bugprone/inc-dec-in-conditions>` check by fixing a false
   positive when increment/decrement operators appear inside lambda bodies that
diff --git a/clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp b/clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
index 0c418efe1420b..81612a50e5bbd 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/bugprone/incorrect-enable-if.cpp
@@ -42,6 +42,12 @@ void invalid_multiple() {}
 // CHECK-FIXES: template <typename T, typename = typename std::enable_if<T::some_value>::type, typename = typename std::enable_if<T::other_value>::type>
 // CHECK-FIXES-CXX20: template <typename T, typename = std::enable_if<T::some_value>::type, typename = std::enable_if<T::other_value>::type>
 
+template <typename T, typename = typename std::enable_if<T::some_value>>
+void invalid_typename_keyword() {}
+// CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]
+// CHECK-FIXES: template <typename T, typename = typename std::enable_if<T::some_value>::type>
+// CHECK-FIXES-CXX20: template <typename T, typename = typename std::enable_if<T::some_value>::type>
+
 template <typename T, typename = std::enable_if<T::some_value>>
 struct InvalidClass {};
 // CHECK-MESSAGES: [[@LINE-2]]:23: warning: incorrect std::enable_if usage detected; use 'typename std::enable_if<...>::type' [bugprone-incorrect-enable-if]

@localspook localspook force-pushed the incorrect-enable-if branch from 22cc58e to d600650 Compare April 8, 2026 03:10
Copy link
Copy Markdown
Contributor

@vbvictor vbvictor left a comment

Choose a reason for hiding this comment

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

LGTM

Comment thread clang-tools-extra/docs/ReleaseNotes.rst Outdated
Co-authored-by: EugeneZelenko <eugene.zelenko@gmail.com>
@localspook localspook enabled auto-merge (squash) April 10, 2026 01:13
@localspook localspook merged commit d458f34 into llvm:main Apr 10, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants