Skip to content

Commit 728fc71

Browse files
committed
[clang-tidy] Fix modernize-use-constraints crash on uses of nonstandard enable_ifs
1 parent cc8c941 commit 728fc71

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "UseConstraintsCheck.h"
1010
#include "clang/AST/ASTContext.h"
11+
#include "clang/AST/DeclTemplate.h"
1112
#include "clang/ASTMatchers/ASTMatchFinder.h"
1213
#include "clang/Lex/Lexer.h"
1314

@@ -78,6 +79,15 @@ matchEnableIfSpecializationImplTypename(TypeLoc TheType) {
7879
if (!TD || TD->getName() != "enable_if")
7980
return std::nullopt;
8081

82+
const TemplateParameterList *Params = TD->getTemplateParameters();
83+
if (Params->size() != 2)
84+
return std::nullopt;
85+
86+
const auto *FirstParam =
87+
dyn_cast<NonTypeTemplateParmDecl>(Params->getParam(0));
88+
if (!FirstParam || !FirstParam->getType()->isBooleanType())
89+
return std::nullopt;
90+
8191
int NumArgs = SpecializationLoc.getNumArgs();
8292
if (NumArgs != 1 && NumArgs != 2)
8393
return std::nullopt;

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ Changes in existing checks
136136
- Improved :doc:`misc-header-include-cycle
137137
<clang-tidy/checks/misc/header-include-cycle>` check performance.
138138

139+
- Fixed a :doc:`modernize-use-constraints
140+
<clang-tidy/checks/modernize/use-constraints>` crash on uses of
141+
nonstandard ``enable_if``s with a signature different from
142+
``std::enable_if`` (such as ``boost::enable_if``).
143+
139144
- Improved :doc:`modernize-use-designated-initializers
140145
<clang-tidy/checks/modernize/use-designated-initializers>` check to
141146
suggest using designated initializers for aliased aggregate types.

clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %check_clang_tidy -std=c++20 %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
1+
// RUN: %check_clang_tidy -std=c++20-or-later %s modernize-use-constraints %t -- -- -fno-delayed-template-parsing
22

33
// NOLINTBEGIN
44
namespace std {
@@ -756,3 +756,32 @@ abs(const number<T, ExpressionTemplates> &v) {
756756
}
757757

758758
}
759+
760+
template <typename T>
761+
struct some_type_trait {
762+
static constexpr bool value = true;
763+
};
764+
765+
// Fix-its are offered even for a nonstandard enable_if.
766+
namespace nonstd {
767+
768+
template <bool Condition, typename T = void>
769+
struct enable_if : std::enable_if<Condition, T> {};
770+
771+
}
772+
773+
template <typename T>
774+
typename nonstd::enable_if<some_type_trait<T>::value, void>::type nonstd_enable_if() {}
775+
// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use C++20 requires constraints instead of enable_if [modernize-use-constraints]
776+
// CHECK-FIXES: {{^}}void nonstd_enable_if() requires some_type_trait<T>::value {}{{$}}
777+
778+
// But only if the nonstandard enable_if has the same signature as the standard one.
779+
namespace boost {
780+
781+
template <typename Condition, typename T = void>
782+
struct enable_if : std::enable_if<Condition::value, T> {};
783+
784+
}
785+
786+
template <typename T>
787+
typename boost::enable_if<some_type_trait<T>, void>::type boost_enable_if() {}

0 commit comments

Comments
 (0)