Index: clang-tidy/misc/CMakeLists.txt =================================================================== --- clang-tidy/misc/CMakeLists.txt +++ clang-tidy/misc/CMakeLists.txt @@ -4,6 +4,7 @@ ArgumentCommentCheck.cpp AssertSideEffectCheck.cpp MisplacedConstCheck.cpp + MpiTypeMismatchCheck.cpp UnconventionalAssignOperatorCheck.cpp BoolPointerImplicitConversionCheck.cpp DanglingHandleCheck.cpp Index: clang-tidy/misc/MiscTidyModule.cpp =================================================================== --- clang-tidy/misc/MiscTidyModule.cpp +++ clang-tidy/misc/MiscTidyModule.cpp @@ -13,6 +13,7 @@ #include "ArgumentCommentCheck.h" #include "AssertSideEffectCheck.h" #include "MisplacedConstCheck.h" +#include "MpiTypeMismatchCheck.h" #include "UnconventionalAssignOperatorCheck.h" #include "BoolPointerImplicitConversionCheck.h" #include "DanglingHandleCheck.h" @@ -64,6 +65,8 @@ "misc-assert-side-effect"); CheckFactories.registerCheck( "misc-misplaced-const"); + CheckFactories.registerCheck( + "misc-mpi-type-mismatch"); CheckFactories.registerCheck( "misc-unconventional-assign-operator"); CheckFactories.registerCheck( Index: clang-tidy/misc/MpiTypeMismatchCheck.h =================================================================== --- /dev/null +++ clang-tidy/misc/MpiTypeMismatchCheck.h @@ -0,0 +1,158 @@ +//===--- MpiTypeMismatchCheck.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_MISC_MPI_TYPE_MISMATCH_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MPI_TYPE_MISMATCH_H + +#include "../ClangTidy.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include +#include + +namespace clang { +namespace tidy { +namespace misc { + +/// 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 typedef, 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/misc-mpi-type-mismatch.html +class MpiTypeMismatchCheck : public ClangTidyCheck { +public: + MpiTypeMismatchCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) { + initContainers(); + } + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + void initContainers(); + void initTypedefMap(); + void initBuiltinMap(); + void initComplexCMap(); + void initComplexCXXMap(); + void initAlltypesSet(); + + /** + * Get the passed argument as a StringRef. This function is used, to obtain + * MPI datatype (tags) by their name. + * + * @param CE call expression + * @param idx argument index + * @param Result + * + * @return the argument as a string ref + */ + StringRef argumentAsStringRef( + const CallExpr *const CE, const size_t idx, + const clang::ast_matchers::MatchFinder::MatchResult &Result) const; + + /** + * Get the unqualified, dereferenced type of an argument. + * + * @param CE call expression + * @param idx argument index + * + * @return type of the argument + */ + const Type *argumentType(const CallExpr *const CE, const size_t idx) const; + + /** + * Check if the buffer type MPI datatype pairs match. + * + * @param BufferTypes buffer types + * @param MPIDatatypes MPI datatype + * @param ArgumentExpressions buffer arguments as expressions + */ + void checkArguments(const SmallVector &BufferTypes, + const SmallVector &MPIDatatypes, + const SmallVector &ArgumentExpressions); + + /** + * 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 + * + * @return true if the pair matches + */ + bool isMPITypeMatching( + const std::multimap &MultiMap, + const clang::BuiltinType::Kind Kind, + const std::string &MPIDatatype) const; + + /** + * 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 + * + * @return true if the type matches or the buffer type is unknown + */ + bool isCComplexTypeMatching(const clang::ComplexType *const Complex, + std::string &BufferTypeName, + const std::string &MPIDatatype) const; + + /** + * Check if a complex 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 + * + * @return true if the type matches or the buffer type is unknown + */ + bool isCXXComplexTypeMatching( + const clang::TemplateSpecializationType *const Template, + std::string &BufferTypeName, const std::string &MPIDatatype) const; + + /** + * 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 + * + * @return true if the type matches or the buffer type is unknown + */ + bool isTypedefTypeMatching(const clang::TypedefType *const Typedef, + std::string &BufferTypeName, + const std::string &MPIDatatype) const; + + /** + * Emit a warning in case of an error. + * + * @param ArgumentExpression buffer argument expression + * @param BufferTypeName buffer type name + * @param MPIDatatype MPI datatype name + */ + void logError(const Expr *const ArgumentExpression, StringRef BufferTypeName, + StringRef MPIDatatype); + + llvm::SmallVector MPITypes; + std::multimap BuiltinMatches; + std::multimap ComplexCMatches; + std::multimap ComplexCXXMatches; + std::map FixedWidthMatches; + std::unordered_set AllTypes; +}; + +} // namespace misc +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MPI_TYPE_MISMATCH_H Index: clang-tidy/misc/MpiTypeMismatchCheck.cpp =================================================================== --- /dev/null +++ clang-tidy/misc/MpiTypeMismatchCheck.cpp @@ -0,0 +1,302 @@ +//===--- MpiTypeMismatchCheck.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 "MpiTypeMismatchCheck.h" +#include "clang/../../lib/StaticAnalyzer/Checkers/MPI-Checker/MPIFunctionClassifier.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace misc { + +void MpiTypeMismatchCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(callExpr().bind("CE"), this); +} + +void MpiTypeMismatchCheck::initContainers() { + initTypedefMap(); + initBuiltinMap(); + initComplexCMap(); + initComplexCXXMap(); + initAlltypesSet(); +} + +void MpiTypeMismatchCheck::initTypedefMap() { + FixedWidthMatches["int8_t"] = "MPI_INT8_T"; + FixedWidthMatches["int16_t"] = "MPI_INT16_T"; + FixedWidthMatches["int32_t"] = "MPI_INT32_T"; + FixedWidthMatches["int64_t"] = "MPI_INT64_T"; + FixedWidthMatches["uint8_t"] = "MPI_UINT8_T"; + FixedWidthMatches["uint16_t"] = "MPI_UINT16_T"; + FixedWidthMatches["uint32_t"] = "MPI_UINT32_T"; + FixedWidthMatches["uint64_t"] = "MPI_UINT64_T"; +} + +void MpiTypeMismatchCheck::initBuiltinMap() { + BuiltinMatches.insert({BuiltinType::SChar, "MPI_CHAR"}); + BuiltinMatches.insert({BuiltinType::SChar, "MPI_SIGNED_CHAR"}); + BuiltinMatches.insert({BuiltinType::Char_S, "MPI_CHAR"}); + BuiltinMatches.insert({BuiltinType::Char_S, "MPI_SIGNED_CHAR"}); + BuiltinMatches.insert({BuiltinType::UChar, "MPI_UNSIGNED_CHAR"}); + BuiltinMatches.insert({BuiltinType::Char_U, "MPI_UNSIGNED_CHAR"}); + BuiltinMatches.insert({BuiltinType::WChar_S, "MPI_WCHAR"}); + BuiltinMatches.insert({BuiltinType::WChar_U, "MPI_WCHAR"}); + + BuiltinMatches.insert({BuiltinType::Bool, "MPI_C_BOOL"}); + BuiltinMatches.insert({BuiltinType::Bool, "MPI_CXX_BOOL"}); + BuiltinMatches.insert({BuiltinType::Short, "MPI_SHORT"}); + BuiltinMatches.insert({BuiltinType::Int, "MPI_INT"}); + BuiltinMatches.insert({BuiltinType::Long, "MPI_LONG"}); + BuiltinMatches.insert({BuiltinType::LongLong, "MPI_LONG_LONG"}); + BuiltinMatches.insert({BuiltinType::LongLong, "MPI_LONG_LONG_INT"}); + + BuiltinMatches.insert({BuiltinType::UShort, "MPI_UNSIGNED_SHORT"}); + BuiltinMatches.insert({BuiltinType::UInt, "MPI_UNSIGNED"}); + BuiltinMatches.insert({BuiltinType::ULong, "MPI_UNSIGNED_LONG"}); + BuiltinMatches.insert({BuiltinType::ULongLong, "MPI_UNSIGNED_LONG_LONG"}); + + BuiltinMatches.insert({BuiltinType::Float, "MPI_FLOAT"}); + BuiltinMatches.insert({BuiltinType::Double, "MPI_DOUBLE"}); + BuiltinMatches.insert({BuiltinType::LongDouble, "MPI_LONG_DOUBLE"}); +} + +void MpiTypeMismatchCheck::initComplexCMap() { + ComplexCMatches.insert({BuiltinType::Float, "MPI_C_COMPLEX"}); + ComplexCMatches.insert({BuiltinType::Float, "MPI_C_FLOAT_COMPLEX"}); + ComplexCMatches.insert({BuiltinType::Double, "MPI_C_DOUBLE_COMPLEX"}); + ComplexCMatches.insert( + {BuiltinType::LongDouble, "MPI_C_LONG_DOUBLE_COMPLEX"}); +} + +void MpiTypeMismatchCheck::initComplexCXXMap() { + ComplexCXXMatches.insert({BuiltinType::Float, "MPI_CXX_FLOAT_COMPLEX"}); + ComplexCXXMatches.insert({BuiltinType::Double, "MPI_CXX_DOUBLE_COMPLEX"}); + ComplexCXXMatches.insert( + {BuiltinType::LongDouble, "MPI_CXX_LONG_DOUBLE_COMPLEX"}); +} + +void MpiTypeMismatchCheck::initAlltypesSet() { + 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"}; +} + +bool MpiTypeMismatchCheck::isMPITypeMatching( + const std::multimap &MultiMap, + const clang::BuiltinType::Kind Kind, const std::string &MPIDatatype) const { + + bool Matches{false}; + auto ItPair = MultiMap.equal_range(Kind); + if (ItPair.first != ItPair.second) { + while (ItPair.first != ItPair.second) { + if (ItPair.first->second == MPIDatatype) { + Matches = true; + break; + } + ++ItPair.first; + } + } + return Matches; +} + +StringRef MpiTypeMismatchCheck::argumentAsStringRef( + const CallExpr *const CE, const size_t idx, + const MatchFinder::MatchResult &Result) const { + return Lexer::getSourceText( + CharSourceRange::getTokenRange(CE->getArg(idx)->getSourceRange()), + *Result.SourceManager, LangOptions()); +} + +const Type *MpiTypeMismatchCheck::argumentType(const CallExpr *const CE, + const size_t idx) const { + const clang::QualType QT = CE->getArg(idx)->IgnoreImpCasts()->getType(); + if (QT.getTypePtr()->isArrayType()) { + return QT.getTypePtr()->getArrayElementTypeNoTypeQual(); + } else if (QT.getTypePtr()->isPointerType()) { + return QT.getTypePtr()->getPointeeType()->getBaseElementTypeUnsafe(); + } else { + return (const Type *)nullptr; + } +} + +void MpiTypeMismatchCheck::check(const MatchFinder::MatchResult &Result) { + static ento::mpi::MPIFunctionClassifier FuncClassifier{*Result.Context}; + const CallExpr *const CE = Result.Nodes.getNodeAs("CE"); + if (!CE->getDirectCallee()) + return; + + const IdentifierInfo *Identifier = CE->getDirectCallee()->getIdentifier(); + if (!Identifier || !FuncClassifier.isMPIType(Identifier)) + return; + + SmallVector BufferTypes; + SmallVector MPIDatatypes; + SmallVector ArgumentExpr; + + auto addPair = [&](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) || + argumentAsStringRef(CE, BufferIdx, Result) == "MPI_IN_PLACE") + return; + // Skip unknown MPI datatypes and void pointer. + StringRef MPIDatatype = argumentAsStringRef(CE, DatatypeIdx, Result); + const Type *ArgType = argumentType(CE, BufferIdx); + if (AllTypes.find(MPIDatatype) == AllTypes.end() || ArgType->isVoidType()) + return; + + ArgumentExpr.push_back(CE->getArg(BufferIdx)); + BufferTypes.push_back(ArgType); + MPIDatatypes.push_back(MPIDatatype); + }; + + // Collect pairs. + 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, MPIDatatypes, ArgumentExpr); +} + +bool MpiTypeMismatchCheck::isCComplexTypeMatching( + const clang::ComplexType *const Complex, std::string &BufferTypeName, + const std::string &MPIDatatype) const { + + const clang::BuiltinType *const Builtin = + Complex->getElementType().getTypePtr()->getAs(); + if (Builtin) { + BufferTypeName = + (llvm::Twine(Builtin->getName(LangOptions())) + " _Complex").str(); + return isMPITypeMatching(ComplexCMatches, Builtin->getKind(), MPIDatatype); + } + return true; +} + +bool MpiTypeMismatchCheck::isCXXComplexTypeMatching( + const clang::TemplateSpecializationType *const Template, + std::string &BufferTypeName, const std::string &MPIDatatype) const { + + if (Template->getAsCXXRecordDecl()->getNameAsString() != "complex") + return true; + + const clang::BuiltinType *const Builtin = + Template->getArg(0).getAsType().getTypePtr()->getAs(); + if (Builtin) { + BufferTypeName = + (llvm::Twine("complex<") + Builtin->getName(LangOptions()) + ">").str(); + return isMPITypeMatching(ComplexCXXMatches, Builtin->getKind(), + MPIDatatype); + } + return true; +} + +bool MpiTypeMismatchCheck::isTypedefTypeMatching( + const clang::TypedefType *const Typedef, std::string &BufferTypeName, + const std::string &MPIDatatype) const { + + StringRef TypedefName = Typedef->getDecl()->getQualifiedNameAsString(); + BufferTypeName = TypedefName; + // Check if the typedef is known. + if (FixedWidthMatches.find(TypedefName) != FixedWidthMatches.end()) { + return FixedWidthMatches.at(TypedefName) == MPIDatatype; + } + return true; +} + +void MpiTypeMismatchCheck::logError(const Expr *const ArgumentExpression, + StringRef BufferTypeName, + StringRef MPIDatatype) { + auto Loc = ArgumentExpression->getSourceRange().getBegin(); + diag(Loc, (llvm::Twine("Buffer type '") + BufferTypeName + + "' does not match the MPI datatype '" + MPIDatatype + "'.") + .str()); +} + +void MpiTypeMismatchCheck::checkArguments( + const SmallVector &BufferTypes, + const SmallVector &MPIDatatypes, + const SmallVector &ArgumentExpressions) { + + for (size_t i = 0; i < MPIDatatypes.size(); ++i) { + const Type *BT = BufferTypes[i]; + bool Error{false}; + std::string BufferTypeName; + + // typedef + if (const clang::TypedefType *Typedef = BT->getAs()) { + Error = !isTypedefTypeMatching(Typedef, BufferTypeName, MPIDatatypes[i]); + } + // complex c type + else if (const clang::ComplexType *Complex = BT->getAs()) { + Error = !isCComplexTypeMatching(Complex, BufferTypeName, MPIDatatypes[i]); + } + // template type + else if (const clang::TemplateSpecializationType *Template = + BT->getAs()) { + Error = + !isCXXComplexTypeMatching(Template, BufferTypeName, MPIDatatypes[i]); + } + // builtin type + else if (const clang::BuiltinType *Builtin = BT->getAs()) { + BufferTypeName = Builtin->getName(LangOptions()); + Error = !isMPITypeMatching(BuiltinMatches, Builtin->getKind(), + MPIDatatypes[i]); + } + + if (Error) + logError(ArgumentExpressions[i], BufferTypeName, MPIDatatypes[i]); + } +} + +} // namespace misc +} // namespace tidy +} // namespace clang Index: docs/clang-tidy/checks/list.rst =================================================================== --- docs/clang-tidy/checks/list.rst +++ docs/clang-tidy/checks/list.rst @@ -60,12 +60,14 @@ misc-inaccurate-erase misc-incorrect-roundings misc-inefficient-algorithm + misc-m-p-i-type-mismatch misc-macro-parentheses misc-macro-repeated-side-effects misc-misplaced-const misc-misplaced-widening-cast misc-move-const-arg misc-move-constructor-init + misc-mpi-type-mismatch misc-multiple-statement-macro misc-new-delete-overloads misc-noexcept-move-constructor Index: docs/clang-tidy/checks/misc-mpi-type-mismatch.rst =================================================================== --- /dev/null +++ docs/clang-tidy/checks/misc-mpi-type-mismatch.rst @@ -0,0 +1,18 @@ +.. title:: clang-tidy - misc-mpi-type-mismatch + +misc-mpi-type-mismatch +====================== + +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 typedef, custom MPI datatypes and null pointer +constants are skipped, in the course of verification. + +Example: +// buffer type matches MPI datatype +char buf; +MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD); + +// buffer type does not match MPI datatype +int buf; +MPI_Send(&buf, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD); Index: test/clang-tidy/misc-mpi-type-mismatch.cpp =================================================================== --- /dev/null +++ test/clang-tidy/misc-mpi-type-mismatch.cpp @@ -0,0 +1,249 @@ +// RUN: %check_clang_tidy %s misc-mpi-type-mismatch %t + +// #include "clang/../../test/Analysis/MPIMock.h" +#include "/Users/lx/Documents/Text/Code/Open_Source/llvm_trunk_git/repo/tools/clang/test/Analysis/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'. [misc-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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + std::complex buf8; + MPI_Send(&buf8, 1, MPI_CHAR, 0, 0, MPI_COMM_WORLD); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Buffer type 'complex' does not match the MPI datatype 'MPI_CHAR'. [misc-mpi-type-mismatch] +} + +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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + std::complex buf8; + MPI_Send(&buf8, 1, MPI_INT, 0, 0, MPI_COMM_WORLD); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Buffer type 'complex' does not match the MPI datatype 'MPI_INT'. [misc-mpi-type-mismatch] +} + +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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + std::complex buf8; + MPI_Send(&buf8, 1, MPI_LONG, 0, 0, MPI_COMM_WORLD); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Buffer type 'complex' does not match the MPI datatype 'MPI_LONG'. [misc-mpi-type-mismatch] +} + +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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + std::complex buf8; + MPI_Send(&buf8, 1, MPI_INT8_T, 0, 0, MPI_COMM_WORLD); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Buffer type 'complex' does not match the MPI datatype 'MPI_INT8_T'. [misc-mpi-type-mismatch] +} + +void complex_c_long_double_complex_tNegativeTest() { + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + std::complex buf8; + MPI_Send(&buf8, 1, MPI_C_LONG_DOUBLE_COMPLEX, 0, 0, MPI_COMM_WORLD); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Buffer type 'complex' does not match the MPI datatype 'MPI_C_LONG_DOUBLE_COMPLEX'. [misc-mpi-type-mismatch] +} + +void complex_cxx_float_complex_tNegativeTest() { + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + 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'. [misc-mpi-type-mismatch] + + std::complex buf8; + MPI_Send(&buf8, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD); + // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: Buffer type 'complex' does not match the MPI datatype 'MPI_CXX_FLOAT_COMPLEX'. [misc-mpi-type-mismatch] +} + +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 buf6; + MPI_Send(&buf6, 1, MPI_CXX_FLOAT_COMPLEX, 0, 0, MPI_COMM_WORLD); +}