royjacobson updated this revision to Diff 466285.
royjacobson added a comment.

Addrees CR comments


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D135404/new/

https://reviews.llvm.org/D135404

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
  clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst
  clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/type-traits.cpp
@@ -0,0 +1,73 @@
+// RUN: %check_clang_tidy -std=c++17-or-later %s modernize-type-traits %t
+
+namespace std {
+
+template <class T, T x>
+struct integral_constant {
+    static constexpr inline T value = x;
+};
+
+template <class U, class V>
+struct is_same : integral_constant<bool, false> {};
+
+template <class T>
+struct is_trivially_default_constructible : integral_constant<bool, false> {};
+
+template <class T>
+struct alignment_of : integral_constant<int, 3> {};
+
+}
+
+
+template <class T>
+void f() {
+    auto x = std::is_same<int, T>::value;
+    auto y = std::is_trivially_default_constructible<T>::value;
+    auto z = std::alignment_of<T>::value;
+
+// CHECK-FIXES:      auto x = std::is_same_v<int, T>;
+// CHECK-FIXES-NEXT: auto y = std::is_trivially_default_constructible_v<T>;
+// CHECK-FIXES-NEXT: auto z = std::alignment_of_v<T>;
+// Test that we don't get this twice or something weird like that because
+// we're in a dependant context.
+// CHECK-FIXES-NOT:  auto x = std::is_same_v<int, T>;
+}
+
+void g() {
+    f<int>();
+    f<float>();
+}
+
+void h() {
+    auto x = std::is_same<int, float>::value;
+    auto y = std::is_trivially_default_constructible<float>::value;
+    auto z = std::alignment_of<float>::value;
+// CHECK-FIXES:      auto x = std::is_same_v<int, float>;
+// CHECK-FIXES-NEXT: auto y = std::is_trivially_default_constructible_v<float>;
+// CHECK-FIXES-NEXT: auto z = std::alignment_of_v<float>;
+}
+
+
+template <class T>
+struct NonDiagnosableTemplate : std::integral_constant<bool, false> {};
+
+struct NonDiagnosable1 : std::integral_constant<bool, false> {};
+struct NonDiagnosable2 {
+    using value = int;
+};
+
+#define IN_A_MACRO std::is_same<int, int>::value
+void macro_use() {
+    bool a = IN_A_MACRO;
+}
+// Don't fix-it if we use it inside a macro.
+// CHECK-FIXES: #define IN_A_MACRO std::is_same<int, int>::value
+
+void test_no_diagnostic() {
+    auto x = NonDiagnosableTemplate<int>::value;
+    auto y = NonDiagnosable1::value;
+    auto z = NonDiagnosable2::value(4);
+// CHECK-FIXES:      auto x = NonDiagnosableTemplate<int>::value;
+// CHECK-FIXES-NEXT: auto y = NonDiagnosable1::value;
+// CHECK-FIXES-NEXT: auto z = NonDiagnosable2::value(4);
+}
Index: clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/type-traits.rst
@@ -0,0 +1,33 @@
+.. title:: clang-tidy - modernize-type-traits
+
+modernize-type-traits
+=====================
+
+
+Convert type traits from the form ``trait<...>::value`` into ``trait_v<...>``
+The template variable traits from C++17 can improve compile times, as in
+modern library implementations they don't instantiate structs.
+
+For example, this:
+
+.. code-block:: c++
+
+  std::is_same<int, float>::value
+  std::is_integral<float>::value
+
+is replaced by:
+
+.. code-block:: c++
+
+  std::is_same_v<int, float>
+  std::is_integral_v<float>
+
+Options
+-------
+
+.. option:: ValueTypeTraits
+
+    Specifies a list of type traits which are used with a static ``::value``
+    member for metaprogramming instead of the regular one of traits available
+    in the STL. This check assumes that a matching version exists with the
+    same name and a ``_v`` suffix.
\ No newline at end of file
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -275,6 +275,7 @@
    `modernize-replace-random-shuffle <modernize/replace-random-shuffle.html>`_, "Yes"
    `modernize-return-braced-init-list <modernize/return-braced-init-list.html>`_, "Yes"
    `modernize-shrink-to-fit <modernize/shrink-to-fit.html>`_, "Yes"
+   `modernize-type-traits <modernize/type-traits.html>`_, "Yes"
    `modernize-unary-static-assert <modernize/unary-static-assert.html>`_, "Yes"
    `modernize-use-auto <modernize/use-auto.html>`_, "Yes"
    `modernize-use-bool-literals <modernize/use-bool-literals.html>`_, "Yes"
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -110,6 +110,13 @@
 
   Warns when a struct or class uses const or reference (lvalue or rvalue) data members.
 
+- New :doc:`modernize-type-traits
+  <clang-tidy/checks/modernize/type-traits>` check.
+
+  Finds usages of C++11 style type traits like ``std::is_same<...>::value`` and replaces
+  them with the C++17 variable template ``std::is_same_v<...>``. This transformation can
+  help reduce compile times.
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 
Index: clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.h
@@ -0,0 +1,41 @@
+//===--- TypeTraitsCheck.h - clang-tidy -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_TYPETRAITSCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_TYPETRAITSCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+/// Convert type traits from the form `trait<...>::value` into `trait_v<...>`
+/// The template variable traits from C++17 can improve compile times, as in
+/// modern library implementations they don't instantiate structs.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/type-traits.html
+class TypeTraitsCheck : public ClangTidyCheck {
+public:
+  TypeTraitsCheck(StringRef Name, ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
+    return LangOpts.CPlusPlus17;
+  }
+
+private:
+  llvm::DenseSet<StringRef> ValueTypeTraits;
+};
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_TYPETRAITSCHECK_H
Index: clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/modernize/TypeTraitsCheck.cpp
@@ -0,0 +1,98 @@
+//===--- TypeTraitsCheck.cpp - clang-tidy ---------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TypeTraitsCheck.h"
+#include "../utils/OptionsUtils.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Tooling/FixIt.h"
+#include "llvm/Support/Regex.h"
+#include <iostream>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace modernize {
+
+const auto DefaultValueTypeTraits =
+    "std::alignment_of;std::conjunction;std::disjunction;std::extent;std::has_"
+    "unique_object_representations;std::has_virtual_destructor;std::is_"
+    "abstract;std::is_aggregate;std::is_arithmetic;std::is_array;std::is_"
+    "assignable;std::is_base_of;std::is_bounded_array;std::is_class;std::is_"
+    "compound;std::is_const;std::is_constructible;std::is_convertible;std::is_"
+    "copy_assignable;std::is_copy_constructible;std::is_default_constructible;"
+    "std::is_destructible;std::is_empty;std::is_enum;std::is_final;std::is_"
+    "floating_point;std::is_function;std::is_fundamental;std::is_integral;std::"
+    "is_invocable;std::is_invocable_r;std::is_layout_compatible;std::is_lvalue_"
+    "reference;std::is_member_function_pointer;std::is_member_object_pointer;"
+    "std::is_member_pointer;std::is_move_assignable;std::is_move_constructible;"
+    "std::is_nothrow_assignable;std::is_nothrow_constructible;std::is_nothrow_"
+    "convertible;std::is_nothrow_copy_assignable;std::is_nothrow_copy_"
+    "constructible;std::is_nothrow_default_constructible;std::is_nothrow_"
+    "destructible;std::is_nothrow_invocable;std::is_nothrow_invocable_r;std::"
+    "is_nothrow_move_assignable;std::is_nothrow_move_constructible;std::is_"
+    "nothrow_swappable;std::is_nothrow_swappable_with;std::is_null_pointer;std:"
+    ":is_object;std::is_pointer;std::is_pointer_interconvertible_base_of;std::"
+    "is_polymorphic;std::is_reference;std::is_rvalue_reference;std::is_same;"
+    "std::is_scalar;std::is_scoped_enum;std::is_signed;std::is_standard_layout;"
+    "std::is_swappable;std::is_swappable_with;std::is_trivial;std::is_"
+    "trivially_assignable;std::is_trivially_constructible;std::is_trivially_"
+    "copy_assignable;std::is_trivially_copy_constructible;std::is_trivially_"
+    "copyable;std::is_trivially_default_constructible;std::is_trivially_"
+    "destructible;std::is_trivially_move_assignable;std::is_trivially_move_"
+    "constructible;std::is_unbounded_array;std::is_union;std::is_unsigned;std::"
+    "is_void;std::is_volatile;std::negation;std::rank;std::reference_"
+    "constructs_from_temporary;std::reference_converts_from_temporary";
+
+TypeTraitsCheck::TypeTraitsCheck(StringRef Name, ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context) {
+  auto VectorValueTypeTraits = utils::options::parseStringList(
+      Options.get("ValueTypeTraits", DefaultValueTypeTraits));
+  ValueTypeTraits = llvm::DenseSet<StringRef>(VectorValueTypeTraits.begin(),
+                                              VectorValueTypeTraits.end());
+}
+
+void TypeTraitsCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      declRefExpr(to(varDecl(hasName("value")))).bind("memberExpr"), this);
+}
+
+void TypeTraitsCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *MatchedDecl = Result.Nodes.getNodeAs<DeclRefExpr>("memberExpr");
+  if (MatchedDecl) {
+    const auto *Qualifier = MatchedDecl->getQualifier();
+    if (!Qualifier)
+      return;
+    const auto *RecordQualifier =
+        dyn_cast_if_present<ClassTemplateSpecializationDecl>(
+            Qualifier->getAsRecordDecl());
+    if (!RecordQualifier)
+      return;
+    auto TraitName = RecordQualifier->getQualifiedNameAsString();
+    if (ValueTypeTraits.find(TraitName) == ValueTypeTraits.end())
+      return;
+
+    SourceLocation ValueLoc = MatchedDecl->getSourceRange().getEnd();
+    auto IssuedDiag = diag(ValueLoc, "use c++17 style variable templates");
+
+    if (ValueLoc.isMacroID())
+      return;
+
+    llvm::Regex replacement_regex(TraitName + "<(.*)>::value$");
+    auto CurrentText = tooling::fixit::getText(*MatchedDecl, *Result.Context);
+    if (replacement_regex.match(CurrentText))
+      IssuedDiag << FixItHint::CreateReplacement(
+          MatchedDecl->getSourceRange(),
+          replacement_regex.sub(TraitName + "_v<\\1>", CurrentText));
+  }
+}
+
+} // namespace modernize
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -26,6 +26,7 @@
 #include "ReplaceRandomShuffleCheck.h"
 #include "ReturnBracedInitListCheck.h"
 #include "ShrinkToFitCheck.h"
+#include "TypeTraitsCheck.h"
 #include "UnaryStaticAssertCheck.h"
 #include "UseAutoCheck.h"
 #include "UseBoolLiteralsCheck.h"
@@ -77,6 +78,7 @@
     CheckFactories.registerCheck<ReturnBracedInitListCheck>(
         "modernize-return-braced-init-list");
     CheckFactories.registerCheck<ShrinkToFitCheck>("modernize-shrink-to-fit");
+    CheckFactories.registerCheck<TypeTraitsCheck>("modernize-type-traits");
     CheckFactories.registerCheck<UnaryStaticAssertCheck>(
         "modernize-unary-static-assert");
     CheckFactories.registerCheck<UseAutoCheck>("modernize-use-auto");
Index: clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -25,6 +25,7 @@
   ReplaceRandomShuffleCheck.cpp
   ReturnBracedInitListCheck.cpp
   ShrinkToFitCheck.cpp
+  TypeTraitsCheck.cpp
   UnaryStaticAssertCheck.cpp
   UseAutoCheck.cpp
   UseBoolLiteralsCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to