Пример #1
0
bool ExprTypeAnalyser::checkEnumCast(const ExplicitCastExpr* expr, QualType DestType, QualType SrcType) {
    // by now: DestType is: Bool, Integer, Function or Enum
    switch (DestType->getTypeClass()) {
    case TC_BUILTIN:
        return true;    // allow
    case TC_POINTER:
    case TC_ARRAY:
    case TC_UNRESOLVED:
    case TC_ALIAS:
    case TC_STRUCT:
        assert(0 && "should not come here");
        return false;
    case TC_ENUM:
        return true;    // allow
    case TC_FUNCTION:
        break;          // deny
    case TC_MODULE:
        assert(0 && "should not come here");
        return false;
    }
    StringBuilder buf1(MAX_LEN_TYPENAME);
    StringBuilder buf2(MAX_LEN_TYPENAME);
    SrcType.DiagName(buf1);
    DestType.DiagName(buf2);
    Diags.Report(expr->getLocation(), diag::err_illegal_cast)
            << buf1 << buf2 << expr->getSourceRange();
    return false;
}
Пример #2
0
void ExprTypeAnalyser::error(SourceLocation loc, QualType left, QualType right) const {
    StringBuilder buf1(MAX_LEN_TYPENAME);
    StringBuilder buf2(MAX_LEN_TYPENAME);
    right.DiagName(buf1);
    left.DiagName(buf2);
    // TODO error msg depends on conv type (see clang errors)
    Diags.Report(loc, diag::err_illegal_type_conversion)
            << buf1 << buf2;

}
Пример #3
0
bool ExprTypeAnalyser::checkExplicitCast(const ExplicitCastExpr* expr, QualType DestType, QualType SrcType) {
    // C99 6.5.4p2: the cast type needs to be void or scalar and the expression

    if (!DestType.isScalarType()) {
        // Dont allow any cast to non-scalar
        StringBuilder buf1(MAX_LEN_TYPENAME);
        StringBuilder buf2(MAX_LEN_TYPENAME);
        DestType.DiagName(buf1);
        SrcType.DiagName(buf2);
        Diags.Report(expr->getLocation(), diag::err_typecheck_cond_expect_scalar)
                << buf1 << buf2 << expr->getSourceRange();
        return false;
    }

    // If either type is a pointer, the other type has to be either an
    // integer or a pointer
    // TODO decide if Enums are arithmatic types or not (they are in C99, not is C++0x)
    if (DestType.isPointerType()) {
        if (SrcType.isPointerType()) {
            // allow all pointer casts
            return true;
        } else {
            // only allow cast to pointer from uint32/64 (pointer size)
            const BuiltinType* BT = dyncast<BuiltinType>(SrcType.getCanonicalType());
            // TODO use TargetInfo to check if 32-bit
            if (BT && BT->getKind() == BuiltinType::UInt64) return true;

            QualType expected = Type::UInt64();
            StringBuilder buf1(MAX_LEN_TYPENAME);
            expected.DiagName(buf1);
            Diags.Report(expr->getLocation(), diag::err_cast_nonword_to_pointer) << buf1;
        }
    } else {
        if (SrcType.isPointerType()) {
            // only allow cast to uint32/64 (pointer size)
            const BuiltinType* BT = dyncast<BuiltinType>(DestType.getCanonicalType());
            // TODO use TargetInfo to check if 32-bit
            if (BT && BT->getKind() == BuiltinType::UInt64) return true;

            QualType expected = Type::UInt64();
            StringBuilder buf1(MAX_LEN_TYPENAME);
            expected.DiagName(buf1);
            Diags.Report(expr->getLocation(), diag::err_cast_pointer_to_nonword) << buf1;
        } else {
            // check non-pointer to non-pointer type
            // TODO make this top level function? (switch on src-type)
            return checkNonPointerCast(expr, DestType, SrcType);
        }
    }
    return false;
}
Пример #4
0
bool ExprTypeAnalyser::checkFunctionCast(const ExplicitCastExpr* expr, QualType DestType, QualType SrcType) {
    switch (DestType->getTypeClass()) {
    case TC_BUILTIN:
    {
        // TODO duplicate code
        // only allow cast to uint32/64 (pointer size)
        const BuiltinType* BT = dyncast<BuiltinType>(DestType.getCanonicalType());
        // TODO use TargetInfo to check if 32-bit
        if (BT && BT->getKind() == BuiltinType::UInt64) return true;

        QualType expected = Type::UInt64();
        StringBuilder buf1(MAX_LEN_TYPENAME);
        expected.DiagName(buf1);
        // TODO use  warn_int_to_void_pointer_cast, remove err_cast_pointer_to_nonword
        Diags.Report(expr->getLocation(), diag::err_cast_pointer_to_nonword) << buf1;
        return false;
    }
    case TC_POINTER:
    case TC_ARRAY:
    case TC_UNRESOLVED:
    case TC_ALIAS:
    case TC_STRUCT:
        assert(0 && "should not come here");
        return false;
    case TC_ENUM:
        break;          // deny
    case TC_FUNCTION:
    {
        // Always allow TEMP
        return true;
/*
        // check other function proto, allow if same
        const FunctionType* src = cast<FunctionType>(SrcType);
        const FunctionType* dest = cast<FunctionType>(DestType);
        if (FunctionType::sameProto(src, dest)) return true;
        break;  // deny
*/
    }
    case TC_MODULE:
        assert(0 && "should not come here");
        return false;
    }
    StringBuilder buf1(MAX_LEN_TYPENAME);
    StringBuilder buf2(MAX_LEN_TYPENAME);
    SrcType.DiagName(buf1);
    DestType.DiagName(buf2);
    Diags.Report(expr->getLocation(), diag::err_illegal_cast)
            << buf1 << buf2 << expr->getSourceRange();
    return false;
}
Пример #5
0
bool TypeResolver::requireCompleteType(SourceLocation loc, QualType Q, int msg) {
    if (Q.isIncompleteType()) {
        StringBuilder name;
        Q.DiagName(name);
        Diags.Report(loc, msg) << name;
        return false;
    }
    return true;
}
Пример #6
0
bool ExprTypeAnalyser::checkNonPointerCast(const ExplicitCastExpr* expr, QualType DestType, QualType SrcType) {
    // by now: DestType isScalar(): Bool, Arithmetic, Function or Enum

    QualType C = SrcType.getCanonicalType();
    switch (C->getTypeClass()) {
    case TC_BUILTIN:
        return checkBuiltinCast(expr, DestType, SrcType);
    case TC_POINTER:
        assert(0 && "should not come here");
        return false;
    case TC_ARRAY:
        // TODO
        break;
    case TC_UNRESOLVED:
        // TODO
        break;
    case TC_ALIAS:
        // TODO
        break;
    case TC_STRUCT:
        // no casts allowed
        break;
    case TC_ENUM:
        return checkEnumCast(expr, DestType, SrcType);
    case TC_FUNCTION:
        return checkFunctionCast(expr, DestType, SrcType);
    case TC_MODULE:
        // no casts allowed
        break;
    }

    // TODO refactor duplicate code (after completion)
    StringBuilder buf1(MAX_LEN_TYPENAME);
    StringBuilder buf2(MAX_LEN_TYPENAME);
    SrcType.DiagName(buf1);
    DestType.DiagName(buf2);
    Diags.Report(expr->getLocation(), diag::err_illegal_cast)
            << buf1 << buf2 << expr->getSourceRange();
    return false;
}
Пример #7
0
bool LiteralAnalyser::checkRange(QualType TLeft, const Expr* Right, clang::SourceLocation Loc, llvm::APSInt Result) {
    // TODO refactor with check()
    const QualType QT = TLeft.getCanonicalType();
    int availableWidth = 0;
    if (QT.isBuiltinType()) {
        const BuiltinType* TL = cast<BuiltinType>(QT);
        if (!TL->isInteger()) {
            // TODO floats
            return false;
        }
        availableWidth = TL->getIntegerWidth();
    } else {
        QT.dump();
        assert(0 && "todo");
    }

    const Limit* L = getLimit(availableWidth);
    assert(Result.isSigned() && "TEMP FOR NOW");
    int64_t value = Result.getSExtValue();
    bool overflow = false;
    if (Result.isNegative()) {
        const int64_t limit = L->minVal;
        if (value < limit) overflow = true;
    } else {
        const int64_t limit = (int64_t)L->maxVal;
        if (value > limit) overflow = true;
    }
    //fprintf(stderr, "VAL=%lld  width=%d signed=%d\n", value, availableWidth, Result.isSigned());
    if (overflow) {
        SmallString<20> ss;
        Result.toString(ss, 10, true);

        StringBuilder buf1;
        TLeft->DiagName(buf1);

        if (Right) {
            Diags.Report(Right->getLocStart(), diag::err_literal_outofbounds)
                    << buf1 << L->minStr << L->maxStr << ss << Right->getSourceRange();
        } else {
            Diags.Report(Loc, diag::err_literal_outofbounds)
                    << buf1 << L->minStr << L->maxStr << ss;
        }
        return false;
    }
    return true;
}
Пример #8
0
bool LiteralAnalyser::calcWidth(QualType TLeft, const Expr* Right, int* availableWidth) {
    const QualType QT = TLeft.getCanonicalType();
    // TODO check if type is already ok?, then skip check?
    //if (QT == Right->getType().getCanonicalType()) return;
    if (QT.isBuiltinType()) {
        const BuiltinType* TL = cast<BuiltinType>(QT);
        if (!TL->isInteger()) {
            // TODO floats
            return false;
        }
        // TODO remove const cast
        Expr* EE = const_cast<Expr*>(Right);
        QualType Canon = EE->getType().getCanonicalType();
        assert(Canon->isBuiltinType());
        const BuiltinType* BI = cast<BuiltinType>(Canon);
        if (TL->getKind() != BI->getKind()) EE->setImpCast(TL->getKind());
        if (QT == Type::Bool()) {
            // NOTE: any integer to bool is ok
            return false;
        }

        *availableWidth = TL->getIntegerWidth();
    } else if (QT.isPointerType()) {
        *availableWidth = 32;    // only 32-bit for now
        // dont ask for pointer, replace with uint32 here.
    } else {
        StringBuilder t1name(128);
        Right->getType().DiagName(t1name);
        // Q: allow FuncPtr to return 0? (or nil?)
        StringBuilder t2name(128);
        TLeft->DiagName(t2name);
        Diags.Report(Right->getLocation(), diag::err_typecheck_convert_incompatible) << t1name << t2name << 2 << 0 << 0;
        return false;
        //QT.dump();
        //assert(0 && "todo");
    }

    return true;
}
Пример #9
0
void LiteralAnalyser::check(QualType TLeft, const Expr* Right) {
    if (Right->getCTC() == CTC_NONE) return;
    // TODO assert here instead of check?


    // special case for assignments to enums
    if (TLeft.isEnumType()) {
        // dont check value if right is also same enum type
        if (TLeft == Right->getType()) return;

        // TODO should be done elsewhere (checking if conversion is allowed)
        fprintf(stderr, "TODO refactor checking!!, type conversion not allowed\n");
#if 0
        // this part should be used when checking casting CTC's to Enum types
        APSInt Result = checkLiterals(Right);

        // check if value has matching enum constant
        const EnumType* ET = cast<EnumType>(TLeft.getTypePtr());
        const EnumTypeDecl* ETD = ET->getDecl();
        assert(ETD);
        if (!ETD->hasConstantValue(Result)) {
            fprintf(stderr, "NO SUCH CONSTANT\n");

        }
#endif
        return;
    }

    int availableWidth = 0;
    if (!calcWidth(TLeft, Right, &availableWidth)) return;

    StringBuilder tname(128);
    TLeft->DiagName(tname);
    const Limit* L = getLimit(availableWidth);
    checkWidth(availableWidth, L, Right, tname);
}
Пример #10
0
bool ExprTypeAnalyser::checkBuiltin(QualType left, QualType right, const Expr* expr, bool first) const {
    const BuiltinType* Left = cast<BuiltinType>(left.getCanonicalType());

    // left is builtin
    QualType C = right.getCanonicalType();
    switch (C->getTypeClass()) {
    case TC_BUILTIN:
    {
        // NOTE: canonical is builtin, var itself my be UnresolvedType etc
        const BuiltinType* Right = cast<BuiltinType>(right.getCanonicalType());
        int rule = type_conversions[Right->getKind()][Left->getKind()];
        // 0 = ok, 1 = loss of precision, 2 sign-conversion, 3=float->integer, 4 incompatible, 5 loss of FP prec.
        // TODO use matrix with allowed conversions: 3 options: ok, error, warn
        int errorMsg = 0;

        if (first) {
            if (Right->getKind() != Left->getKind()) {
                // add Implicit Cast
                // TODO remove const cast
                Expr* E = const_cast<Expr*>(expr);
                E->setImpCast(Left->getKind());
            }
            if (rule == 1) {
                QualType Q = TypeFinder::findType(expr);
                return checkBuiltin(left, Q, expr, false);
            }
        }

        switch (rule) {
        case 0:
            return true;
        case 1: // loss of precision
            errorMsg = diag::warn_impcast_integer_precision;
            break;
        case 2: // sign-conversion
            errorMsg = diag::warn_impcast_integer_sign;
            break;
        case 3: // float->integer
            errorMsg = diag::warn_impcast_float_integer;
            break;
        case 4: // incompatible
            errorMsg = diag::err_illegal_type_conversion;
            break;
        case 5: // loss of fp-precision
            errorMsg = diag::warn_impcast_float_precision;
            break;
        default:
            assert(0 && "should not come here");
            break;
        }
        StringBuilder buf1(MAX_LEN_TYPENAME);
        StringBuilder buf2(MAX_LEN_TYPENAME);
        right.DiagName(buf1);
        left.DiagName(buf2);
        // TODO error msg depends on conv type (see clang errors)
        Diags.Report(expr->getLocation(), errorMsg) << buf1 << buf2
                << expr->getSourceRange();
        return false;
    }
    case TC_POINTER:
        // allow implicit cast to bool if(ptr), TODO other cases
        if (Left->getKind() == BuiltinType::Bool) return true;
        break;
    case TC_ARRAY:
        break;
    case TC_UNRESOLVED:
        break;
    case TC_ALIAS:
        break;
    case TC_STRUCT:
        break;
    case TC_ENUM:
        break;
    case TC_FUNCTION:
        break;
    case TC_MODULE:
        break;
    }
    error(expr->getLocation(), left, right);
    return false;
}
Пример #11
0
bool ExprTypeAnalyser::checkBuiltinCast(const ExplicitCastExpr* expr, QualType DestType, QualType SrcType) {
    // by now: DestType isScalar(): Bool, Arithmetic, Function or Enum
    const BuiltinType* Right = cast<BuiltinType>(SrcType.getCanonicalType());

    QualType C = DestType.getCanonicalType();
    switch (C->getTypeClass()) {
    case TC_BUILTIN:
    {
        const BuiltinType* Left = cast<BuiltinType>(DestType.getCanonicalType());
        int rule = type_conversions[Right->getKind()][Left->getKind()];
        switch (rule) {
        case 0:
        case 1: // loss of precision
        case 2: // sign-conversion
        case 3: // float->integer
            break;
        case 4: // incompatible
        {
            StringBuilder buf1(MAX_LEN_TYPENAME);
            StringBuilder buf2(MAX_LEN_TYPENAME);
            DestType.DiagName(buf1);
            SrcType.DiagName(buf2);
            Diags.Report(expr->getLocation(), diag::err_illegal_cast)
                    << buf1 << buf2 << expr->getSourceRange();
            return false;
        }
        case 5: // loss of fp-precision
            break;
        default:
            assert(0 && "should not come here");
        }
        return true;
    }
    case TC_POINTER:
        assert(0 && "should not come here");
        return false;
    case TC_ARRAY:
        // TODO
        break;
    case TC_UNRESOLVED:
    case TC_ALIAS:
    case TC_STRUCT:
    case TC_ENUM:
        assert(0 && "should not come here");
        return false;
    case TC_FUNCTION:
        // only allow if uint32/64 (ptr size)
        // TODO use TargetInfo to check if 32-bit
        if (Right->getKind() != BuiltinType::UInt64) {
            StringBuilder buf1(MAX_LEN_TYPENAME);
            SrcType.DiagName(buf1);
            StringBuilder buf2(MAX_LEN_TYPENAME);
            DestType.DiagName(buf2);
            Diags.Report(expr->getLocation(), diag::warn_int_to_pointer_cast) << buf1 << buf2;
            return false;
        }
        break;
    case TC_MODULE:
        assert(0 && "should not come here");
        return false;
    }
    return true;
}