Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial Setup and Implicit this Check #1

Merged
merged 2 commits into from
Jun 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang-tools-extra/clang-tidy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ add_subdirectory(darwin)
add_subdirectory(fuchsia)
add_subdirectory(google)
add_subdirectory(hicpp)
add_subdirectory(kokkos)
add_subdirectory(linuxkernel)
add_subdirectory(llvm)
add_subdirectory(llvmlibc)
Expand All @@ -75,6 +76,7 @@ set(ALL_CLANG_TIDY_CHECKS
clangTidyFuchsiaModule
clangTidyGoogleModule
clangTidyHICPPModule
clangTidyKokkosModule
clangTidyLinuxKernelModule
clangTidyLLVMModule
clangTidyLLVMLibcModule
Expand Down
9 changes: 9 additions & 0 deletions clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
//===- ClangTidyForceLinker.h - clang-tidy --------------------------------===//
//
// Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// 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
Expand Down Expand Up @@ -65,6 +69,11 @@ extern volatile int HICPPModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED HICPPModuleAnchorDestination =
HICPPModuleAnchorSource;

// This anchor is used to force the linker to link the KokkosModule.
extern volatile int KokkosModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED KokkosModuleAnchorDestination =
KokkosModuleAnchorSource;

// This anchor is used to force the linker to link the LinuxKernelModule.
extern volatile int LinuxKernelModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED LinuxKernelModuleAnchorDestination =
Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/clang-tidy/add_new_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ def write_header(module_path, module, namespace, check_name, check_name_camel):
f.write('*- C++ -*-===//')
f.write("""
//
// Copyright 2020 National Technology & Engineering Solutions of Sandia,
// LLC (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// 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
Expand Down
16 changes: 16 additions & 0 deletions clang-tools-extra/clang-tidy/kokkos/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
set(LLVM_LINK_COMPONENTS support)

add_clang_library(clangTidyKokkosModule
ImplicitThisCaptureCheck.cpp
KokkosMatchers.cpp
KokkosTidyModule.cpp

LINK_LIBS
clangAnalysis
clangAST
clangASTMatchers
clangBasic
clangLex
clangTidy
clangTidyUtils
)
94 changes: 94 additions & 0 deletions clang-tools-extra/clang-tidy/kokkos/ImplicitThisCaptureCheck.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//===--- ImplicitThisCaptureCheck.cpp - clang-tidy ------------------------===//
//
// Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// 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 "ImplicitThisCaptureCheck.h"
#include "KokkosMatchers.h"
#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "llvm/ADT/Optional.h"

using namespace clang::ast_matchers;

namespace clang {
namespace tidy {
namespace kokkos {

namespace {
llvm::Optional<SourceLocation> capturesThis(CXXRecordDecl const *CRD) {
if (!CRD->isLambda()) {
return llvm::None;
}

for (auto const &Capture : CRD->captures()) {
if (Capture.capturesThis()) {
return llvm::Optional<SourceLocation>(Capture.getLocation());
}
}

return llvm::None;
}

} // namespace

ImplicitThisCaptureCheck::ImplicitThisCaptureCheck(
StringRef Name, ClangTidyContext *Context)
: ClangTidyCheck(Name, Context) {
CheckIfExplicitHost = std::stoi(Options.get("CheckIfExplicitHost", "0"));
HostTypeDefRegex =
Options.get("HostTypeDefRegex", "Kokkos::DefaultHostExecutionSpace");
}

void ImplicitThisCaptureCheck::storeOptions(
ClangTidyOptions::OptionMap &Opts) {
Options.store(Opts, "CheckIfExplicitHost",
std::to_string(CheckIfExplicitHost));
Options.store(Opts, "HostTypeDefRegex", HostTypeDefRegex);
}

void ImplicitThisCaptureCheck::registerMatchers(MatchFinder *Finder) {
auto isAllowedPolicy = expr(hasType(
cxxRecordDecl(matchesName("::Impl::ThreadVectorRangeBoundariesStruct.*|::"
"Impl::TeamThreadRangeBoundariesStruct.*"))));

auto Lambda = expr(hasType(cxxRecordDecl(isLambda()).bind("Lambda")));

Finder->addMatcher(
callExpr(isKokkosParallelCall(),
hasAnyArgument(Lambda), unless(hasAnyArgument(isAllowedPolicy)))
.bind("x"),
this);
}

void ImplicitThisCaptureCheck::check(
const MatchFinder::MatchResult &Result) {
auto const *CE = Result.Nodes.getNodeAs<CallExpr>("x");

if (CheckIfExplicitHost) {
if (explicitlyUsingHostExecutionSpace(CE, HostTypeDefRegex)) {
return;
}
}

auto const *Lambda = Result.Nodes.getNodeAs<CXXRecordDecl>("Lambda");
auto CaptureLocation = capturesThis(Lambda);
if (CaptureLocation) {
diag(Lambda->getBeginLoc(), "Lambda passed to %0 implicitly captures this.")
<< CE->getDirectCallee()->getName();
diag(CaptureLocation.getValue(), "the captured variable is used here.",
DiagnosticIDs::Note);
diag(CE->getBeginLoc(), "Kokkos call here.", DiagnosticIDs::Note);
}
}

} // namespace kokkos
} // namespace tidy
} // namespace clang
41 changes: 41 additions & 0 deletions clang-tools-extra/clang-tidy/kokkos/ImplicitThisCaptureCheck.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//===--- ImplicitThisCaptureCheck.h - clang-tidy ----------------*- C++ -*-===//
//
// Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// 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_KOKKOS_IMPLICITTHISCAPTURECHECK_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_KOKKOS_IMPLICITTHISCAPTURECHECK_H

#include "../ClangTidyCheck.h"

#include <string>

namespace clang {
namespace tidy {
namespace kokkos {

/// Check to detect when a lambda passed to a ::Kokkos::parallel_* implicitly
/// captures the this pointer
class ImplicitThisCaptureCheck : public ClangTidyCheck {
public:
ImplicitThisCaptureCheck(StringRef Name, ClangTidyContext *Context);
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
private:
int CheckIfExplicitHost;
std::string HostTypeDefRegex;
};

} // namespace kokkos
} // namespace tidy
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_KOKKOS_IMPLICITTHISCAPTURECHECK_H
54 changes: 54 additions & 0 deletions clang-tools-extra/clang-tidy/kokkos/KokkosMatchers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//===--- KokkosMatchers.cpp - clang-tidy ------------------------===//
//
// Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// 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 "KokkosMatchers.h"

namespace clang {
namespace tidy {
namespace kokkos {

bool explicitlyUsingHostExecutionSpace(CallExpr const *CE,
std::string const &RegexString) {
using namespace clang::ast_matchers;
auto &Ctx = CE->getCalleeDecl()->getASTContext();

// We will assume that any policy where the user might explicitly ask for the
// host space inherits from Impl::PolicyTraits
auto FilterArgs =
hasAnyArgument(expr(hasType(cxxRecordDecl(isDerivedFrom(cxxRecordDecl(
matchesName("Impl::PolicyTraits"))))))
.bind("expr"));

// We have to jump through some hoops to find this, if we just looked at the
// template type of the Policy constructor we lose the sugar and instead of
// Kokkos::DefaultHostExecutionSpace we get what the ever the typedef was set
// to such as Kokkos::Serial, preventing us from figuring out if the user
// actually asked for a host space specifically or just happens to have a
// host space as the default space.
llvm::Regex Reg(RegexString);
auto BNs = match(callExpr(FilterArgs).bind("CE"), *CE, Ctx);
for (auto &BN : BNs) {
if (auto const *E = BN.getNodeAs<Expr>("expr")) {
if (auto const *TST = E->getType()->getAs<TemplateSpecializationType>()) {
if (Reg.match(TST->getArg(0).getAsType().getAsString())) {
return true;
}
}
}
}

return false;
}

} // namespace kokkos
} // namespace tidy
} // namespace clang
52 changes: 52 additions & 0 deletions clang-tools-extra/clang-tidy/kokkos/KokkosMatchers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//===--- KokkosMatchers.h - clang-tidy ------------------------===//
//
// Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// 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_KOKKOS_KOKKOSMATCHERS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_KOKKOS_KOKKOSMATCHERS_H

#include "clang/AST/ASTContext.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include <string>

namespace clang {
namespace tidy {
namespace kokkos {

AST_MATCHER_FUNCTION(ast_matchers::internal::Matcher<FunctionDecl>,
kokkosParallelXFunctionDecl) {
using namespace clang::ast_matchers;
return functionDecl(matchesName("::Kokkos::parallel_.*"));
}

AST_MATCHER(CallExpr, isKokkosParallelCall) {
using namespace clang::ast_matchers;
if (auto const *FD = Node.getDirectCallee()) {
std::string Name = FD->getQualifiedNameAsString();
StringRef SR(Name);
if (SR.startswith("::Kokkos::parallel_")) {
return true;
}
}

return false;
}

bool explicitlyUsingHostExecutionSpace(CallExpr const *CE,
std::string const &RegexString);


} // namespace kokkos
} // namespace tidy
} // namespace clang

#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_KOKKOS_KOKKOSMATCHERS_H
41 changes: 41 additions & 0 deletions clang-tools-extra/clang-tidy/kokkos/KokkosTidyModule.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//===--- KokkosTidyModule.cpp - clang-tidy ----------------------------------===//
//
// Copyright 2020 National Technology & Engineering Solutions of Sandia, LLC
// (NTESS). Under the terms of Contract DE-NA0003525 with NTESS, the U.S.
// Government retains certain rights in this software.
//
// 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 "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
#include "ImplicitThisCaptureCheck.h"

namespace clang {
namespace tidy {
namespace kokkos {

class KokkosModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<ImplicitThisCaptureCheck>(
"kokkos-implicit-this-capture");
}
};

} // namespace kokkos

// Register the DarwinTidyModule using this statically initialized variable.
static ClangTidyModuleRegistry::Add<kokkos::KokkosModule>
X("kokkos-module", "Adds Kokkos specific linting checks.");

// This anchor is used to force the linker to link in the generated object file
// and thus register the KokkosModule.
volatile int KokkosModuleAnchorSource = 0;

} // namespace tidy
} // namespace clang
5 changes: 5 additions & 0 deletions clang-tools-extra/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,11 @@ New checks
Flags use of the `C` standard library functions ``memset``, ``memcpy`` and
``memcmp`` and similar derivatives on non-trivial types.

- New :doc:`kokkos-implicit-this-capture
<clang-tidy/checks/kokkos-implicit-this-capture>` check.

New check for implicit this capture detection

- New :doc:`llvmlibc-callee-namespace
<clang-tidy/checks/llvmlibc-callee-namespace>` check.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.. title:: clang-tidy - kokkos-implicit-this-capture

kokkos-implicit-this-capture
============================

The implicit-this-capture check checks if a lambda passed to any of
parallel_reduce, parallel_for, or parallel_scan functions captures the this
pointer.

Example of a class that should trigger the check
.. code-block:: c++

class Foo {
int x = 0;

void operator()(){
Kokkos::parallel_for(10, KOKKOS_LAMBDA(int y){ printf("%d", x+y)});
}
};
Loading