Exemple #1
0
/**
 * 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);
}
Exemple #2
0
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;
}
Exemple #3
0
/**
 * Checks if buffer type and specified mpi datatype matches.
 *
 * @param mpiCall call to check type correspondence for
 */
void MPICheckerAST::checkBufferTypeMatch(
    const clang::CallExpr *const mpiCall) const {
    // one pair consists of {bufferIdx, mpiDatatypeIdx}
    IndexPairs indexPairs = bufferDataTypeIndices(mpiCall);

    // for every buffer mpi-data pair in function
    // check if their types match
    for (const auto &idxPair : indexPairs) {
        auto bufferType =
            mpiCall->getArg(idxPair.first)->IgnoreImpCasts()->getType();

        // collect buffer type information
        const mpi::TypeVisitor typeVisitor {
            bufferType
        };

        // get mpi datatype as string
        StringRef mpiDatatypeString{util::sourceRangeAsStringRef(
                                        mpiCall->getArg(idxPair.second)->getSourceRange(),
                                        analysisManager_)};

        // check if buffer is correctly referenced
        if (typeVisitor.pointerCount() != 1) {
            bugReporter_.reportIncorrectBufferReferencing(
                mpiCall, idxPair, bufferType, typeVisitor.pointerCount());
        }

        // MPI_BYTE needs no matching
        if (mpiDatatypeString == "MPI_BYTE") return;

        // if MPI type not known
        if (!cont::isContained(mpiTypes_, mpiDatatypeString)) return;

        selectTypeMatcher(typeVisitor, mpiCall, mpiDatatypeString, idxPair);
    }
}
Exemple #4
0
bool MPICheckerAST::matchExactWidthType(
    const mpi::TypeVisitor &visitor, const llvm::StringRef mpiDatatype) const {
    // check typedef type match
    // no break needs to be specified for string switch
    bool isTypeMatching = llvm::StringSwitch<bool>(visitor.typedefTypeName())
                          .Case("int8_t", (mpiDatatype == "MPI_INT8_T"))
                          .Case("int16_t", (mpiDatatype == "MPI_INT16_T"))
                          .Case("int32_t", (mpiDatatype == "MPI_INT32_T"))
                          .Case("int64_t", (mpiDatatype == "MPI_INT64_T"))

                          .Case("uint8_t", (mpiDatatype == "MPI_UINT8_T"))
                          .Case("uint16_t", (mpiDatatype == "MPI_UINT16_T"))
                          .Case("uint32_t", (mpiDatatype == "MPI_UINT32_T"))
                          .Case("uint64_t", (mpiDatatype == "MPI_UINT64_T"))
                          // unknown typedefs are rated as correct
                          .Default(true);

    return isTypeMatching;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
/**
 * 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");
            }
        }
    }
}