[clang-tools-extra] r278553 - [clang-tidy] MPIBufferDerefCheck
Alexander Droste via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 12 12:30:31 PDT 2016
Author: alexander_droste
Date: Fri Aug 12 14:30:31 2016
New Revision: 278553
URL: http://llvm.org/viewvc/llvm-project?rev=278553&view=rev
Log:
[clang-tidy] MPIBufferDerefCheck
...
This check verifies if a buffer passed to an MPI (Message Passing Interface)
function is sufficiently dereferenced. Buffers should be passed as a single
pointer or array. As MPI function signatures specify void * for their buffer
types, insufficiently dereferenced buffers can be passed, like for example
as double pointers or multidimensional arrays, without a compiler warning
emitted.
Instructions on how to apply the check can be found at:
https://github.com/0ax1/MPI-Checker/tree/master/examples
Reviewers: Haojian Wu
Differential revision: https://reviews.llvm.org/D22729
Added:
clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.cpp
clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.h
clang-tools-extra/trunk/docs/clang-tidy/checks/mpi-buffer-deref.rst
clang-tools-extra/trunk/test/clang-tidy/mpi-buffer-deref.cpp
Modified:
clang-tools-extra/trunk/clang-tidy/mpi/CMakeLists.txt
clang-tools-extra/trunk/clang-tidy/mpi/MPITidyModule.cpp
clang-tools-extra/trunk/docs/ReleaseNotes.rst
clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
clang-tools-extra/trunk/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h
Added: clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.cpp?rev=278553&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.cpp (added)
+++ clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.cpp Fri Aug 12 14:30:31 2016
@@ -0,0 +1,132 @@
+//===--- BufferDerefCheck.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 "BufferDerefCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
+#include "clang/Tooling/FixIt.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+void BufferDerefCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(callExpr().bind("CE"), this);
+}
+
+void BufferDerefCheck::check(const MatchFinder::MatchResult &Result) {
+ static ento::mpi::MPIFunctionClassifier FuncClassifier(*Result.Context);
+ const auto *CE = Result.Nodes.getNodeAs<CallExpr>("CE");
+ if (!CE->getDirectCallee())
+ return;
+
+ const IdentifierInfo *Identifier = CE->getDirectCallee()->getIdentifier();
+ if (!Identifier || !FuncClassifier.isMPIType(Identifier))
+ return;
+
+ // These containers are used, to capture the type and expression of a buffer.
+ SmallVector<const Type *, 1> BufferTypes;
+ SmallVector<const Expr *, 1> BufferExprs;
+
+ // Adds the type and expression of a buffer that is used in the MPI call
+ // expression to the captured containers.
+ auto addBuffer = [&CE, &Result, &BufferTypes,
+ &BufferExprs](const size_t BufferIdx) {
+ // Skip null pointer constants and in place 'operators'.
+ if (CE->getArg(BufferIdx)->isNullPointerConstant(
+ *Result.Context, Expr::NPC_ValueDependentIsNull) ||
+ tooling::fixit::getText(*CE->getArg(BufferIdx), *Result.Context) ==
+ "MPI_IN_PLACE")
+ return;
+
+ const Expr *ArgExpr = CE->getArg(BufferIdx);
+ if (!ArgExpr)
+ return;
+ const Type *ArgType = ArgExpr->IgnoreImpCasts()->getType().getTypePtr();
+ if (!ArgType)
+ return;
+ BufferExprs.push_back(ArgExpr);
+ BufferTypes.push_back(ArgType);
+ };
+
+ // Collect buffer types and argument expressions for all buffers used in the
+ // MPI call expression. The number passed to the lambda corresponds to the
+ // argument index of the currently verified MPI function call.
+ if (FuncClassifier.isPointToPointType(Identifier)) {
+ addBuffer(0);
+ } else if (FuncClassifier.isCollectiveType(Identifier)) {
+ if (FuncClassifier.isReduceType(Identifier)) {
+ addBuffer(0);
+ addBuffer(1);
+ } else if (FuncClassifier.isScatterType(Identifier) ||
+ FuncClassifier.isGatherType(Identifier) ||
+ FuncClassifier.isAlltoallType(Identifier)) {
+ addBuffer(0);
+ addBuffer(3);
+ } else if (FuncClassifier.isBcastType(Identifier)) {
+ addBuffer(0);
+ }
+ }
+
+ checkBuffers(BufferTypes, BufferExprs);
+}
+
+void BufferDerefCheck::checkBuffers(ArrayRef<const Type *> BufferTypes,
+ ArrayRef<const Expr *> BufferExprs) {
+ for (size_t i = 0; i < BufferTypes.size(); ++i) {
+ unsigned IndirectionCount = 0;
+ const Type *BufferType = BufferTypes[i];
+ llvm::SmallVector<IndirectionType, 1> Indirections;
+
+ // Capture the depth and types of indirections for the passed buffer.
+ while (true) {
+ if (BufferType->isPointerType()) {
+ BufferType = BufferType->getPointeeType().getTypePtr();
+ Indirections.push_back(IndirectionType::Pointer);
+ } else if (BufferType->isArrayType()) {
+ BufferType = BufferType->getArrayElementTypeNoTypeQual();
+ Indirections.push_back(IndirectionType::Array);
+ } else {
+ break;
+ }
+ ++IndirectionCount;
+ }
+
+ if (IndirectionCount > 1) {
+ // Referencing an array with '&' is valid, as this also points to the
+ // beginning of the array.
+ if (IndirectionCount == 2 &&
+ Indirections[0] == IndirectionType::Pointer &&
+ Indirections[1] == IndirectionType::Array)
+ return;
+
+ // Build the indirection description in reverse order of discovery.
+ std::string IndirectionDesc;
+ for (auto It = Indirections.rbegin(); It != Indirections.rend(); ++It) {
+ if (!IndirectionDesc.empty())
+ IndirectionDesc += "->";
+ if (*It == IndirectionType::Pointer) {
+ IndirectionDesc += "pointer";
+ } else {
+ IndirectionDesc += "array";
+ }
+ }
+
+ const auto Loc = BufferExprs[i]->getSourceRange().getBegin();
+ diag(Loc, "buffer is insufficiently dereferenced: %0") << IndirectionDesc;
+ }
+ }
+}
+
+} // namespace mpi
+} // namespace tidy
+} // namespace clang
Added: clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.h?rev=278553&view=auto
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.h (added)
+++ clang-tools-extra/trunk/clang-tidy/mpi/BufferDerefCheck.h Fri Aug 12 14:30:31 2016
@@ -0,0 +1,51 @@
+//===--- BufferDerefCheck.h - clang-tidy-------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_BUFFER_DEREF_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_BUFFER_DEREF_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+/// This check verifies if a buffer passed to an MPI (Message Passing Interface)
+/// function is sufficiently dereferenced. Buffers should be passed as a single
+/// pointer or array. As MPI function signatures specify void * for their buffer
+/// types, insufficiently dereferenced buffers can be passed, like for example
+/// as double pointers or multidimensional arrays, without a compiler warning
+/// emitted.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/mpi-buffer-deref.html
+class BufferDerefCheck : public ClangTidyCheck {
+public:
+ BufferDerefCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ /// Checks for all buffers in an MPI call if they are sufficiently
+ /// dereferenced.
+ ///
+ /// \param BufferTypes buffer types
+ /// \param BufferExprs buffer arguments as expressions
+ void checkBuffers(ArrayRef<const Type *> BufferTypes,
+ ArrayRef<const Expr *> BufferExprs);
+
+ enum class IndirectionType : unsigned char { Pointer, Array };
+};
+
+} // namespace mpi
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_BUFFER_DEREF_H
Modified: clang-tools-extra/trunk/clang-tidy/mpi/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/mpi/CMakeLists.txt?rev=278553&r1=278552&r2=278553&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/mpi/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clang-tidy/mpi/CMakeLists.txt Fri Aug 12 14:30:31 2016
@@ -1,6 +1,7 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyMPIModule
+ BufferDerefCheck.cpp
MPITidyModule.cpp
TypeMismatchCheck.cpp
Modified: clang-tools-extra/trunk/clang-tidy/mpi/MPITidyModule.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/mpi/MPITidyModule.cpp?rev=278553&r1=278552&r2=278553&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/mpi/MPITidyModule.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/mpi/MPITidyModule.cpp Fri Aug 12 14:30:31 2016
@@ -10,6 +10,7 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
+#include "BufferDerefCheck.h"
#include "TypeMismatchCheck.h"
namespace clang {
@@ -19,6 +20,7 @@ namespace mpi {
class MPIModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<BufferDerefCheck>("mpi-buffer-deref");
CheckFactories.registerCheck<TypeMismatchCheck>("mpi-type-mismatch");
}
};
Modified: clang-tools-extra/trunk/docs/ReleaseNotes.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/ReleaseNotes.rst?rev=278553&r1=278552&r2=278553&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/ReleaseNotes.rst (original)
+++ clang-tools-extra/trunk/docs/ReleaseNotes.rst Fri Aug 12 14:30:31 2016
@@ -69,6 +69,16 @@ Improvements to clang-tidy
Flags classes where some, but not all, special member functions are user-defined.
+- New `mpi-buffer-deref
+ <http://clang.llvm.org/extra/clang-tidy/checks/mpi-buffer-deref.html>`_ check
+
+ Flags buffers which are insufficiently dereferenced when passed to an MPI function call.
+
+- New `mpi-type-mismatch
+ <http://clang.llvm.org/extra/clang-tidy/checks/mpi-type-mismatch.html>`_ check
+
+ Flags MPI function calls with a buffer type and MPI data type mismatch.
+
- New `performance-inefficient-string-concatenation
<http://clang.llvm.org/extra/clang-tidy/checks/performance-inefficient-string-concatenation.html>`_ check
Modified: clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst?rev=278553&r1=278552&r2=278553&view=diff
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst (original)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/list.rst Fri Aug 12 14:30:31 2016
@@ -110,6 +110,7 @@ Clang-Tidy Checks
modernize-use-nullptr
modernize-use-override
modernize-use-using
+ mpi-buffer-deref
mpi-type-mismatch
performance-faster-string-find
performance-for-range-copy
Added: clang-tools-extra/trunk/docs/clang-tidy/checks/mpi-buffer-deref.rst
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/docs/clang-tidy/checks/mpi-buffer-deref.rst?rev=278553&view=auto
==============================================================================
--- clang-tools-extra/trunk/docs/clang-tidy/checks/mpi-buffer-deref.rst (added)
+++ clang-tools-extra/trunk/docs/clang-tidy/checks/mpi-buffer-deref.rst Fri Aug 12 14:30:31 2016
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - mpi-buffer-deref
+
+mpi-buffer-deref
+================
+
+This check verifies if a buffer passed to an MPI (Message Passing Interface)
+function is sufficiently dereferenced. Buffers should be passed as a single
+pointer or array. As MPI function signatures specify ``void *`` for their buffer
+types, insufficiently dereferenced buffers can be passed, like for example as
+double pointers or multidimensional arrays, without a compiler warning emitted.
+
+Examples:
+.. code:: c++
+
+ // A double pointer is passed to the MPI function.
+ char *buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+ // A multidimensional array is passed to the MPI function.
+ short buf[1][1];
+ MPI_Send(buf, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
+
+ // A pointer to an array is passed to the MPI function.
+ short *buf[1];
+ MPI_Send(buf, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
Modified: clang-tools-extra/trunk/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h?rev=278553&r1=278552&r2=278553&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h (original)
+++ clang-tools-extra/trunk/test/clang-tidy/Inputs/mpi-type-mismatch/mpimock.h Fri Aug 12 14:30:31 2016
@@ -24,6 +24,7 @@ namespace std { template<class T> struct
#define MPI_DATATYPE_NULL 0
#define MPI_CHAR 0
#define MPI_BYTE 0
+#define MPI_SHORT 0
#define MPI_INT 0
#define MPI_LONG 0
#define MPI_LONG_DOUBLE 0
@@ -31,6 +32,7 @@ namespace std { template<class T> struct
#define MPI_INT8_T 0
#define MPI_UINT8_T 0
#define MPI_UINT16_T 0
+#define MPI_C_FLOAT_COMPLEX 0
#define MPI_C_LONG_DOUBLE_COMPLEX 0
#define MPI_FLOAT 0
#define MPI_DOUBLE 0
Added: clang-tools-extra/trunk/test/clang-tidy/mpi-buffer-deref.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/mpi-buffer-deref.cpp?rev=278553&view=auto
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/mpi-buffer-deref.cpp (added)
+++ clang-tools-extra/trunk/test/clang-tidy/mpi-buffer-deref.cpp Fri Aug 12 14:30:31 2016
@@ -0,0 +1,50 @@
+// RUN: %check_clang_tidy %s mpi-buffer-deref %t -- -- -I %S/Inputs/mpi-type-mismatch
+
+#include "mpimock.h"
+
+void negativeTests() {
+ char *buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->pointer [mpi-buffer-deref]
+
+ unsigned **buf2;
+ MPI_Send(buf2, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->pointer
+
+ short buf3[1][1];
+ MPI_Send(buf3, 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: array->array
+
+ long double _Complex *buf4[1];
+ MPI_Send(buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->array
+
+ std::complex<float> *buf5[1][1];
+ MPI_Send(&buf5, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer is insufficiently dereferenced: pointer->array->array->pointer
+}
+
+void positiveTests() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+ unsigned *buf2;
+ MPI_Send(buf2, 1, MPI_UNSIGNED, 0, 0, MPI_COMM_WORLD);
+
+ short buf3[1][1];
+ MPI_Send(buf3[0], 1, MPI_SHORT, 0, 0, MPI_COMM_WORLD);
+
+ long double _Complex *buf4[1];
+ MPI_Send(*buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ long double _Complex buf5[1];
+ MPI_Send(buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ std::complex<float> *buf6[1][1];
+ MPI_Send(*buf6[0], 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ // Referencing an array with '&' is valid, as this also points to the
+ // beginning of the array.
+ long double _Complex buf7[1];
+ MPI_Send(&buf7, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+}
More information about the cfe-commits
mailing list