forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from kokkos/implicit-this
Initial Setup and Implicit this Check
- Loading branch information
Showing
13 changed files
with
516 additions
and
164 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
94
clang-tools-extra/clang-tidy/kokkos/ImplicitThisCaptureCheck.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
41
clang-tools-extra/clang-tidy/kokkos/ImplicitThisCaptureCheck.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
19 changes: 19 additions & 0 deletions
19
clang-tools-extra/docs/clang-tidy/checks/kokkos-implicit-this-capture.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)}); | ||
} | ||
}; |
Oops, something went wrong.