diff options
| author | John McCall <rjmccall@apple.com> | 2010-11-14 08:17:51 +0000 | 
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2010-11-14 08:17:51 +0000 | 
| commit | d764625448caf3b885b37be6bfa88f93f16cbb3c (patch) | |
| tree | 2b9c0721eb6616f64567cddfd829eff93609f298 /clang/lib | |
| parent | 2536851543ed3fd4ac60631488a2f7df61829669 (diff) | |
| download | bcm5719-llvm-d764625448caf3b885b37be6bfa88f93f16cbb3c.tar.gz bcm5719-llvm-d764625448caf3b885b37be6bfa88f93f16cbb3c.zip | |
Add a few more complex-related cast kinds that arise due to arbitrary
implicit conversions;  the last batch was specific to promotions.
I think this is the full set we need.  I do think dividing the cast
kinds into floating and integral is probably a good idea.
Annotate a *lot* more C casts with useful cast kinds.
llvm-svn: 119036
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Expr.cpp | 14 | ||||
| -rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 9 | ||||
| -rw-r--r-- | clang/lib/Checker/GRExprEngine.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprComplex.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 21 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 158 | 
7 files changed, 181 insertions, 37 deletions
| diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index cc209a458a1..d5bdc88ccfe 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -800,14 +800,24 @@ const char *CastExpr::getCastKindName() const {      return "ObjCObjectLValueCast";    case CK_FloatingRealToComplex:      return "FloatingRealToComplex"; +  case CK_FloatingComplexToReal: +    return "FloatingComplexToReal"; +  case CK_FloatingComplexToBoolean: +    return "FloatingComplexToBoolean";    case CK_FloatingComplexCast:      return "FloatingComplexCast"; +  case CK_FloatingComplexToIntegralComplex: +    return "FloatingComplexToIntegralComplex";    case CK_IntegralRealToComplex:      return "IntegralRealToComplex"; +  case CK_IntegralComplexToReal: +    return "IntegralComplexToReal"; +  case CK_IntegralComplexToBoolean: +    return "IntegralComplexToBoolean";    case CK_IntegralComplexCast:      return "IntegralComplexCast"; -  case CK_IntegralToFloatingComplex: -    return "IntegralToFloatingComplex"; +  case CK_IntegralComplexToFloatingComplex: +    return "IntegralComplexToFloatingComplex";    }    llvm_unreachable("Unhandled cast kind!"); diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 172a811bee1..8a6d4ba7c42 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2073,7 +2073,14 @@ bool FloatExprEvaluator::VisitCastExpr(CastExpr *E) {                                      Result, Info.Ctx);      return true;    } -  // FIXME: Handle complex types + +  if (E->getCastKind() == CK_FloatingComplexToReal) { +    ComplexValue V; +    if (!EvaluateComplex(SubExpr, V, Info)) +      return false; +    Result = V.getComplexFloatReal(); +    return true; +  }    return false;  } diff --git a/clang/lib/Checker/GRExprEngine.cpp b/clang/lib/Checker/GRExprEngine.cpp index 19238bf2afb..4a1df68e5be 100644 --- a/clang/lib/Checker/GRExprEngine.cpp +++ b/clang/lib/Checker/GRExprEngine.cpp @@ -2525,10 +2525,15 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,    case CK_FloatingToIntegral:    case CK_FloatingCast:    case CK_FloatingRealToComplex: +  case CK_FloatingComplexToReal: +  case CK_FloatingComplexToBoolean:    case CK_FloatingComplexCast: +  case CK_FloatingComplexToIntegralComplex:    case CK_IntegralRealToComplex: +  case CK_IntegralComplexToReal: +  case CK_IntegralComplexToBoolean:    case CK_IntegralComplexCast: -  case CK_IntegralToFloatingComplex: +  case CK_IntegralComplexToFloatingComplex:    case CK_AnyPointerToObjCPointerCast:    case CK_AnyPointerToBlockPointerCast:    case CK_DerivedToBase: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 6739fd679cf..3356cf46fbd 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -1815,10 +1815,15 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {    case CK_FloatingToIntegral:    case CK_FloatingCast:    case CK_FloatingRealToComplex: +  case CK_FloatingComplexToReal: +  case CK_FloatingComplexToBoolean:    case CK_FloatingComplexCast: +  case CK_FloatingComplexToIntegralComplex:    case CK_IntegralRealToComplex: +  case CK_IntegralComplexToReal: +  case CK_IntegralComplexToBoolean:    case CK_IntegralComplexCast: -  case CK_IntegralToFloatingComplex: +  case CK_IntegralComplexToFloatingComplex:    case CK_DerivedToBaseMemberPointer:    case CK_BaseToDerivedMemberPointer:    case CK_MemberPointerToBoolean: diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 637441f4e19..ad0786fd9b0 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -274,6 +274,8 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfComplex(llvm::Value *SrcPtr,                                                      bool isVolatile) {    llvm::Value *Real=0, *Imag=0; +  // FIXME: we should really not be suppressing volatile loads. +    if (!IgnoreReal) {      llvm::Value *RealP = Builder.CreateStructGEP(SrcPtr, 0,                                                   SrcPtr->getName() + ".realp"); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 5b419c02f8b..8d72e47fb86 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1083,7 +1083,8 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {    case CK_FloatingComplexCast:    case CK_IntegralRealToComplex:    case CK_IntegralComplexCast: -  case CK_IntegralToFloatingComplex: +  case CK_IntegralComplexToFloatingComplex: +  case CK_FloatingComplexToIntegralComplex:    case CK_ConstructorConversion:      assert(0 && "Should be unreachable!");      break; @@ -1151,6 +1152,20 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {      const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();      return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, MemPtr, MPT);    } + +  case CK_FloatingComplexToReal: +  case CK_IntegralComplexToReal: +    return CGF.EmitComplexExpr(E, false, true, false, true).first; + +  case CK_FloatingComplexToBoolean: +  case CK_IntegralComplexToBoolean: { +    CodeGenFunction::ComplexPairTy V +      = CGF.EmitComplexExpr(E, false, false, false, false); + +    // TODO: kill this function off, inline appropriate case here +    return EmitComplexToScalarConversion(V, E->getType(), DestTy); +  } +    }    // Handle cases where the source is an non-complex type. @@ -1162,8 +1177,10 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {      return EmitScalarConversion(Src, E->getType(), DestTy);    } +  // Handle cases where the source is a complex type. +  // TODO: when we're certain about cast kinds, we should just be able +  // to assert that no complexes make it here.    if (E->getType()->isAnyComplexType()) { -    // Handle cases where the source is a complex type.      bool IgnoreImag = true;      bool IgnoreImagAssign = true;      bool IgnoreReal = IgnoreResultAssign; 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; | 

