llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-tools-extra Author: Donát Nagy (NagyDonat) <details> <summary>Changes</summary> This commit ensures that the modernize-use-constraints check ignores templates that happen to be named `enable_if` or `enable_if_t` if they are not declared in the namespace `std`. This patch motivated by a crash observed during the analysis of the open source library https://github.com/Neargye/magic_enum/ which declares a template `detail::enable_if_t` with semantics that significantly differ from the standard one. (I was unable to reproduce that crash with the standard `enable_if_t`.) However, there are other projects that use non-standard `enable_if`: even `boost` declares a `boost::enable_if` which excepts different parameters than `std::enable_if`. --- Full diff: https://github.com/llvm/llvm-project/pull/155237.diff 2 Files Affected: - (modified) clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp (+2-2) - (modified) clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp (+30) ``````````diff diff --git a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp index 07274d0376207..1818e30971c21 100644 --- a/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp +++ b/clang-tools-extra/clang-tidy/modernize/UseConstraintsCheck.cpp @@ -77,7 +77,7 @@ matchEnableIfSpecializationImplTypename(TypeLoc TheType) { const TemplateDecl *TD = Specialization->getTemplateName().getAsTemplateDecl(); - if (!TD || TD->getName() != "enable_if") + if (!TD || TD->getName() != "enable_if" || !TD->isInStdNamespace()) return std::nullopt; int NumArgs = SpecializationLoc.getNumArgs(); @@ -101,7 +101,7 @@ matchEnableIfSpecializationImplTrait(TypeLoc TheType) { const TemplateDecl *TD = Specialization->getTemplateName().getAsTemplateDecl(); - if (!TD || TD->getName() != "enable_if_t") + if (!TD || TD->getName() != "enable_if_t" || !TD->isInStdNamespace()) return std::nullopt; if (!Specialization->isTypeAlias()) diff --git a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp index 3bcd5cd74024e..8289efe338e3f 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/modernize/use-constraints.cpp @@ -756,3 +756,33 @@ abs(const number<T, ExpressionTemplates> &v) { } } + +// NOLINTBEGIN +namespace custom { +template <bool B, class T = void> struct enable_if { }; + +template <class T> struct enable_if<true, T> { typedef T type; }; + +template <bool B, class T = void> +using enable_if_t = typename enable_if<B, T>::type; + +} // namespace custom +// NOLINTEND + +namespace use_custom { +// We cannot assume anything about the behavior of templates that happen to be +// named `enable_if` or `enable_if_t` if they are not declared in the namespace +// `std`. (E.g. the first template parameter of `boost::enable_if` is a class +// and not a boolean and `boost::enable_if<Cond, T>` is equivalent to +// `std::enable_if<Cond::value, T>`.) + +template <typename T> +typename custom::enable_if<T::some_value, Obj>::type custom_basic() { + return Obj{}; +} + +template <typename T> +custom::enable_if_t<T::some_value, Obj> custom_basic_t() { + return Obj{}; +} +} `````````` </details> https://github.com/llvm/llvm-project/pull/155237 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
