示例#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 TypePrinter::Print(QualType T, std::string &S) {
  if (T.isNull()) {
    S += "NULL TYPE";
    return;
  }
  
  if (Policy.SuppressSpecifiers && T->isSpecifierType())
    return;
  
  // Print qualifiers as appropriate.
  Qualifiers Quals = T.getLocalQualifiers();
  if (!Quals.empty()) {
    std::string TQS;
    Quals.getAsStringInternal(TQS, Policy);
    
    if (!S.empty()) {
      TQS += ' ';
      TQS += S;
    }
    std::swap(S, TQS);
  }
  
  switch (T->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
#define TYPE(CLASS, PARENT) case Type::CLASS:                \
    Print##CLASS(cast<CLASS##Type>(T.getTypePtr()), S);      \
    break;
#include "clang/AST/TypeNodes.def"
  }
}
示例#3
0
QualType TypeResolver::resolveCanonical(QualType Q) const {
    if (Q->hasCanonicalType()) return Q.getCanonicalType();

    const Type* T = Q.getTypePtr();
    switch (Q->getTypeClass()) {
    case TC_BUILTIN:
        return Q;
    case TC_POINTER:
        {
            const PointerType* P = cast<PointerType>(T);
            QualType t1 = P->getPointeeType();
            // Pointee will always be in same TypeContext (file), since it's either built-in or UnresolvedType
            QualType t2 = resolveCanonical(t1);
            assert(t2.isValid());
            if (t1 == t2) {
                Q->setCanonicalType(Q);
                return Q;
            } else {
                // TODO qualifiers
                QualType Canon = typeContext.getPointerType(t2);
                if (!Canon->hasCanonicalType()) Canon->setCanonicalType(Canon);
                Q->setCanonicalType(Canon);
                return Canon;
            }
        }
    case TC_ARRAY:
        {
            const ArrayType* A = cast<ArrayType>(T);
            QualType t1 = A->getElementType();
            // NOTE: qualifiers are lost here!
            QualType t2 = resolveCanonical(t1);
            if (t1 == t2) {
                Q->setCanonicalType(Q);
                return Q;
            } else  {
                // NOTE: need size Expr, but set ownership to none
                QualType Canon = typeContext.getArrayType(t2, A->getSizeExpr(), false, A->isIncremental());
                if (!Canon->hasCanonicalType()) Canon->setCanonicalType(Canon);
                Q->setCanonicalType(Canon);
                return Canon;
            }
        }
    case TC_UNRESOLVED:
        assert(0 && "should not get here");
        return QualType();
    case TC_ALIAS:
    case TC_STRUCT:
    case TC_ENUM:
    case TC_FUNCTION:
        return Q.getCanonicalType();
    case TC_MODULE:
        assert(0 && "TBD");
        return Q;
    }
    assert(0);
}
示例#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
QualType TypeResolver::resolveUnresolved(QualType Q) const {
    const Type* T = Q.getTypePtr();
    switch (Q->getTypeClass()) {
    case TC_BUILTIN:
        return Q;
    case TC_POINTER:
        {
            // Dont return new type if not needed
            const PointerType* P = cast<PointerType>(T);
            QualType t1 = P->getPointeeType();
            QualType Result = resolveUnresolved(t1);
            if (t1 == Result) return Q;
            // TODO qualifiers
            return typeContext.getPointerType(Result);
        }
    case TC_ARRAY:
        {
            const ArrayType* A = cast<ArrayType>(T);
            QualType t1 = A->getElementType();
            QualType Result = resolveUnresolved(t1);
            if (t1 == Result) return Q;
            // TODO qualifiers
            return typeContext.getArrayType(Result, A->getSizeExpr(), false, A->isIncremental());

        }
    case TC_UNRESOLVED:
        {
            const UnresolvedType* U = cast<UnresolvedType>(T);
            TypeDecl* TD = U->getDecl();
            assert(TD);
            QualType result = TD->getType();
            if (Q.isConstQualified()) result.addConst();
            if (Q.isVolatileQualified()) result.addVolatile();
            return result;
        }
    case TC_ALIAS:
    case TC_STRUCT:
    case TC_ENUM:
    case TC_FUNCTION:
        return Q;
    case TC_MODULE:
        assert(0 && "TBD");
        return Q;
    }
    return Q;
}
示例#6
0
void MicrosoftCXXNameMangler::mangleType(QualType T) {
  // Only operate on the canonical type!
  T = getASTContext().getCanonicalType(T);
  
  Qualifiers Quals = T.getLocalQualifiers();
  if (Quals) {
    // We have to mangle these now, while we still have enough information.
    // <pointer-cvr-qualifiers> ::= P  # pointer
    //                          ::= Q  # const pointer
    //                          ::= R  # volatile pointer
    //                          ::= S  # const volatile pointer
    if (T->isAnyPointerType() || T->isMemberPointerType() ||
        T->isBlockPointerType()) {
      if (!Quals.hasVolatile())
        Out << 'Q';
      else {
        if (!Quals.hasConst())
          Out << 'R';
        else
          Out << 'S';
      }
    } else
      // Just emit qualifiers like normal.
      // NB: When we mangle a pointer/reference type, and the pointee
      // type has no qualifiers, the lack of qualifier gets mangled
      // in there.
      mangleQualifiers(Quals, false);
  } else if (T->isAnyPointerType() || T->isMemberPointerType() ||
             T->isBlockPointerType()) {
    Out << 'P';
  }
  switch (T->getTypeClass()) {
#define ABSTRACT_TYPE(CLASS, PARENT)
#define NON_CANONICAL_TYPE(CLASS, PARENT) \
case Type::CLASS: \
llvm_unreachable("can't mangle non-canonical type " #CLASS "Type"); \
return;
#define TYPE(CLASS, PARENT) \
case Type::CLASS: \
mangleType(static_cast<const CLASS##Type*>(T.getTypePtr())); \
break;
#include "clang/AST/TypeNodes.def"
  }
}
示例#7
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;
}
示例#8
0
QualType TypeResolver::checkCanonicals(Decls& decls, QualType Q, bool set) const {
    if (Q->hasCanonicalType()) return Q.getCanonicalType();

    const Type* T = Q.getTypePtr();
    switch (Q->getTypeClass()) {
    case TC_BUILTIN:
        return Q;
    case TC_POINTER:
        {
            const PointerType* P = cast<PointerType>(T);
            QualType t1 = P->getPointeeType();
            // Pointee will always be in same TypeContext (file), since it's either built-in or UnresolvedType
            QualType t2 = checkCanonicals(decls, t1, set);
            if (!t2.isValid()) return t2;
            QualType canon;
            if (t1 == t2) canon = Q;
            else {
                canon = typeContext.getPointerType(t2);
                if (!canon->hasCanonicalType()) canon->setCanonicalType(canon);
            }
            assert(Q.isValid());
            if (set) P->setCanonicalType(canon);
            return canon;
        }
    case TC_ARRAY:
        {
            const ArrayType* A = cast<ArrayType>(T);
            QualType t1 = A->getElementType();
            // NOTE: qualifiers are lost here!
            QualType t2 = checkCanonicals(decls, t1, set);
            if (!t2.isValid()) return t2;
            QualType canon;
            if (t1 == t2) canon = Q;
            // NOTE: need size Expr, but set ownership to none
            else {
                canon = typeContext.getArrayType(t2, A->getSizeExpr(), false, A->isIncremental());
                if (!canon->hasCanonicalType()) canon->setCanonicalType(canon);
            }

            if (set) A->setCanonicalType(canon);
            return canon;
        }
    case TC_UNRESOLVED:
        {
            const UnresolvedType* U = cast<UnresolvedType>(T);
            TypeDecl* TD = U->getDecl();
            assert(TD);
            // check if exists
            if (!checkDecls(decls, TD)) {
                return QualType();
            }
            QualType canonical = checkCanonicals(decls, TD->getType(), false);
            if (set) U->setCanonicalType(canonical);
            return canonical;
        }
    case TC_ALIAS:
        {
            const AliasType* A = cast<AliasType>(T);
            if (!checkDecls(decls, A->getDecl())) {
                return QualType();
            }
            QualType canonical = checkCanonicals(decls, A->getRefType(), set);
            assert(Q.isValid());
            if (set) A->setCanonicalType(canonical);
            return canonical;
        }
    case TC_STRUCT:
        return Q.getCanonicalType();
    case TC_ENUM:
        {
            assert(0 && "TODO");
            return 0;
        }
    case TC_FUNCTION:
        return Q.getCanonicalType();
    case TC_MODULE:
        assert(0 && "TBD");
        return 0;
    }
    assert(0);
}
示例#9
0
/// getOrCreateType - Get the type from the cache or create a new
/// one if necessary.
llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,
                                          llvm::DICompileUnit Unit) {
  if (Ty.isNull())
    return llvm::DIType();
  
  // Check to see if the compile unit already has created this type.
  llvm::DIType &Slot = TypeCache[Ty.getAsOpaquePtr()];
  if (!Slot.isNull()) return Slot;

  // Handle CVR qualifiers, which recursively handles what they refer to.
  if (Ty.getCVRQualifiers())
    return Slot = CreateCVRType(Ty, Unit);

  // Work out details of type.
  switch (Ty->getTypeClass()) {
#define TYPE(Class, Base)
#define ABSTRACT_TYPE(Class, Base)
#define NON_CANONICAL_TYPE(Class, Base)
#define DEPENDENT_TYPE(Class, Base) case Type::Class:
#include "clang/AST/TypeNodes.def"
    assert(false && "Dependent types cannot show up in debug information");
    
  case Type::Complex:
  case Type::LValueReference:
  case Type::RValueReference:
  case Type::Vector:
  case Type::ExtVector:
  case Type::ExtQual:
  case Type::ObjCQualifiedInterface:
  case Type::ObjCQualifiedId:
  case Type::FixedWidthInt:
  case Type::BlockPointer:
  case Type::MemberPointer:
  case Type::TemplateSpecialization:
  case Type::QualifiedName:
  case Type::ObjCQualifiedClass:
    // Unsupported types
    return llvm::DIType();

  case Type::ObjCInterface: 
    Slot = CreateType(cast<ObjCInterfaceType>(Ty), Unit); break;
  case Type::Builtin: Slot = CreateType(cast<BuiltinType>(Ty), Unit); break;
  case Type::Pointer: Slot = CreateType(cast<PointerType>(Ty), Unit); break;
  case Type::Typedef: Slot = CreateType(cast<TypedefType>(Ty), Unit); break;
  case Type::Record:
  case Type::Enum:
    Slot = CreateType(cast<TagType>(Ty), Unit); 
    break;
  case Type::FunctionProto:
  case Type::FunctionNoProto:
    return Slot = CreateType(cast<FunctionType>(Ty), Unit);
    
  case Type::ConstantArray:
  case Type::VariableArray:
  case Type::IncompleteArray:
    return Slot = CreateType(cast<ArrayType>(Ty), Unit);
  case Type::TypeOfExpr:
    return Slot = getOrCreateType(cast<TypeOfExprType>(Ty)->getUnderlyingExpr()
                                  ->getType(), Unit);
  case Type::TypeOf:
    return Slot = getOrCreateType(cast<TypeOfType>(Ty)->getUnderlyingType(),
                                  Unit);
  }
  
  return Slot;
}
示例#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;
}