add_subdirectory(google)
add_subdirectory(misc)
add_subdirectory(modernize)
+add_subdirectory(mpi)
add_subdirectory(performance)
add_subdirectory(readability)
add_subdirectory(utils)
--- /dev/null
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangTidyMPIModule
+ MPITidyModule.cpp
+ TypeMismatchCheck.cpp
+
+ LINK_LIBS
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangLex
+ clangTidy
+ clangTidyUtils
+ clangTooling
+ )
--- /dev/null
+//===--- MPITidyModule.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 "TypeMismatchCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+class MPIModule : public ClangTidyModule {
+public:
+ void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+ CheckFactories.registerCheck<TypeMismatchCheck>("mpi-type-mismatch");
+ }
+};
+
+} // namespace mpi
+
+// Register the MPITidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<mpi::MPIModule>
+ X("mpi-module", "Adds MPI clang-tidy checks.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the MPIModule.
+volatile int MPIModuleAnchorSource = 0;
+
+} // namespace tidy
+} // namespace clang
--- /dev/null
+//===--- TypeMismatchCheck.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 "TypeMismatchCheck.h"
+#include "clang/StaticAnalyzer/Checkers/MPIFunctionClassifier.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Tooling/FixIt.h"
+#include <map>
+#include <unordered_set>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+/// Check if a BuiltinType::Kind matches the MPI datatype.
+///
+/// \param MultiMap datatype group
+/// \param Kind buffer type kind
+/// \param MPIDatatype name of the MPI datatype
+///
+/// \returns true if the pair matches
+static bool
+isMPITypeMatching(const std::multimap<BuiltinType::Kind, std::string> &MultiMap,
+ const BuiltinType::Kind Kind,
+ const std::string &MPIDatatype) {
+ auto ItPair = MultiMap.equal_range(Kind);
+ while (ItPair.first != ItPair.second) {
+ if (ItPair.first->second == MPIDatatype)
+ return true;
+ ++ItPair.first;
+ }
+ return false;
+}
+
+/// Check if the MPI datatype is a standard type.
+///
+/// \param MPIDatatype name of the MPI datatype
+///
+/// \returns true if the type is a standard type
+static bool isStandardMPIDatatype(const std::string &MPIDatatype) {
+ static std::unordered_set<std::string> AllTypes = {
+ "MPI_C_BOOL",
+ "MPI_CHAR",
+ "MPI_SIGNED_CHAR",
+ "MPI_UNSIGNED_CHAR",
+ "MPI_WCHAR",
+ "MPI_INT",
+ "MPI_LONG",
+ "MPI_SHORT",
+ "MPI_LONG_LONG",
+ "MPI_LONG_LONG_INT",
+ "MPI_UNSIGNED",
+ "MPI_UNSIGNED_SHORT",
+ "MPI_UNSIGNED_LONG",
+ "MPI_UNSIGNED_LONG_LONG",
+ "MPI_FLOAT",
+ "MPI_DOUBLE",
+ "MPI_LONG_DOUBLE",
+ "MPI_C_COMPLEX",
+ "MPI_C_FLOAT_COMPLEX",
+ "MPI_C_DOUBLE_COMPLEX",
+ "MPI_C_LONG_DOUBLE_COMPLEX",
+ "MPI_INT8_T",
+ "MPI_INT16_T",
+ "MPI_INT32_T",
+ "MPI_INT64_T",
+ "MPI_UINT8_T",
+ "MPI_UINT16_T",
+ "MPI_UINT32_T",
+ "MPI_UINT64_T",
+ "MPI_CXX_BOOL",
+ "MPI_CXX_FLOAT_COMPLEX",
+ "MPI_CXX_DOUBLE_COMPLEX",
+ "MPI_CXX_LONG_DOUBLE_COMPLEX"};
+
+ return AllTypes.find(MPIDatatype) != AllTypes.end();
+}
+
+/// Check if a BuiltinType matches the MPI datatype.
+///
+/// \param Builtin the builtin type
+/// \param BufferTypeName buffer type name, gets assigned
+/// \param MPIDatatype name of the MPI datatype
+/// \param LO language options
+///
+/// \returns true if the type matches
+static bool isBuiltinTypeMatching(const BuiltinType *Builtin,
+ std::string &BufferTypeName,
+ const std::string &MPIDatatype,
+ const LangOptions &LO) {
+ static std::multimap<BuiltinType::Kind, std::string> BuiltinMatches = {
+ {BuiltinType::SChar, "MPI_CHAR"},
+ {BuiltinType::SChar, "MPI_SIGNED_CHAR"},
+ {BuiltinType::Char_S, "MPI_CHAR"},
+ {BuiltinType::Char_S, "MPI_SIGNED_CHAR"},
+ {BuiltinType::UChar, "MPI_UNSIGNED_CHAR"},
+ {BuiltinType::Char_U, "MPI_UNSIGNED_CHAR"},
+ {BuiltinType::WChar_S, "MPI_WCHAR"},
+ {BuiltinType::WChar_U, "MPI_WCHAR"},
+ {BuiltinType::Bool, "MPI_C_BOOL"},
+ {BuiltinType::Bool, "MPI_CXX_BOOL"},
+ {BuiltinType::Short, "MPI_SHORT"},
+ {BuiltinType::Int, "MPI_INT"},
+ {BuiltinType::Long, "MPI_LONG"},
+ {BuiltinType::LongLong, "MPI_LONG_LONG"},
+ {BuiltinType::LongLong, "MPI_LONG_LONG_INT"},
+ {BuiltinType::UShort, "MPI_UNSIGNED_SHORT"},
+ {BuiltinType::UInt, "MPI_UNSIGNED"},
+ {BuiltinType::ULong, "MPI_UNSIGNED_LONG"},
+ {BuiltinType::ULongLong, "MPI_UNSIGNED_LONG_LONG"},
+ {BuiltinType::Float, "MPI_FLOAT"},
+ {BuiltinType::Double, "MPI_DOUBLE"},
+ {BuiltinType::LongDouble, "MPI_LONG_DOUBLE"}};
+
+ if (!isMPITypeMatching(BuiltinMatches, Builtin->getKind(), MPIDatatype)) {
+ BufferTypeName = Builtin->getName(LO);
+ return false;
+ }
+
+ return true;
+}
+
+/// Check if a complex float/double/long double buffer type matches
+/// the MPI datatype.
+///
+/// \param Complex buffer type
+/// \param BufferTypeName buffer type name, gets assigned
+/// \param MPIDatatype name of the MPI datatype
+/// \param LO language options
+///
+/// \returns true if the type matches or the buffer type is unknown
+static bool isCComplexTypeMatching(const ComplexType *const Complex,
+ std::string &BufferTypeName,
+ const std::string &MPIDatatype,
+ const LangOptions &LO) {
+ static std::multimap<BuiltinType::Kind, std::string> ComplexCMatches = {
+ {BuiltinType::Float, "MPI_C_COMPLEX"},
+ {BuiltinType::Float, "MPI_C_FLOAT_COMPLEX"},
+ {BuiltinType::Double, "MPI_C_DOUBLE_COMPLEX"},
+ {BuiltinType::LongDouble, "MPI_C_LONG_DOUBLE_COMPLEX"}};
+
+ const auto *Builtin =
+ Complex->getElementType().getTypePtr()->getAs<BuiltinType>();
+
+ if (Builtin &&
+ !isMPITypeMatching(ComplexCMatches, Builtin->getKind(), MPIDatatype)) {
+ BufferTypeName = (llvm::Twine(Builtin->getName(LO)) + " _Complex").str();
+ return false;
+ }
+ return true;
+}
+
+/// Check if a complex<float/double/long double> templated buffer type matches
+/// the MPI datatype.
+///
+/// \param Complex buffer type
+/// \param BufferTypeName buffer type name, gets assigned
+/// \param MPIDatatype name of the MPI datatype
+/// \param LO language options
+///
+/// \returns true if the type matches or the buffer type is unknown
+static bool
+isCXXComplexTypeMatching(const TemplateSpecializationType *const Template,
+ std::string &BufferTypeName,
+ const std::string &MPIDatatype,
+ const LangOptions &LO) {
+ static std::multimap<BuiltinType::Kind, std::string> ComplexCXXMatches = {
+ {BuiltinType::Float, "MPI_CXX_FLOAT_COMPLEX"},
+ {BuiltinType::Double, "MPI_CXX_DOUBLE_COMPLEX"},
+ {BuiltinType::LongDouble, "MPI_CXX_LONG_DOUBLE_COMPLEX"}};
+
+ if (Template->getAsCXXRecordDecl()->getName() != "complex")
+ return true;
+
+ const auto *Builtin =
+ Template->getArg(0).getAsType().getTypePtr()->getAs<BuiltinType>();
+
+ if (Builtin &&
+ !isMPITypeMatching(ComplexCXXMatches, Builtin->getKind(), MPIDatatype)) {
+ BufferTypeName =
+ (llvm::Twine("complex<") + Builtin->getName(LO) + ">").str();
+ return false;
+ }
+
+ return true;
+}
+
+/// Check if a fixed size width buffer type matches the MPI datatype.
+///
+/// \param Complex buffer type
+/// \param BufferTypeName buffer type name, gets assigned
+/// \param MPIDatatype name of the MPI datatype
+///
+/// \returns true if the type matches or the buffer type is unknown
+static bool isTypedefTypeMatching(const TypedefType *const Typedef,
+ std::string &BufferTypeName,
+ const std::string &MPIDatatype) {
+ static llvm::StringMap<std::string> FixedWidthMatches = {
+ {"int8_t", "MPI_INT8_T"}, {"int16_t", "MPI_INT16_T"},
+ {"int32_t", "MPI_INT32_T"}, {"int64_t", "MPI_INT64_T"},
+ {"uint8_t", "MPI_UINT8_T"}, {"uint16_t", "MPI_UINT16_T"},
+ {"uint32_t", "MPI_UINT32_T"}, {"uint64_t", "MPI_UINT64_T"}};
+
+ const auto it = FixedWidthMatches.find(Typedef->getDecl()->getName());
+ // Check if the typedef is known and not matching the MPI datatype.
+ if (it != FixedWidthMatches.end() && it->getValue() != MPIDatatype) {
+ BufferTypeName = Typedef->getDecl()->getName();
+ return false;
+ }
+ return true;
+}
+
+/// Get the unqualified, dereferenced type of an argument.
+///
+/// \param CE call expression
+/// \param idx argument index
+///
+/// \returns type of the argument
+static const Type *argumentType(const CallExpr *const CE, const size_t idx) {
+ const QualType QT = CE->getArg(idx)->IgnoreImpCasts()->getType();
+ return QT.getTypePtr()->getPointeeOrArrayElementType();
+}
+
+void TypeMismatchCheck::registerMatchers(MatchFinder *Finder) {
+ Finder->addMatcher(callExpr().bind("CE"), this);
+}
+
+void TypeMismatchCheck::check(const MatchFinder::MatchResult &Result) {
+ static ento::mpi::MPIFunctionClassifier FuncClassifier(*Result.Context);
+ const CallExpr *const 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 buffer, MPI datatype pairs.
+ SmallVector<const Type *, 1> BufferTypes;
+ SmallVector<const Expr *, 1> BufferExprs;
+ SmallVector<StringRef, 1> MPIDatatypes;
+
+ // Adds a buffer, MPI datatype pair of an MPI call expression to the
+ // containers. For buffers, the type and expression is captured.
+ auto addPair = [&CE, &Result, &BufferTypes, &BufferExprs, &MPIDatatypes](
+ const size_t BufferIdx, const size_t DatatypeIdx) {
+ // 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;
+
+ StringRef MPIDatatype =
+ tooling::fixit::getText(*CE->getArg(DatatypeIdx), *Result.Context);
+
+ const Type *ArgType = argumentType(CE, BufferIdx);
+ // Skip unknown MPI datatypes and void pointers.
+ if (!isStandardMPIDatatype(MPIDatatype) || ArgType->isVoidType())
+ return;
+
+ BufferTypes.push_back(ArgType);
+ BufferExprs.push_back(CE->getArg(BufferIdx));
+ MPIDatatypes.push_back(MPIDatatype);
+ };
+
+ // Collect all buffer, MPI datatype pairs for the inspected call expression.
+ if (FuncClassifier.isPointToPointType(Identifier)) {
+ addPair(0, 2);
+ } else if (FuncClassifier.isCollectiveType(Identifier)) {
+ if (FuncClassifier.isReduceType(Identifier)) {
+ addPair(0, 3);
+ addPair(1, 3);
+ } else if (FuncClassifier.isScatterType(Identifier) ||
+ FuncClassifier.isGatherType(Identifier) ||
+ FuncClassifier.isAlltoallType(Identifier)) {
+ addPair(0, 2);
+ addPair(3, 5);
+ } else if (FuncClassifier.isBcastType(Identifier)) {
+ addPair(0, 2);
+ }
+ }
+ checkArguments(BufferTypes, BufferExprs, MPIDatatypes,
+ Result.Context->getLangOpts());
+}
+
+void TypeMismatchCheck::checkArguments(ArrayRef<const Type *> BufferTypes,
+ ArrayRef<const Expr *> BufferExprs,
+ ArrayRef<StringRef> MPIDatatypes,
+ const LangOptions &LO) {
+ std::string BufferTypeName;
+
+ for (size_t i = 0; i < MPIDatatypes.size(); ++i) {
+ const Type *const BT = BufferTypes[i];
+ bool Error = false;
+
+ if (const auto *Typedef = BT->getAs<TypedefType>()) {
+ Error = !isTypedefTypeMatching(Typedef, BufferTypeName, MPIDatatypes[i]);
+ } else if (const auto *Complex = BT->getAs<ComplexType>()) {
+ Error =
+ !isCComplexTypeMatching(Complex, BufferTypeName, MPIDatatypes[i], LO);
+ } else if (const auto *Template = BT->getAs<TemplateSpecializationType>()) {
+ Error = !isCXXComplexTypeMatching(Template, BufferTypeName,
+ MPIDatatypes[i], LO);
+ } else if (const auto *Builtin = BT->getAs<BuiltinType>()) {
+ Error =
+ !isBuiltinTypeMatching(Builtin, BufferTypeName, MPIDatatypes[i], LO);
+ }
+
+ if (Error) {
+ const auto Loc = BufferExprs[i]->getSourceRange().getBegin();
+ diag(Loc, "buffer type '%0' does not match the MPI datatype '%1'")
+ << BufferTypeName << MPIDatatypes[i];
+ }
+ }
+}
+
+} // namespace mpi
+} // namespace tidy
+} // namespace clang
--- /dev/null
+//===--- TypeMismatchCheck.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_TYPE_MISMATCH_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_TYPE_MISMATCH_H
+
+#include "../ClangTidy.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+namespace clang {
+namespace tidy {
+namespace mpi {
+
+/// This check verifies if buffer type and MPI (Message Passing Interface)
+/// datatype pairs match. All MPI datatypes defined by the MPI standard (3.1)
+/// are verified by this check. User defined typedefs, custom MPI datatypes and
+/// null pointer constants are skipped, in the course of verification.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/mpi-type-mismatch.html
+class TypeMismatchCheck : public ClangTidyCheck {
+public:
+ TypeMismatchCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+ /// Check if the buffer type MPI datatype pairs match.
+ ///
+ /// \param BufferTypes buffer types
+ /// \param BufferExprs buffer arguments as expressions
+ /// \param MPIDatatypes MPI datatype
+ /// \param LO language options
+ void checkArguments(ArrayRef<const Type *> BufferTypes,
+ ArrayRef<const Expr *> BufferExprs,
+ ArrayRef<StringRef> MPIDatatypes,
+ const LangOptions &LO);
+};
+
+} // namespace mpi
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MPI_TYPE_MISMATCH_H
clangTidyLLVMModule
clangTidyMiscModule
clangTidyModernizeModule
+ clangTidyMPIModule
clangTidyPerformanceModule
clangTidyReadabilityModule
clangTooling
clangTidyLLVMModule
clangTidyMiscModule
clangTidyModernizeModule
+ clangTidyMPIModule
clangTidyPerformanceModule
clangTidyReadabilityModule
clangTooling
static int LLVM_ATTRIBUTE_UNUSED ModernizeModuleAnchorDestination =
ModernizeModuleAnchorSource;
+// This anchor is used to force the linker to link the MPIModule.
+extern volatile int MPIModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED MPIModuleAnchorDestination =
+ MPIModuleAnchorSource;
+
// This anchor is used to force the linker to link the PerformanceModule.
extern volatile int PerformanceModuleAnchorSource;
static int LLVM_ATTRIBUTE_UNUSED PerformanceModuleAnchorDestination =
modernize-use-nullptr
modernize-use-override
modernize-use-using
+ mpi-type-mismatch
performance-faster-string-find
performance-for-range-copy
performance-implicit-cast-in-loop
--- /dev/null
+.. title:: clang-tidy - mpi-type-mismatch
+
+mpi-type-mismatch
+=================
+
+This check verifies if buffer type and MPI (Message Passing Interface) datatype
+pairs match for used MPI functions. All MPI datatypes defined by the MPI
+standard (3.1) are verified by this check. User defined typedefs, custom MPI
+datatypes and null pointer constants are skipped, in the course of verification.
+
+Example:
+.. code:: c++
+ // In this case, the buffer type matches MPI datatype.
+ char buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+ // In the following case, the buffer type does not match MPI datatype.
+ int buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
--- /dev/null
+// This Message Passing Interface mock header is used, to mock typedefs,
+// constants and functions, required for integration tests being part of
+// clang-tidy MPI checks.
+
+#ifndef MPIMOCK_H
+#define MPIMOCK_H
+
+#define NULL 0
+
+// These typedefs are used to mock MPI types, fixed width integer types and the
+// templated C++ complex number type.
+typedef int MPI_Datatype;
+typedef int MPI_Comm;
+typedef int MPI_Request;
+typedef int MPI_Status;
+typedef int MPI_Op;
+typedef int int8_t;
+typedef int uint8_t;
+typedef int uint16_t;
+typedef int int64_t;
+namespace std { template<class T> struct complex { T real; T imag; }; }
+
+// These defines are used to mock MPI constants.
+#define MPI_DATATYPE_NULL 0
+#define MPI_CHAR 0
+#define MPI_BYTE 0
+#define MPI_INT 0
+#define MPI_LONG 0
+#define MPI_LONG_DOUBLE 0
+#define MPI_UNSIGNED 0
+#define MPI_INT8_T 0
+#define MPI_UINT8_T 0
+#define MPI_UINT16_T 0
+#define MPI_C_LONG_DOUBLE_COMPLEX 0
+#define MPI_FLOAT 0
+#define MPI_DOUBLE 0
+#define MPI_CXX_BOOL 0
+#define MPI_CXX_FLOAT_COMPLEX 0
+#define MPI_CXX_DOUBLE_COMPLEX 0
+#define MPI_CXX_LONG_DOUBLE_COMPLEX 0
+#define MPI_IN_PLACE 0
+#define MPI_COMM_WORLD 0
+#define MPI_STATUS_IGNORE 0
+#define MPI_STATUSES_IGNORE 0
+#define MPI_SUM 0
+
+// These declarations are used to mock MPI functions.
+int MPI_Comm_size(MPI_Comm, int *);
+int MPI_Comm_rank(MPI_Comm, int *);
+int MPI_Send(const void *, int, MPI_Datatype, int, int, MPI_Comm);
+int MPI_Recv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Status *);
+int MPI_Isend(const void *, int, MPI_Datatype, int, int, MPI_Comm,
+ MPI_Request *);
+int MPI_Irecv(void *, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request *);
+int MPI_Wait(MPI_Request *, MPI_Status *);
+int MPI_Waitall(int, MPI_Request[], MPI_Status[]);
+int MPI_Reduce(const void *, void *, int, MPI_Datatype, MPI_Op, int, MPI_Comm);
+int MPI_Ireduce(const void *, void *, int, MPI_Datatype, MPI_Op, int, MPI_Comm,
+ MPI_Request *);
+int MPI_Bcast(void *, int count, MPI_Datatype, int, MPI_Comm);
+
+#endif // end of include guard: MPIMOCK_H
--- /dev/null
+// RUN: %check_clang_tidy %s mpi-type-mismatch %t -- -- -I %S/Inputs/mpi-type-mismatch
+
+#include "mpimock.h"
+
+void charNegativeTest() {
+ unsigned char buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned char' does not match the MPI datatype 'MPI_CHAR' [mpi-type-mismatch]
+
+ int buf2;
+ MPI_Send(&buf2, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int' does not match the MPI datatype 'MPI_CHAR'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_CHAR'
+
+ long buf4;
+ MPI_Send(&buf4, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long' does not match the MPI datatype 'MPI_CHAR'
+
+ int8_t buf5;
+ MPI_Send(&buf5, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_CHAR'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_CHAR'
+
+ long double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_CHAR'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_CHAR'
+}
+
+void intNegativeTest() {
+ unsigned char buf;
+ MPI_Send(&buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned char' does not match the MPI datatype 'MPI_INT'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_INT'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_INT'
+
+ long buf4;
+ MPI_Send(&buf4, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long' does not match the MPI datatype 'MPI_INT'
+
+ int8_t buf5;
+ MPI_Send(&buf5, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_INT'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_INT'
+
+ long double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_INT'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_INT'
+}
+
+void longNegativeTest() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_LONG'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_LONG'
+
+ unsigned short buf3;
+ MPI_Send(&buf3, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned short' does not match the MPI datatype 'MPI_LONG'
+
+ unsigned long buf4;
+ MPI_Send(&buf4, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_LONG'
+
+ int8_t buf5;
+ MPI_Send(&buf5, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'int8_t' does not match the MPI datatype 'MPI_LONG'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_LONG'
+
+ long double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_LONG'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_LONG'
+}
+
+void int8_tNegativeTest() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_INT8_T'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_INT8_T'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_INT8_T'
+
+ unsigned long buf4;
+ MPI_Send(&buf4, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_INT8_T'
+
+ uint8_t buf5;
+ MPI_Send(&buf5, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_INT8_T'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_INT8_T'
+
+ long double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'long double _Complex' does not match the MPI datatype 'MPI_INT8_T'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_INT8_T'
+}
+
+void complex_c_long_double_complexNegativeTest() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ unsigned long buf4;
+ MPI_Send(&buf4, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ uint8_t buf5;
+ MPI_Send(&buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'double _Complex' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+
+ std::complex<float> buf8;
+ MPI_Send(&buf8, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<float>' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'
+}
+
+void complex_cxx_float_complexNegativeTest() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'char' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ unsigned buf2;
+ MPI_Send(&buf2, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned int' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ short buf3;
+ MPI_Send(&buf3, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'short' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ unsigned long buf4;
+ MPI_Send(&buf4, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'unsigned long' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ uint8_t buf5;
+ MPI_Send(&buf5, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint8_t' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ uint16_t buf6;
+ MPI_Send(&buf6, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'uint16_t' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ double _Complex buf7;
+ MPI_Send(&buf7, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'double _Complex' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+
+ std::complex<double> buf8;
+ MPI_Send(&buf8, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+ // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: buffer type 'complex<double>' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'
+}
+
+void skippedTypesTests() {
+ // typedefs, user defined MPI and nullptr types are skipped
+ typedef char CHAR;
+ CHAR buf;
+ MPI_Send(&buf, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ typedef unsigned UNSIGNED;
+ UNSIGNED buf2;
+ MPI_Send(&buf2, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+#define _MPI_LONG MPI_LONG
+ int buf3;
+ MPI_Send(&buf3, 1, _MPI_LONG, 0, 0, MPI_COMM_WORLD);
+
+#define _MPI_CXX_FLOAT_COMPLEX MPI_CXX_FLOAT_COMPLEX
+ short buf4;
+ MPI_Send(&buf4, 1, _MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ MPI_Send(NULL, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+}
+
+void positiveTests() {
+ char buf;
+ MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
+
+ int buf2;
+ MPI_Send(&buf2, 1, MPI_INT, 0, 0, MPI_COMM_WORLD);
+
+ long buf3;
+ MPI_Send(&buf3, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD);
+
+ int8_t buf4;
+ MPI_Send(&buf4, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD);
+
+ long double _Complex buf5;
+ MPI_Send(&buf5, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ std::complex<float> buf6;
+ MPI_Send(&buf6, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD);
+
+ uint8_t buf7;
+ MPI_Send(&buf7, 1, MPI_UINT8_T, 0, 0, MPI_COMM_WORLD);
+
+ uint16_t buf8;
+ MPI_Send(&buf8, 1, MPI_UINT16_T, 0, 0, MPI_COMM_WORLD);
+}