aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-11-14 08:17:51 +0000
committerJohn McCall <rjmccall@apple.com>2010-11-14 08:17:51 +0000
commitf3ea8cfe6b1c2ef0702efe130561e9e66708d799 (patch)
treee846d78ad848b43259d6f6a48698f41e4f29e399
parent81921cc4218e07363b5a0ea031fe775cba9b40c6 (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.h7
-rw-r--r--include/clang/AST/OperationKinds.h19
-rw-r--r--lib/AST/Expr.cpp14
-rw-r--r--lib/AST/ExprConstant.cpp9
-rw-r--r--lib/Checker/GRExprEngine.cpp7
-rw-r--r--lib/CodeGen/CGExpr.cpp7
-rw-r--r--lib/CodeGen/CGExprComplex.cpp2
-rw-r--r--lib/CodeGen/CGExprScalar.cpp21
-rw-r--r--lib/Sema/SemaExpr.cpp158
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;