Index: clang-tidy/CMakeLists.txt =================================================================== --- clang-tidy/CMakeLists.txt +++ clang-tidy/CMakeLists.txt @@ -41,6 +41,7 @@ add_subdirectory(objc) add_subdirectory(performance) add_subdirectory(plugin) +add_subdirectory(portability) add_subdirectory(readability) add_subdirectory(tool) add_subdirectory(utils) Index: clang-tidy/plugin/CMakeLists.txt =================================================================== --- clang-tidy/plugin/CMakeLists.txt +++ clang-tidy/plugin/CMakeLists.txt @@ -19,6 +19,7 @@ clangTidyMPIModule clangTidyObjCModule clangTidyPerformanceModule + clangTidyPortabilityModule clangTidyReadabilityModule clangTooling ) Index: clang-tidy/plugin/ClangTidyPlugin.cpp =================================================================== --- clang-tidy/plugin/ClangTidyPlugin.cpp +++ clang-tidy/plugin/ClangTidyPlugin.cpp @@ -118,6 +118,11 @@ static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination = PerformanceModuleAnchorSource; +// This anchor is used to force the linker to link the PortabilityModule. +extern volatile int PortabilityModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED PortabilityModuleAnchorDestination = + PortabilityModuleAnchorSource; + // This anchor is used to force the linker to link the ReadabilityModule. extern volatile int ReadabilityModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = Index: clang-tidy/portability/CMakeLists.txt =================================================================== --- /dev/null +++ clang-tidy/portability/CMakeLists.txt @@ -0,0 +1,15 @@ +set(LLVM_LINK_COMPONENTS support) + +add_clang_library(clangTidyPortabilityModule + PortabilityTidyModule.cpp + SIMDIntrinsicsCheck.cpp + + LINK_LIBS + clangAST + clangASTMatchers + clangBasic + clangLex + clangTidy + clangTidyUtils + clangTooling + ) Index: clang-tidy/portability/PortabilityTidyModule.cpp =================================================================== --- /dev/null +++ clang-tidy/portability/PortabilityTidyModule.cpp @@ -0,0 +1,38 @@ +//===--- PortabilityTidyModule.cpp - clang-tidy ---------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../ClangTidy.h" +#include "../ClangTidyModule.h" +#include "../ClangTidyModuleRegistry.h" +#include "SIMDIntrinsicsCheck.h" + +namespace clang { +namespace tidy { +namespace portability { + +class PortabilityModule : public ClangTidyModule { +public: + void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "portability-simd-intrinsics"); + } +}; + +// Register the PortabilityModule using this statically initialized variable. +static ClangTidyModuleRegistry::Add + X("portability-module", "Adds portability-related checks."); + +} // namespace portability + +// This anchor is used to force the linker to link in the generated object file +// and thus register the PortabilityModule. +volatile int PortabilityModuleAnchorSource = 0; + +} // namespace tidy +} // namespace clang Index: clang-tidy/portability/SIMDIntrinsicsCheck.h =================================================================== --- clang-tidy/portability/SIMDIntrinsicsCheck.h +++ clang-tidy/portability/SIMDIntrinsicsCheck.h @@ -14,12 +14,12 @@ namespace clang { namespace tidy { -namespace readability { +namespace portability { /// Find SIMD intrinsics calls and suggest std::experimental::simd alternatives. /// /// For the user-facing documentation see: -/// http://clang.llvm.org/extra/clang-tidy/checks/readability-simd-intrinsics.html +/// http://clang.llvm.org/extra/clang-tidy/checks/portability-simd-intrinsics.html class SIMDIntrinsicsCheck : public ClangTidyCheck { public: SIMDIntrinsicsCheck(StringRef Name, ClangTidyContext *Context); @@ -29,11 +29,11 @@ void check(const ast_matchers::MatchFinder::MatchResult &Result) override; private: + std::string Std; const bool Suggest; - StringRef Std; }; -} // namespace readability +} // namespace portability } // namespace tidy } // namespace clang Index: clang-tidy/portability/SIMDIntrinsicsCheck.cpp =================================================================== --- clang-tidy/portability/SIMDIntrinsicsCheck.cpp +++ clang-tidy/portability/SIMDIntrinsicsCheck.cpp @@ -18,7 +18,7 @@ namespace clang { namespace tidy { -namespace readability { +namespace portability { namespace { @@ -84,17 +84,21 @@ SIMDIntrinsicsCheck::SIMDIntrinsicsCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context), Suggest(Options.get("Suggest", 0) != 0) {} + : ClangTidyCheck(Name, Context), Std(Options.get("Std", "")), + Suggest(Options.get("Suggest", 0) != 0) {} void SIMDIntrinsicsCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "Std", ""); Options.store(Opts, "Suggest", 0); } void SIMDIntrinsicsCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus11) return; + // If Std is not specified, infer it from the language options. // libcxx implementation backports it to C++11 std::experimental::simd. - Std = getLangOpts().CPlusPlus2a ? "std" : "std::experimental"; + if (Std.empty()) + Std = getLangOpts().CPlusPlus2a ? "std" : "std::experimental"; Finder->addMatcher(callExpr(callee(functionDecl(allOf( matchesName("^::(_mm_|_mm256_|_mm512_|vec_)"), @@ -116,18 +120,20 @@ llvm::Triple::ArchType Arch = Result.Context->getTargetInfo().getTriple().getArch(); + // We warn or suggest if this SIMD intrinsic function has a std::simd + // replacement. switch (Arch) { - default: - break; - case llvm::Triple::ppc: - case llvm::Triple::ppc64: - case llvm::Triple::ppc64le: - New = TrySuggestPPC(Old); - break; - case llvm::Triple::x86: - case llvm::Triple::x86_64: - New = TrySuggestX86(Old); - break; + default: + break; + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + New = TrySuggestPPC(Old); + break; + case llvm::Triple::x86: + case llvm::Triple::x86_64: + New = TrySuggestX86(Old); + break; } if (!New.empty()) { @@ -137,7 +143,7 @@ if (Suggest) { Message = (Twine("'") + Old + "' can be replaced by " + New).str(); Message = llvm::Regex("\\$std").sub(Std, Message); - Message = llvm::Regex("\\$simd").sub(Std.str() + "::simd", Message); + Message = llvm::Regex("\\$simd").sub(Std + "::simd", Message); } else { Message = (Twine("'") + Old + "' is a non-portable " + llvm::Triple::getArchTypeName(Arch) + " intrinsic function") @@ -147,6 +153,6 @@ } } -} // namespace readability +} // namespace portability } // namespace tidy } // namespace clang Index: clang-tidy/readability/CMakeLists.txt =================================================================== --- clang-tidy/readability/CMakeLists.txt +++ clang-tidy/readability/CMakeLists.txt @@ -24,7 +24,6 @@ RedundantStringCStrCheck.cpp RedundantSmartptrGetCheck.cpp RedundantStringInitCheck.cpp - SIMDIntrinsicsCheck.cpp SimplifyBooleanExprCheck.cpp StaticAccessedThroughInstanceCheck.cpp StaticDefinitionInAnonymousNamespaceCheck.cpp Index: clang-tidy/readability/ReadabilityTidyModule.cpp =================================================================== --- clang-tidy/readability/ReadabilityTidyModule.cpp +++ clang-tidy/readability/ReadabilityTidyModule.cpp @@ -31,7 +31,6 @@ #include "RedundantSmartptrGetCheck.h" #include "RedundantStringCStrCheck.h" #include "RedundantStringInitCheck.h" -#include "SIMDIntrinsicsCheck.h" #include "SimplifyBooleanExprCheck.h" #include "StaticAccessedThroughInstanceCheck.h" #include "StaticDefinitionInAnonymousNamespaceCheck.h" @@ -93,8 +92,6 @@ "readability-redundant-string-cstr"); CheckFactories.registerCheck( "readability-redundant-string-init"); - CheckFactories.registerCheck( - "readability-simd-intrinsics"); CheckFactories.registerCheck( "readability-simplify-boolean-expr"); CheckFactories.registerCheck( Index: clang-tidy/tool/CMakeLists.txt =================================================================== --- clang-tidy/tool/CMakeLists.txt +++ clang-tidy/tool/CMakeLists.txt @@ -31,6 +31,7 @@ clangTidyMPIModule clangTidyObjCModule clangTidyPerformanceModule + clangTidyPortabilityModule clangTidyReadabilityModule clangTooling clangToolingCore Index: clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tidy/tool/ClangTidyMain.cpp +++ clang-tidy/tool/ClangTidyMain.cpp @@ -554,6 +554,11 @@ static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination = PerformanceModuleAnchorSource; +// This anchor is used to force the linker to link the PortabilityModule. +extern volatile int PortabilityModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED PortabilityModuleAnchorDestination = + PortabilityModuleAnchorSource; + // This anchor is used to force the linker to link the ReadabilityModule. extern volatile int ReadabilityModuleAnchorSource; static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = Index: docs/ReleaseNotes.rst =================================================================== --- docs/ReleaseNotes.rst +++ docs/ReleaseNotes.rst @@ -95,8 +95,8 @@ Finds and replaces deprecated uses of ``std::uncaught_exception`` to ``std::uncaught_exceptions``. -- New `readability-simd-intrinsics - `_ check +- New `portability-simd-intrinsics + `_ check Warns if SIMD intrinsics are used which can be replaced by ``std::experimental::simd`` operations. Index: docs/clang-tidy/checks/portability-simd-intrinsics.rst =================================================================== --- docs/clang-tidy/checks/portability-simd-intrinsics.rst +++ docs/clang-tidy/checks/portability-simd-intrinsics.rst @@ -41,4 +41,9 @@ `P0214`_ alternatives, otherwise it only points out the intrinsic function is non-portable. +.. option:: Std + + The namespace used to suggest `P0214`_ alternatives. If not specified, `std::` + for `-std=c++2a` and `std::experimental::` for `-std=c++11`. + .. _P0214: http://wg21.link/p0214 Index: test/clang-tidy/portability-simd-intrinsics-ppc.cpp =================================================================== --- test/clang-tidy/portability-simd-intrinsics-ppc.cpp +++ test/clang-tidy/portability-simd-intrinsics-ppc.cpp @@ -1,6 +1,6 @@ -// RUN: %check_clang_tidy %s readability-simd-intrinsics %t -- \ +// RUN: %check_clang_tidy %s portability-simd-intrinsics %t -- \ // RUN: -config='{CheckOptions: [ \ -// RUN: {key: readability-simd-intrinsics.Suggest, value: 1} \ +// RUN: {key: portability-simd-intrinsics.Suggest, value: 1} \ // RUN: ]}' -- -target ppc64le -maltivec -std=c++11 vector int vec_add(vector int, vector int); @@ -9,5 +9,5 @@ vector int i0, i1; vec_add(i0, i1); -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'vec_add' can be replaced by operator+ on std::experimental::simd objects [readability-simd-intrinsics] +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: 'vec_add' can be replaced by operator+ on std::experimental::simd objects [portability-simd-intrinsics] } Index: test/clang-tidy/portability-simd-intrinsics-x86.cpp =================================================================== --- test/clang-tidy/portability-simd-intrinsics-x86.cpp +++ test/clang-tidy/portability-simd-intrinsics-x86.cpp @@ -1,6 +1,6 @@ -// RUN: %check_clang_tidy %s readability-simd-intrinsics %t -- \ +// RUN: %check_clang_tidy %s portability-simd-intrinsics %t -- \ // RUN: -config='{CheckOptions: [ \ -// RUN: {key: readability-simd-intrinsics.Suggest, value: 1} \ +// RUN: {key: portability-simd-intrinsics.Suggest, value: 1} \ // RUN: ]}' -- -target x86_64 -std=c++11 typedef long long __m128i __attribute__((vector_size(16))); @@ -17,7 +17,7 @@ __m256 d0; _mm_add_epi32(i0, i1); -// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: '_mm_add_epi32' can be replaced by operator+ on std::experimental::simd objects [readability-simd-intrinsics] +// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: '_mm_add_epi32' can be replaced by operator+ on std::experimental::simd objects [portability-simd-intrinsics] d0 = _mm256_load_pd(0); _mm256_store_pd(0, d0);