/** * Select apprioriate function to match the buffer type against * the specified mpi datatype. * * @param typeVisitor contains information about the buffer * @param mpiCall call whose arguments are observed * @param mpiDatatypeString * @param idxPair bufferIdx, mpiDatatypeIdx */ void MPICheckerAST::selectTypeMatcher( const mpi::TypeVisitor &typeVisitor, const MPICall &mpiCall, const StringRef mpiDatatypeString, const std::pair<size_t, size_t> &idxPair) const { const clang::BuiltinType *builtinType = typeVisitor.builtinType(); bool isTypeMatching{true}; // check for exact width types (e.g. int16_t, uint32_t) if (typeVisitor.isTypedefType()) { isTypeMatching = matchExactWidthType(typeVisitor, mpiDatatypeString); } // check for complex-floating types (e.g. float _Complex) else if (typeVisitor.isComplexType()) { isTypeMatching = matchComplexType(typeVisitor, mpiDatatypeString); } // check for basic builtin types (e.g. int, char) else if (!builtinType) { return; // if no builtin type cancel checking } else if (builtinType->isBooleanType()) { isTypeMatching = matchBoolType(typeVisitor, mpiDatatypeString); } else if (builtinType->isAnyCharacterType()) { isTypeMatching = matchCharType(typeVisitor, mpiDatatypeString); } else if (builtinType->isSignedInteger()) { isTypeMatching = matchSignedType(typeVisitor, mpiDatatypeString); } else if (builtinType->isUnsignedIntegerType()) { isTypeMatching = matchUnsignedType(typeVisitor, mpiDatatypeString); } else if (builtinType->isFloatingType()) { isTypeMatching = matchFloatType(typeVisitor, mpiDatatypeString); } if (!isTypeMatching) bugReporter_.reportTypeMismatch(mpiCall.callExpr(), idxPair, typeVisitor.qualType_, mpiDatatypeString); }
bool MPICheckerAST::matchCharType(const mpi::TypeVisitor &visitor, const llvm::StringRef mpiDatatype) const { bool isTypeMatching; switch (visitor.builtinType()->getKind()) { case BuiltinType::SChar: isTypeMatching = (mpiDatatype == "MPI_CHAR" || mpiDatatype == "MPI_SIGNED_CHAR"); break; case BuiltinType::Char_S: isTypeMatching = (mpiDatatype == "MPI_CHAR" || mpiDatatype == "MPI_SIGNED_CHAR"); break; case BuiltinType::UChar: isTypeMatching = (mpiDatatype == "MPI_UNSIGNED_CHAR"); break; case BuiltinType::Char_U: isTypeMatching = (mpiDatatype == "MPI_UNSIGNED_CHAR"); break; case BuiltinType::WChar_S: isTypeMatching = (mpiDatatype == "MPI_WCHAR"); break; case BuiltinType::WChar_U: isTypeMatching = (mpiDatatype == "MPI_WCHAR"); break; default: isTypeMatching = true; } return isTypeMatching; }
/** * Check if invalid argument types are used in a mpi call. * This check looks at indices where only integer values are valid. * (count, rank, tag) Any non integer type usage is reported. * * @param mpiCall to check the arguments for */ void MPICheckerAST::checkForInvalidArgs(const MPICall &mpiCall) const { std::vector<size_t> indicesToCheck = integerIndices(mpiCall); if (!indicesToCheck.size()) return; // iterate indices which should not have integer arguments for (const size_t idx : indicesToCheck) { // check for invalid variable types const auto &arg = mpiCall.arguments()[idx]; const auto &vars = arg.vars(); for (const auto &var : vars) { const mpi::TypeVisitor typeVisitor{var->getType()}; if (!typeVisitor.builtinType() || !typeVisitor.builtinType()->isIntegerType()) { bugReporter_.reportInvalidArgumentType( mpiCall.callExpr(), idx, var->getSourceRange(), "Variable"); } } // check for float literals if (arg.floatingLiterals().size()) { bugReporter_.reportInvalidArgumentType( mpiCall.callExpr(), idx, arg.floatingLiterals().front()->getSourceRange(), "Literal"); } // check for invalid return types from functions const auto &functions = arg.functions(); for (const auto &function : functions) { const mpi::TypeVisitor typeVisitor{function->getReturnType()}; if (!typeVisitor.builtinType() || !typeVisitor.builtinType()->isIntegerType()) { bugReporter_.reportInvalidArgumentType( mpiCall.callExpr(), idx, function->getSourceRange(), "Return value"); } } } }
bool MPICheckerAST::matchFloatType(const mpi::TypeVisitor &visitor, const llvm::StringRef mpiDatatype) const { bool isTypeMatching; switch (visitor.builtinType()->getKind()) { case BuiltinType::Float: isTypeMatching = (mpiDatatype == "MPI_FLOAT"); break; case BuiltinType::Double: isTypeMatching = (mpiDatatype == "MPI_DOUBLE"); break; case BuiltinType::LongDouble: isTypeMatching = (mpiDatatype == "MPI_LONG_DOUBLE"); break; default: isTypeMatching = true; } return isTypeMatching; }
bool MPICheckerAST::matchUnsignedType(const mpi::TypeVisitor &visitor, const llvm::StringRef mpiDatatype) const { bool isTypeMatching; switch (visitor.builtinType()->getKind()) { case BuiltinType::UInt: isTypeMatching = (mpiDatatype == "MPI_UNSIGNED"); break; case BuiltinType::UShort: isTypeMatching = (mpiDatatype == "MPI_UNSIGNED_SHORT"); break; case BuiltinType::ULong: isTypeMatching = (mpiDatatype == "MPI_UNSIGNED_LONG"); break; case BuiltinType::ULongLong: isTypeMatching = (mpiDatatype == "MPI_UNSIGNED_LONG_LONG"); break; default: isTypeMatching = true; } return isTypeMatching; }