diff options
Diffstat (limited to 'clang/lib/Sema/SemaExpr.cpp')
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 158 | 
1 files changed, 128 insertions, 30 deletions
| diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index b9d3d875659..687b92e21bb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -406,7 +406,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,          ImpCastExprToType(rhsExpr, lhs, CK_FloatingRealToComplex);        } else {          assert(rhs->isComplexIntegerType()); -        ImpCastExprToType(rhsExpr, lhs, CK_IntegralToFloatingComplex); +        ImpCastExprToType(rhsExpr, lhs, CK_IntegralComplexToFloatingComplex);        }        return lhs;      } @@ -420,7 +420,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,            ImpCastExprToType(lhsExpr, rhs, CK_FloatingRealToComplex);          } else {            assert(lhs->isComplexIntegerType()); -          ImpCastExprToType(lhsExpr, rhs, CK_IntegralToFloatingComplex); +          ImpCastExprToType(lhsExpr, rhs, CK_IntegralComplexToFloatingComplex);          }        }        return rhs; @@ -537,7 +537,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,        QualType result = Context.getComplexType(lhs);        // _Complex int -> _Complex float -      ImpCastExprToType(rhsExpr, result, CK_IntegralToFloatingComplex); +      ImpCastExprToType(rhsExpr, result, CK_IntegralComplexToFloatingComplex);        // float -> _Complex float        if (!isCompAssign) @@ -560,7 +560,7 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,      // _Complex int -> _Complex float      if (!isCompAssign) -      ImpCastExprToType(lhsExpr, result, CK_IntegralToFloatingComplex); +      ImpCastExprToType(lhsExpr, result, CK_IntegralComplexToFloatingComplex);      // float -> _Complex float      ImpCastExprToType(rhsExpr, result, CK_FloatingRealToComplex); @@ -4252,43 +4252,131 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,    return Owned(E);  } -static CastKind getScalarCastKind(ASTContext &Context, -                                  Expr *Src, QualType DestTy) { +enum ScalarKind { +  SK_Pointer, +  SK_Bool, +  SK_Integral, +  SK_Floating, +  SK_IntegralComplex, +  SK_FloatingComplex +}; +static ScalarKind ClassifyScalarType(QualType QT) { +  assert(QT->isScalarType()); + +  const Type *T = QT->getCanonicalTypeUnqualified().getTypePtr(); +  if (T->hasPointerRepresentation()) +    return SK_Pointer; +  if (T->isBooleanType()) +    return SK_Bool; +  if (T->isRealFloatingType()) +    return SK_Floating; +  if (const ComplexType *CT = dyn_cast<ComplexType>(T)) { +    if (CT->getElementType()->isRealFloatingType()) +      return SK_FloatingComplex; +    return SK_IntegralComplex; +  } +  assert(T->isIntegerType()); +  return SK_Integral; +} + +/// Prepares for a scalar cast, performing all the necessary stages +/// except the final cast and returning the kind required. +static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) { +  // Both Src and Dest are scalar types, i.e. arithmetic or pointer. +  // Also, callers should have filtered out the invalid cases with +  // pointers.  Everything else should be possible. +    QualType SrcTy = Src->getType(); -  if (Context.hasSameUnqualifiedType(SrcTy, DestTy)) +  if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy))      return CK_NoOp; -  if (SrcTy->hasPointerRepresentation()) { -    if (DestTy->hasPointerRepresentation()) -      return DestTy->isObjCObjectPointerType() ? -                CK_AnyPointerToObjCPointerCast : -                CK_BitCast; +  switch (ClassifyScalarType(SrcTy)) { +  case SK_Pointer:      if (DestTy->isIntegerType())        return CK_PointerToIntegral; -  } +    assert(DestTy->hasPointerRepresentation()); +    return DestTy->isObjCObjectPointerType() ? +                CK_AnyPointerToObjCPointerCast : +                CK_BitCast; -  if (SrcTy->isIntegerType()) { -    if (DestTy->isIntegerType()) -      return CK_IntegralCast; -    if (DestTy->hasPointerRepresentation()) { -      if (Src->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) +  case SK_Bool: // casting from bool is like casting from an integer +  case SK_Integral: +    switch (ClassifyScalarType(DestTy)) { +    case SK_Pointer: +      if (Src->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull))          return CK_NullToPointer;        return CK_IntegralToPointer; -    } -    if (DestTy->isRealFloatingType()) + +    case SK_Bool: // TODO: there should be an int->bool cast kind +    case SK_Integral: +      return CK_IntegralCast; +    case SK_Floating:        return CK_IntegralToFloating; -  } +    case SK_IntegralComplex: +      return CK_IntegralRealToComplex; +    case SK_FloatingComplex: +      S.ImpCastExprToType(Src, cast<ComplexType>(DestTy)->getElementType(), +                          CK_IntegralToFloating); +      return CK_FloatingRealToComplex; +    } +    break; -  if (SrcTy->isRealFloatingType()) { -    if (DestTy->isRealFloatingType()) +  case SK_Floating: +    switch (ClassifyScalarType(DestTy)) { +    case SK_Floating:        return CK_FloatingCast; -    if (DestTy->isIntegerType()) +    case SK_Bool: // TODO: there should be a float->bool cast kind +    case SK_Integral:        return CK_FloatingToIntegral; +    case SK_FloatingComplex: +      return CK_FloatingRealToComplex; +    case SK_IntegralComplex: +      S.ImpCastExprToType(Src, cast<ComplexType>(DestTy)->getElementType(), +                          CK_FloatingToIntegral); +      return CK_IntegralRealToComplex; +    case SK_Pointer: llvm_unreachable("valid float->pointer cast?"); +    } +    break; + +  case SK_FloatingComplex: +    switch (ClassifyScalarType(DestTy)) { +    case SK_FloatingComplex: +      return CK_FloatingComplexCast; +    case SK_IntegralComplex: +      return CK_FloatingComplexToIntegralComplex; +    case SK_Floating: +      return CK_FloatingComplexToReal; +    case SK_Bool: +      return CK_FloatingComplexToBoolean; +    case SK_Integral: +      S.ImpCastExprToType(Src, cast<ComplexType>(SrcTy)->getElementType(), +                          CK_FloatingComplexToReal); +      return CK_FloatingToIntegral; +    case SK_Pointer: llvm_unreachable("valid complex float->pointer cast?"); +    } +    break; + +  case SK_IntegralComplex: +    switch (ClassifyScalarType(DestTy)) { +    case SK_FloatingComplex: +      return CK_IntegralComplexToFloatingComplex; +    case SK_IntegralComplex: +      return CK_IntegralComplexCast; +    case SK_Integral: +      return CK_IntegralComplexToReal; +    case SK_Bool: +      return CK_IntegralComplexToBoolean; +    case SK_Floating: +      S.ImpCastExprToType(Src, cast<ComplexType>(SrcTy)->getElementType(), +                          CK_IntegralComplexToReal); +      return CK_IntegralToFloating; +    case SK_Pointer: llvm_unreachable("valid complex int->pointer cast?"); +    } +    break;    } -  // FIXME: Assert here. -  // assert(false && "Unhandled cast combination!"); -  return CK_Unknown; +  llvm_unreachable("Unhandled scalar cast"); +  return CK_BitCast;  }  /// CheckCastTypes - Check type constraints for casting between types. @@ -4353,6 +4441,9 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,        << castType << castExpr->getSourceRange();    } +  // The type we're casting to is known to be a scalar or vector. + +  // Require the operand to be a scalar or vector.    if (!castExpr->getType()->isScalarType() &&        !castExpr->getType()->isVectorType()) {      return Diag(castExpr->getLocStart(), @@ -4368,9 +4459,16 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,    if (castExpr->getType()->isVectorType())      return CheckVectorCast(TyR, castExpr->getType(), castType, Kind); +  // The source and target types are both scalars, i.e. +  //   - arithmetic types (fundamental, enum, and complex) +  //   - all kinds of pointers +  // Note that member pointers were filtered out with C++, above. +    if (isa<ObjCSelectorExpr>(castExpr))      return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr); +  // If either type is a pointer, the other type has to be either an +  // integer or a pointer.    if (!castType->isArithmeticType()) {      QualType castExprType = castExpr->getType();      if (!castExprType->isIntegralType(Context) &&  @@ -4385,9 +4483,9 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,          << castType << castExpr->getSourceRange();    } -  Kind = getScalarCastKind(Context, castExpr, castType); +  Kind = PrepareScalarCast(*this, castExpr, castType); -  if (Kind == CK_Unknown || Kind == CK_BitCast) +  if (Kind == CK_BitCast)      CheckCastAlign(castExpr, castType, TyR);    return false; @@ -4439,7 +4537,7 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,    QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType();    ImpCastExprToType(CastExpr, DestElemTy, -                    getScalarCastKind(Context, CastExpr, DestElemTy)); +                    PrepareScalarCast(*this, CastExpr, DestElemTy));    Kind = CK_VectorSplat;    return false; | 

