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 | f3ea8cfe6b1c2ef0702efe130561e9e66708d799 (patch) | |
tree | e846d78ad848b43259d6f6a48698f41e4f29e399 | |
parent | 81921cc4218e07363b5a0ea031fe775cba9b40c6 (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119036 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/Expr.h | 7 | ||||
-rw-r--r-- | include/clang/AST/OperationKinds.h | 19 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 14 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 9 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 7 | ||||
-rw-r--r-- | lib/CodeGen/CGExprComplex.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 21 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 158 |
9 files changed, 204 insertions, 40 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index eda2368344..950f579c51 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1998,10 +1998,15 @@ private: case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: 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: assert(path_empty() && "Cast kind should not have a base path!"); break; } diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 7cfeed2ab5..d6a7ecf43b 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -123,17 +123,32 @@ enum CastKind { /// \brief Floating point real to floating point complex CK_FloatingRealToComplex, + /// \brief Floating pointer complex to floating point real + CK_FloatingComplexToReal, + + /// \brief Converting a floating complex to bool + CK_FloatingComplexToBoolean, + /// \brief Casting between floating point complex types of different size CK_FloatingComplexCast, + /// \brief Casting from a floating complex to an integral complex + CK_FloatingComplexToIntegralComplex, + /// \brief Integral real to integral complex CK_IntegralRealToComplex, + /// \brief Integral complex to integral real + CK_IntegralComplexToReal, + + /// \brief Converting an integral complex to bool + CK_IntegralComplexToBoolean, + /// \brief Casting between integral complex types of different size CK_IntegralComplexCast, - /// \brief Casting from an integral complex to a floating complex. - CK_IntegralToFloatingComplex + /// \brief Casting from an integral complex to a floating complex + CK_IntegralComplexToFloatingComplex }; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index cc209a458a..d5bdc88ccf 100644 --- a/lib/AST/Expr.cpp +++ b/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/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 172a811bee..8a6d4ba7c4 100644 --- a/lib/AST/ExprConstant.cpp +++ b/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/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index 19238bf2af..4a1df68e5b 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/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/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 6739fd679c..3356cf46fb 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/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/lib/CodeGen/CGExprComplex.cpp b/lib/CodeGen/CGExprComplex.cpp index 637441f4e1..ad0786fd9b 100644 --- a/lib/CodeGen/CGExprComplex.cpp +++ b/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/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index 5b419c02f8..8d72e47fb8 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/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/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index b9d3d87565..687b92e21b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/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; |