[cfe-commits] r119138 - in /cfe/trunk: include/clang/AST/Expr.h include/clang/AST/OperationKinds.h include/clang/AST/Type.h include/clang/Sema/Sema.h lib/AST/Expr.cpp lib/AST/Type.cpp lib/Checker/GRExprEngine.cpp lib/CodeGen/CGExpr.cpp lib/CodeGen/CGExprScalar.cpp lib/Sema/SemaCXXCast.cpp lib/Sema/SemaChecking.cpp lib/Sema/SemaDeclAttr.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaObjCProperty.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp
John McCall
rjmccall at apple.com
Mon Nov 15 01:13:47 PST 2010
Author: rjmccall
Date: Mon Nov 15 03:13:47 2010
New Revision: 119138
URL: http://llvm.org/viewvc/llvm-project?rev=119138&view=rev
Log:
Assorted work leading towards the elimination of CK_Unknown.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/include/clang/AST/OperationKinds.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Checker/GRExprEngine.cpp
cfe/trunk/lib/CodeGen/CGExpr.cpp
cfe/trunk/lib/CodeGen/CGExprScalar.cpp
cfe/trunk/lib/Sema/SemaCXXCast.cpp
cfe/trunk/lib/Sema/SemaChecking.cpp
cfe/trunk/lib/Sema/SemaDeclAttr.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaObjCProperty.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Mon Nov 15 03:13:47 2010
@@ -1961,7 +1961,7 @@
private:
Stmt *Op;
- void CheckBasePath() const {
+ void CheckCastConsistency() const {
#ifndef NDEBUG
switch (getCastKind()) {
case CK_DerivedToBase:
@@ -1973,17 +1973,14 @@
break;
// These should not have an inheritance path.
- case CK_Unknown:
case CK_BitCast:
case CK_LValueBitCast:
- case CK_NoOp:
case CK_Dynamic:
case CK_ToUnion:
case CK_ArrayToPointerDecay:
case CK_FunctionToPointerDecay:
case CK_NullToMemberPointer:
case CK_NullToPointer:
- case CK_UserDefinedConversion:
case CK_ConstructorConversion:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
@@ -1993,20 +1990,30 @@
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
- case CK_MemberPointerToBoolean:
case CK_AnyPointerToObjCPointerCast:
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_IntegralComplexToFloatingComplex:
+ assert(!getType()->isBooleanType() && "unheralded conversion to bool");
+ // fallthrough to check for null base path
+
+ case CK_Dependent:
+ case CK_Unknown:
+ case CK_NoOp:
+ case CK_UserDefinedConversion:
+ case CK_PointerToBoolean:
+ case CK_IntegralToBoolean:
+ case CK_FloatingToBoolean:
+ case CK_MemberPointerToBoolean:
+ case CK_FloatingComplexToBoolean:
+ case CK_IntegralComplexToBoolean:
assert(path_empty() && "Cast kind should not have a base path!");
break;
}
@@ -2029,9 +2036,10 @@
// dependent or if the subexpression is value-dependent.
ty->isDependentType() || (op && op->isValueDependent())),
Op(op) {
+ assert(kind != CK_Invalid && "creating cast with invalid cast kind");
CastExprBits.Kind = kind;
CastExprBits.BasePathSize = BasePathSize;
- CheckBasePath();
+ CheckCastConsistency();
}
/// \brief Construct an empty cast.
Modified: cfe/trunk/include/clang/AST/OperationKinds.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/OperationKinds.h?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/OperationKinds.h (original)
+++ cfe/trunk/include/clang/AST/OperationKinds.h Mon Nov 15 03:13:47 2010
@@ -25,6 +25,10 @@
/// going on.
CK_Unknown,
+ /// CK_Dependent - This explicit cast cannot yet be analyzed because
+ /// the type or expression is dependent.
+ CK_Dependent,
+
/// CK_BitCast - Used for reinterpret_cast.
CK_BitCast,
@@ -83,6 +87,9 @@
/// CK_PointerToIntegral - Pointer to integral
CK_PointerToIntegral,
+
+ /// CK_PointerToBoolean - Pointer to boolean (i.e. is not null)
+ CK_PointerToBoolean,
/// CK_ToVoid - Cast to void.
CK_ToVoid,
@@ -92,14 +99,21 @@
/// src expression into the destination expression.
CK_VectorSplat,
- /// CK_IntegralCast - Casting between integral types of different size.
+ /// CK_IntegralCast - A truncating or extending cast between integral
+ /// types of different size.
CK_IntegralCast,
+ /// CK_IntegralToBoolean - Integral to boolean.
+ CK_IntegralToBoolean,
+
/// CK_IntegralToFloating - Integral to floating point.
CK_IntegralToFloating,
/// CK_FloatingToIntegral - Floating point to integral.
CK_FloatingToIntegral,
+
+ /// CK_FloatingToBoolean - Floating point to boolean.
+ CK_FloatingToBoolean,
/// CK_FloatingCast - Casting between floating types of different size.
CK_FloatingCast,
@@ -151,6 +165,7 @@
CK_IntegralComplexToFloatingComplex
};
+#define CK_Invalid ((CastKind) -1)
enum BinaryOperatorKind {
// Operators listed in order of precedence.
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Mon Nov 15 03:13:47 2010
@@ -1123,6 +1123,18 @@
bool isTemplateTypeParmType() const; // C++ template type parameter
bool isNullPtrType() const; // C++0x nullptr_t
+ enum ScalarTypeKind {
+ STK_Pointer,
+ STK_MemberPointer,
+ STK_Bool,
+ STK_Integral,
+ STK_Floating,
+ STK_IntegralComplex,
+ STK_FloatingComplex
+ };
+ /// getScalarTypeKind - Given that this is a scalar type, classify it.
+ ScalarTypeKind getScalarTypeKind() const;
+
/// isDependentType - Whether this type is a dependent type, meaning
/// that its definition somehow depends on a template parameter
/// (C++ [temp.dep.type]).
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Nov 15 03:13:47 2010
@@ -4109,7 +4109,8 @@
/// CheckAssignmentConstraints - Perform type checking for assignment,
/// argument passing, variable initialization, and function return values.
/// This routine is only used by the following two methods. C99 6.5.16.
- AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs);
+ AssignConvertType CheckAssignmentConstraints(QualType lhs, QualType rhs,
+ CastKind &Kind);
// CheckSingleAssignmentConstraints - Currently used by
// CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking,
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Mon Nov 15 03:13:47 2010
@@ -742,6 +742,8 @@
switch (getCastKind()) {
case CK_Unknown:
return "Unknown";
+ case CK_Dependent:
+ return "Dependent";
case CK_BitCast:
return "BitCast";
case CK_LValueBitCast:
@@ -778,18 +780,24 @@
return "IntegralToPointer";
case CK_PointerToIntegral:
return "PointerToIntegral";
+ case CK_PointerToBoolean:
+ return "PointerToBoolean";
case CK_ToVoid:
return "ToVoid";
case CK_VectorSplat:
return "VectorSplat";
case CK_IntegralCast:
return "IntegralCast";
+ case CK_IntegralToBoolean:
+ return "IntegralToBoolean";
case CK_IntegralToFloating:
return "IntegralToFloating";
case CK_FloatingToIntegral:
return "FloatingToIntegral";
case CK_FloatingCast:
return "FloatingCast";
+ case CK_FloatingToBoolean:
+ return "FloatingToBoolean";
case CK_MemberPointerToBoolean:
return "MemberPointerToBoolean";
case CK_AnyPointerToObjCPointerCast:
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Mon Nov 15 03:13:47 2010
@@ -572,7 +572,8 @@
bool Type::isScalarType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
- return BT->getKind() != BuiltinType::Void && !BT->isPlaceholderType();
+ return BT->getKind() > BuiltinType::Void &&
+ BT->getKind() <= BuiltinType::NullPtr;
if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType))
// Enums are scalar types, but only if they are defined. Incomplete enums
// are not treated as scalar types.
@@ -584,6 +585,35 @@
isa<ObjCObjectPointerType>(CanonicalType);
}
+Type::ScalarTypeKind Type::getScalarTypeKind() const {
+ assert(isScalarType());
+
+ const Type *T = CanonicalType.getTypePtr();
+ if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) {
+ if (BT->getKind() == BuiltinType::Bool) return STK_Bool;
+ if (BT->getKind() == BuiltinType::NullPtr) return STK_Pointer;
+ if (BT->isInteger()) return STK_Integral;
+ if (BT->isFloatingPoint()) return STK_Floating;
+ llvm_unreachable("unknown scalar builtin type");
+ } else if (isa<PointerType>(T) ||
+ isa<BlockPointerType>(T) ||
+ isa<ObjCObjectPointerType>(T)) {
+ return STK_Pointer;
+ } else if (isa<MemberPointerType>(T)) {
+ return STK_MemberPointer;
+ } else if (isa<EnumType>(T)) {
+ assert(cast<EnumType>(T)->getDecl()->isComplete());
+ return STK_Integral;
+ } else if (const ComplexType *CT = dyn_cast<ComplexType>(T)) {
+ if (CT->getElementType()->isRealFloatingType())
+ return STK_FloatingComplex;
+ return STK_IntegralComplex;
+ }
+
+ llvm_unreachable("unknown scalar type");
+ return STK_Pointer;
+}
+
/// \brief Determines whether the type is a C++ aggregate type or C
/// aggregate or union type.
///
Modified: cfe/trunk/lib/Checker/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/GRExprEngine.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Checker/GRExprEngine.cpp Mon Nov 15 03:13:47 2010
@@ -2541,6 +2541,7 @@
return;
case CK_Unknown:
+ case CK_Dependent:
case CK_ArrayToPointerDecay:
case CK_BitCast:
case CK_LValueBitCast:
@@ -2548,8 +2549,11 @@
case CK_NullToPointer:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
+ case CK_PointerToBoolean:
+ case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
+ case CK_FloatingToBoolean:
case CK_FloatingCast:
case CK_FloatingRealToComplex:
case CK_FloatingComplexToReal:
Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Mon Nov 15 03:13:47 2010
@@ -1783,7 +1783,10 @@
switch (E->getCastKind()) {
case CK_ToVoid:
return EmitUnsupportedLValue(E, "unexpected cast lvalue");
-
+
+ case CK_Dependent:
+ llvm_unreachable("dependent cast kind in IR gen!");
+
case CK_NoOp:
if (E->getSubExpr()->Classify(getContext()).getKind()
!= Expr::Classification::CL_PRValue) {
@@ -1800,7 +1803,7 @@
return LV;
}
// Fall through to synthesize a temporary.
-
+
case CK_Unknown:
case CK_BitCast:
case CK_ArrayToPointerDecay:
@@ -1809,10 +1812,13 @@
case CK_NullToPointer:
case CK_IntegralToPointer:
case CK_PointerToIntegral:
+ case CK_PointerToBoolean:
case CK_VectorSplat:
case CK_IntegralCast:
+ case CK_IntegralToBoolean:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
+ case CK_FloatingToBoolean:
case CK_FloatingCast:
case CK_FloatingRealToComplex:
case CK_FloatingComplexToReal:
Modified: cfe/trunk/lib/CodeGen/CGExprScalar.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprScalar.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp Mon Nov 15 03:13:47 2010
@@ -110,6 +110,41 @@
/// EmitNullValue - Emit a value that corresponds to null for the given type.
Value *EmitNullValue(QualType Ty);
+ /// EmitFloatToBoolConversion - Perform an FP to boolean conversion.
+ Value *EmitFloatToBoolConversion(Value *V) {
+ // Compare against 0.0 for fp scalars.
+ llvm::Value *Zero = llvm::Constant::getNullValue(V->getType());
+ return Builder.CreateFCmpUNE(V, Zero, "tobool");
+ }
+
+ /// EmitPointerToBoolConversion - Perform a pointer to boolean conversion.
+ Value *EmitPointerToBoolConversion(Value *V) {
+ Value *Zero = llvm::ConstantPointerNull::get(
+ cast<llvm::PointerType>(V->getType()));
+ return Builder.CreateICmpNE(V, Zero, "tobool");
+ }
+
+ Value *EmitIntToBoolConversion(Value *V) {
+ // Because of the type rules of C, we often end up computing a
+ // logical value, then zero extending it to int, then wanting it
+ // as a logical value again. Optimize this common case.
+ if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(V)) {
+ if (ZI->getOperand(0)->getType() == Builder.getInt1Ty()) {
+ Value *Result = ZI->getOperand(0);
+ // If there aren't any more uses, zap the instruction to save space.
+ // Note that there can be more uses, for example if this
+ // is the result of an assignment.
+ if (ZI->use_empty())
+ ZI->eraseFromParent();
+ return Result;
+ }
+ }
+
+ const llvm::IntegerType *Ty = cast<llvm::IntegerType>(V->getType());
+ Value *Zero = llvm::ConstantInt::get(Ty, 0);
+ return Builder.CreateICmpNE(V, Zero, "tobool");
+ }
+
//===--------------------------------------------------------------------===//
// Visitor Methods
//===--------------------------------------------------------------------===//
@@ -461,11 +496,8 @@
Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");
- if (SrcType->isRealFloatingType()) {
- // Compare against 0.0 for fp scalars.
- llvm::Value *Zero = llvm::Constant::getNullValue(Src->getType());
- return Builder.CreateFCmpUNE(Src, Zero, "tobool");
- }
+ if (SrcType->isRealFloatingType())
+ return EmitFloatToBoolConversion(Src);
if (const MemberPointerType *MPT = dyn_cast<MemberPointerType>(SrcType))
return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, Src, MPT);
@@ -473,25 +505,11 @@
assert((SrcType->isIntegerType() || isa<llvm::PointerType>(Src->getType())) &&
"Unknown scalar type to convert");
- // Because of the type rules of C, we often end up computing a logical value,
- // then zero extending it to int, then wanting it as a logical value again.
- // Optimize this common case.
- if (llvm::ZExtInst *ZI = dyn_cast<llvm::ZExtInst>(Src)) {
- if (ZI->getOperand(0)->getType() ==
- llvm::Type::getInt1Ty(CGF.getLLVMContext())) {
- Value *Result = ZI->getOperand(0);
- // If there aren't any more uses, zap the instruction to save space.
- // Note that there can be more uses, for example if this
- // is the result of an assignment.
- if (ZI->use_empty())
- ZI->eraseFromParent();
- return Result;
- }
- }
+ if (isa<llvm::IntegerType>(Src->getType()))
+ return EmitIntToBoolConversion(Src);
- // Compare against an integer or pointer null.
- llvm::Value *Zero = llvm::Constant::getNullValue(Src->getType());
- return Builder.CreateICmpNE(Src, Zero, "tobool");
+ assert(isa<llvm::PointerType>(Src->getType()));
+ return EmitPointerToBoolConversion(Src);
}
/// EmitScalarConversion - Emit a conversion from the specified type to the
@@ -979,6 +997,8 @@
// a default case, so the compiler will warn on a missing case. The cases
// are in the same order as in the CastKind enum.
switch (Kind) {
+ case CK_Dependent: llvm_unreachable("dependent cast kind in IR gen!");
+
case CK_Unknown:
// FIXME: All casts should have a known kind!
//assert(0 && "Unknown cast kind!");
@@ -1134,19 +1154,27 @@
// Splat the element across to all elements
llvm::SmallVector<llvm::Constant*, 16> Args;
unsigned NumElements = cast<llvm::VectorType>(DstTy)->getNumElements();
+ llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Int32Ty, 0);
for (unsigned i = 0; i < NumElements; i++)
- Args.push_back(llvm::ConstantInt::get(CGF.Int32Ty, 0));
+ Args.push_back(Zero);
llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], NumElements);
llvm::Value *Yay = Builder.CreateShuffleVector(UnV, UnV, Mask, "splat");
return Yay;
}
+
case CK_IntegralCast:
case CK_IntegralToFloating:
case CK_FloatingToIntegral:
case CK_FloatingCast:
return EmitScalarConversion(Visit(E), E->getType(), DestTy);
+ case CK_IntegralToBoolean:
+ return EmitIntToBoolConversion(Visit(E));
+ case CK_PointerToBoolean:
+ return EmitPointerToBoolConversion(Visit(E));
+ case CK_FloatingToBoolean:
+ return EmitFloatToBoolConversion(Visit(E));
case CK_MemberPointerToBoolean: {
llvm::Value *MemPtr = Visit(E);
const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>();
Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Mon Nov 15 03:13:47 2010
@@ -157,7 +157,7 @@
<< Ex->getSourceRange();
switch (Kind) {
- default: assert(0 && "Unknown C++ cast!");
+ default: llvm_unreachable("Unknown C++ cast!");
case tok::kw_const_cast:
if (!TypeDependent)
@@ -167,7 +167,7 @@
Ex, DestTInfo, OpLoc));
case tok::kw_dynamic_cast: {
- CastKind Kind = CK_Unknown;
+ CastKind Kind = CK_Dependent;
CXXCastPath BasePath;
if (!TypeDependent)
CheckDynamicCast(*this, Ex, DestType, OpRange, DestRange, Kind, BasePath);
@@ -177,7 +177,7 @@
OpLoc));
}
case tok::kw_reinterpret_cast: {
- CastKind Kind = CK_Unknown;
+ CastKind Kind = CK_Dependent;
if (!TypeDependent)
CheckReinterpretCast(*this, Ex, DestType, OpRange, DestRange, Kind);
return Owned(CXXReinterpretCastExpr::Create(Context,
@@ -186,7 +186,7 @@
DestTInfo, OpLoc));
}
case tok::kw_static_cast: {
- CastKind Kind = CK_Unknown;
+ CastKind Kind = CK_Dependent;
CXXCastPath BasePath;
if (!TypeDependent)
CheckStaticCast(*this, Ex, DestType, OpRange, Kind, BasePath);
@@ -515,7 +515,7 @@
if (TryStaticCast(Self, SrcExpr, DestType, /*CStyle*/false, OpRange, msg,
Kind, BasePath) != TC_Success && msg != 0)
{
- if ( SrcExpr->getType() == Self.Context.OverloadTy )
+ if (SrcExpr->getType() == Self.Context.OverloadTy)
{
OverloadExpr* oe = OverloadExpr::find(SrcExpr).Expression;
Self.Diag(OpRange.getBegin(), diag::err_bad_static_cast_overload)
@@ -593,7 +593,11 @@
// C++0x 5.2.9p9: A value of a scoped enumeration type can be explicitly
// converted to an integral type.
if (Self.getLangOptions().CPlusPlus0x && SrcType->isEnumeralType()) {
- if (DestType->isIntegralType(Self.Context)) {
+ assert(SrcType->getAs<EnumType>()->getDecl()->isScoped());
+ if (DestType->isBooleanType()) {
+ Kind = CK_IntegralToBoolean;
+ return TC_Success;
+ } else if (DestType->isIntegralType(Self.Context)) {
Kind = CK_IntegralCast;
return TC_Success;
}
@@ -665,8 +669,10 @@
}
// Allow arbitray objective-c pointer conversion with static casts.
if (SrcType->isObjCObjectPointerType() &&
- DestType->isObjCObjectPointerType())
+ DestType->isObjCObjectPointerType()) {
+ Kind = CK_BitCast;
return TC_Success;
+ }
// We tried everything. Everything! Nothing works! :-(
return TC_NotApplicable;
@@ -1357,8 +1363,10 @@
}
// If the type is dependent, we won't do any other semantic analysis now.
- if (CastTy->isDependentType() || CastExpr->isTypeDependent())
+ if (CastTy->isDependentType() || CastExpr->isTypeDependent()) {
+ Kind = CK_Dependent;
return false;
+ }
if (!CastTy->isLValueReferenceType() && !CastTy->isRecordType())
DefaultFunctionArrayLvalueConversion(CastExpr);
Modified: cfe/trunk/lib/Sema/SemaChecking.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaChecking.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaChecking.cpp (original)
+++ cfe/trunk/lib/Sema/SemaChecking.cpp Mon Nov 15 03:13:47 2010
@@ -547,7 +547,7 @@
// GCC does an implicit conversion to the pointer or integer ValType. This
// can fail in some cases (1i -> int**), check for this error case now.
- CastKind Kind = CK_Unknown;
+ CastKind Kind = CK_Invalid;
CXXCastPath BasePath;
if (CheckCastTypes(Arg->getSourceRange(), ValType, Arg, Kind, BasePath))
return ExprError();
Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Mon Nov 15 03:13:47 2010
@@ -1375,7 +1375,8 @@
// If this ever proves to be a problem it should be easy to fix.
QualType Ty = S.Context.getPointerType(VD->getType());
QualType ParamTy = FD->getParamDecl(0)->getType();
- if (S.CheckAssignmentConstraints(ParamTy, Ty) != Sema::Compatible) {
+ CastKind K;
+ if (S.CheckAssignmentConstraints(ParamTy, Ty, K) != Sema::Compatible) {
S.Diag(Attr.getLoc(),
diag::err_attribute_cleanup_func_arg_incompatible_type) <<
Attr.getParameterName() << ParamTy << Ty;
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Mon Nov 15 03:13:47 2010
@@ -4252,33 +4252,6 @@
return Owned(E);
}
-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) {
@@ -4290,87 +4263,112 @@
if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy))
return CK_NoOp;
- switch (ClassifyScalarType(SrcTy)) {
- case SK_Pointer:
- if (DestTy->isIntegerType())
- return CK_PointerToIntegral;
- assert(DestTy->hasPointerRepresentation());
- return DestTy->isObjCObjectPointerType() ?
+ switch (SrcTy->getScalarTypeKind()) {
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
+
+ case Type::STK_Pointer:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_Pointer:
+ return DestTy->isObjCObjectPointerType() ?
CK_AnyPointerToObjCPointerCast :
CK_BitCast;
+ case Type::STK_Bool:
+ return CK_PointerToBoolean;
+ case Type::STK_Integral:
+ return CK_PointerToIntegral;
+ case Type::STK_Floating:
+ case Type::STK_FloatingComplex:
+ case Type::STK_IntegralComplex:
+ case Type::STK_MemberPointer:
+ llvm_unreachable("illegal cast from pointer");
+ }
+ break;
- case SK_Bool: // casting from bool is like casting from an integer
- case SK_Integral:
- switch (ClassifyScalarType(DestTy)) {
- case SK_Pointer:
+ case Type::STK_Bool: // casting from bool is like casting from an integer
+ case Type::STK_Integral:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_Pointer:
if (Src->isNullPointerConstant(S.Context, Expr::NPC_ValueDependentIsNull))
return CK_NullToPointer;
return CK_IntegralToPointer;
-
- case SK_Bool: // TODO: there should be an int->bool cast kind
- case SK_Integral:
+ case Type::STK_Bool:
+ return CK_IntegralToBoolean;
+ case Type::STK_Integral:
return CK_IntegralCast;
- case SK_Floating:
+ case Type::STK_Floating:
return CK_IntegralToFloating;
- case SK_IntegralComplex:
+ case Type::STK_IntegralComplex:
return CK_IntegralRealToComplex;
- case SK_FloatingComplex:
+ case Type::STK_FloatingComplex:
S.ImpCastExprToType(Src, cast<ComplexType>(DestTy)->getElementType(),
CK_IntegralToFloating);
return CK_FloatingRealToComplex;
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
}
break;
- case SK_Floating:
- switch (ClassifyScalarType(DestTy)) {
- case SK_Floating:
+ case Type::STK_Floating:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_Floating:
return CK_FloatingCast;
- case SK_Bool: // TODO: there should be a float->bool cast kind
- case SK_Integral:
+ case Type::STK_Bool:
+ return CK_FloatingToBoolean;
+ case Type::STK_Integral:
return CK_FloatingToIntegral;
- case SK_FloatingComplex:
+ case Type::STK_FloatingComplex:
return CK_FloatingRealToComplex;
- case SK_IntegralComplex:
+ case Type::STK_IntegralComplex:
S.ImpCastExprToType(Src, cast<ComplexType>(DestTy)->getElementType(),
CK_FloatingToIntegral);
return CK_IntegralRealToComplex;
- case SK_Pointer: llvm_unreachable("valid float->pointer cast?");
+ case Type::STK_Pointer:
+ llvm_unreachable("valid float->pointer cast?");
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
}
break;
- case SK_FloatingComplex:
- switch (ClassifyScalarType(DestTy)) {
- case SK_FloatingComplex:
+ case Type::STK_FloatingComplex:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_FloatingComplex:
return CK_FloatingComplexCast;
- case SK_IntegralComplex:
+ case Type::STK_IntegralComplex:
return CK_FloatingComplexToIntegralComplex;
- case SK_Floating:
+ case Type::STK_Floating:
return CK_FloatingComplexToReal;
- case SK_Bool:
+ case Type::STK_Bool:
return CK_FloatingComplexToBoolean;
- case SK_Integral:
+ case Type::STK_Integral:
S.ImpCastExprToType(Src, cast<ComplexType>(SrcTy)->getElementType(),
CK_FloatingComplexToReal);
return CK_FloatingToIntegral;
- case SK_Pointer: llvm_unreachable("valid complex float->pointer cast?");
+ case Type::STK_Pointer:
+ llvm_unreachable("valid complex float->pointer cast?");
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
}
break;
- case SK_IntegralComplex:
- switch (ClassifyScalarType(DestTy)) {
- case SK_FloatingComplex:
+ case Type::STK_IntegralComplex:
+ switch (DestTy->getScalarTypeKind()) {
+ case Type::STK_FloatingComplex:
return CK_IntegralComplexToFloatingComplex;
- case SK_IntegralComplex:
+ case Type::STK_IntegralComplex:
return CK_IntegralComplexCast;
- case SK_Integral:
+ case Type::STK_Integral:
return CK_IntegralComplexToReal;
- case SK_Bool:
+ case Type::STK_Bool:
return CK_IntegralComplexToBoolean;
- case SK_Floating:
+ case Type::STK_Floating:
S.ImpCastExprToType(Src, cast<ComplexType>(SrcTy)->getElementType(),
CK_IntegralComplexToReal);
return CK_IntegralToFloating;
- case SK_Pointer: llvm_unreachable("valid complex int->pointer cast?");
+ case Type::STK_Pointer:
+ llvm_unreachable("valid complex int->pointer cast?");
+ case Type::STK_MemberPointer:
+ llvm_unreachable("member pointer type in C");
}
break;
}
@@ -4565,7 +4563,7 @@
ExprResult
Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
SourceLocation RParenLoc, Expr *castExpr) {
- CastKind Kind = CK_Unknown;
+ CastKind Kind = CK_Invalid;
CXXCastPath BasePath;
if (CheckCastTypes(SourceRange(LParenLoc, RParenLoc), Ty->getType(), castExpr,
Kind, BasePath))
@@ -4772,12 +4770,12 @@
if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) &&
RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
// promote the null to a pointer.
- ImpCastExprToType(RHS, LHSTy, CK_Unknown);
+ ImpCastExprToType(RHS, LHSTy, CK_NullToPointer);
return LHSTy;
}
if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) &&
LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(LHS, RHSTy, CK_Unknown);
+ ImpCastExprToType(LHS, RHSTy, CK_NullToPointer);
return RHSTy;
}
@@ -5242,21 +5240,26 @@
/// As a result, the code for dealing with pointers is more complex than the
/// C99 spec dictates.
///
+/// Sets 'Kind' for any result kind except Incompatible.
Sema::AssignConvertType
-Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
+Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType,
+ CastKind &Kind) {
// Get canonical types. We're not formatting these types, just comparing
// them.
lhsType = Context.getCanonicalType(lhsType).getUnqualifiedType();
rhsType = Context.getCanonicalType(rhsType).getUnqualifiedType();
- if (lhsType == rhsType)
+ if (lhsType == rhsType) {
+ Kind = CK_NoOp;
return Compatible; // Common case: fast path an exact match.
+ }
if ((lhsType->isObjCClassType() &&
(rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) ||
(rhsType->isObjCClassType() &&
(lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) {
- return Compatible;
+ Kind = CK_BitCast;
+ return Compatible;
}
// If the left-hand side is a reference type, then we are in a
@@ -5267,17 +5270,21 @@
// lhsType so that the resulting expression does not have reference
// type.
if (const ReferenceType *lhsTypeRef = lhsType->getAs<ReferenceType>()) {
- if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType))
+ if (Context.typesAreCompatible(lhsTypeRef->getPointeeType(), rhsType)) {
+ Kind = CK_LValueBitCast;
return Compatible;
+ }
return Incompatible;
}
// Allow scalar to ExtVector assignments, and assignments of an ExtVector type
// to the same ExtVector type.
if (lhsType->isExtVectorType()) {
if (rhsType->isExtVectorType())
- return lhsType == rhsType ? Compatible : Incompatible;
- if (rhsType->isArithmeticType())
+ return Incompatible;
+ if (rhsType->isArithmeticType()) {
+ Kind = CK_Unknown; // FIXME: vector splat, requires two casts
return Compatible;
+ }
}
if (lhsType->isVectorType() || rhsType->isVectorType()) {
@@ -5286,48 +5293,67 @@
// vectors, the total size only needs to be the same. This is a bitcast;
// no bits are changed but the result type is different.
if (getLangOptions().LaxVectorConversions &&
- (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType)))
+ (Context.getTypeSize(lhsType) == Context.getTypeSize(rhsType))) {
+ Kind = CK_Unknown; // FIXME: vector reinterpret is... bitcast?
return IncompatibleVectors;
+ }
// Allow assignments of an AltiVec vector type to an equivalent GCC
// vector type and vice versa
- if (Context.areCompatibleVectorTypes(lhsType, rhsType))
+ if (Context.areCompatibleVectorTypes(lhsType, rhsType)) {
+ Kind = CK_Unknown; // FIXME: vector conversion
return Compatible;
+ }
}
return Incompatible;
}
if (lhsType->isArithmeticType() && rhsType->isArithmeticType() &&
- !(getLangOptions().CPlusPlus && lhsType->isEnumeralType()))
+ !(getLangOptions().CPlusPlus && lhsType->isEnumeralType())) {
+ Kind = CK_Unknown; // FIXME: reuse the cast logic if possible
return Compatible;
+ }
if (isa<PointerType>(lhsType)) {
- if (rhsType->isIntegerType())
+ if (rhsType->isIntegerType()) {
+ Kind = CK_IntegralToPointer; // FIXME: null?
return IntToPointer;
+ }
- if (isa<PointerType>(rhsType))
+ if (isa<PointerType>(rhsType)) {
+ Kind = CK_BitCast;
return CheckPointerTypesForAssignment(lhsType, rhsType);
+ }
// In general, C pointers are not compatible with ObjC object pointers.
if (isa<ObjCObjectPointerType>(rhsType)) {
+ Kind = CK_AnyPointerToObjCPointerCast;
if (lhsType->isVoidPointerType()) // an exception to the rule.
return Compatible;
return IncompatiblePointer;
}
if (rhsType->getAs<BlockPointerType>()) {
- if (lhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+ if (lhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+ Kind = CK_BitCast;
return Compatible;
+ }
// Treat block pointers as objects.
- if (getLangOptions().ObjC1 && lhsType->isObjCIdType())
+ if (getLangOptions().ObjC1 && lhsType->isObjCIdType()) {
+ Kind = CK_AnyPointerToObjCPointerCast;
return Compatible;
+ }
}
return Incompatible;
}
if (isa<BlockPointerType>(lhsType)) {
- if (rhsType->isIntegerType())
+ if (rhsType->isIntegerType()) {
+ Kind = CK_IntegralToPointer; // FIXME: null
return IntToBlockPointer;
+ }
+
+ Kind = CK_AnyPointerToObjCPointerCast;
// Treat block pointers as objects.
if (getLangOptions().ObjC1 && rhsType->isObjCIdType())
@@ -5336,16 +5362,20 @@
if (rhsType->isBlockPointerType())
return CheckBlockPointerTypesForAssignment(lhsType, rhsType);
- if (const PointerType *RHSPT = rhsType->getAs<PointerType>()) {
+ if (const PointerType *RHSPT = rhsType->getAs<PointerType>())
if (RHSPT->getPointeeType()->isVoidType())
return Compatible;
- }
+
return Incompatible;
}
if (isa<ObjCObjectPointerType>(lhsType)) {
- if (rhsType->isIntegerType())
+ if (rhsType->isIntegerType()) {
+ Kind = CK_IntegralToPointer; // FIXME: null
return IntToPointer;
+ }
+
+ Kind = CK_BitCast;
// In general, C pointers are not compatible with ObjC object pointers.
if (isa<PointerType>(rhsType)) {
@@ -5367,27 +5397,36 @@
}
if (isa<PointerType>(rhsType)) {
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
- if (lhsType == Context.BoolTy)
+ if (lhsType == Context.BoolTy) {
+ Kind = CK_PointerToBoolean;
return Compatible;
+ }
- if (lhsType->isIntegerType())
+ if (lhsType->isIntegerType()) {
+ Kind = CK_PointerToIntegral;
return PointerToInt;
-
- if (isa<PointerType>(lhsType))
- return CheckPointerTypesForAssignment(lhsType, rhsType);
+ }
if (isa<BlockPointerType>(lhsType) &&
- rhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+ rhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+ Kind = CK_AnyPointerToBlockPointerCast;
return Compatible;
+ }
return Incompatible;
}
if (isa<ObjCObjectPointerType>(rhsType)) {
// C99 6.5.16.1p1: the left operand is _Bool and the right is a pointer.
- if (lhsType == Context.BoolTy)
+ if (lhsType == Context.BoolTy) {
+ Kind = CK_PointerToBoolean;
return Compatible;
+ }
- if (lhsType->isIntegerType())
+ if (lhsType->isIntegerType()) {
+ Kind = CK_PointerToIntegral;
return PointerToInt;
+ }
+
+ Kind = CK_BitCast;
// In general, C pointers are not compatible with ObjC object pointers.
if (isa<PointerType>(lhsType)) {
@@ -5396,14 +5435,18 @@
return IncompatiblePointer;
}
if (isa<BlockPointerType>(lhsType) &&
- rhsType->getAs<PointerType>()->getPointeeType()->isVoidType())
+ rhsType->getAs<PointerType>()->getPointeeType()->isVoidType()) {
+ Kind = CK_AnyPointerToBlockPointerCast;
return Compatible;
+ }
return Incompatible;
}
if (isa<TagType>(lhsType) && isa<TagType>(rhsType)) {
- if (Context.typesAreCompatible(lhsType, rhsType))
+ if (Context.typesAreCompatible(lhsType, rhsType)) {
+ Kind = CK_NoOp;
return Compatible;
+ }
}
return Incompatible;
}
@@ -5463,9 +5506,10 @@
}
}
- if (CheckAssignmentConstraints(it->getType(), rExpr->getType())
+ CastKind Kind = CK_Invalid;
+ if (CheckAssignmentConstraints(it->getType(), rExpr->getType(), Kind)
== Compatible) {
- ImpCastExprToType(rExpr, it->getType(), CK_Unknown);
+ ImpCastExprToType(rExpr, it->getType(), Kind);
InitField = *it;
break;
}
@@ -5502,7 +5546,7 @@
lhsType->isBlockPointerType())
&& rExpr->isNullPointerConstant(Context,
Expr::NPC_ValueDependentIsNull)) {
- ImpCastExprToType(rExpr, lhsType, CK_Unknown);
+ ImpCastExprToType(rExpr, lhsType, CK_NullToPointer);
return Compatible;
}
@@ -5515,8 +5559,9 @@
if (!lhsType->isReferenceType())
DefaultFunctionArrayLvalueConversion(rExpr);
+ CastKind Kind = CK_Invalid;
Sema::AssignConvertType result =
- CheckAssignmentConstraints(lhsType, rExpr->getType());
+ CheckAssignmentConstraints(lhsType, rExpr->getType(), Kind);
// C99 6.5.16.1p2: The value of the right operand is converted to the
// type of the assignment expression.
@@ -5525,8 +5570,7 @@
// The getNonReferenceType() call makes sure that the resulting expression
// does not have reference type.
if (result != Incompatible && rExpr->getType() != lhsType)
- ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context),
- CK_Unknown);
+ ImpCastExprToType(rExpr, lhsType.getNonLValueExprType(Context), Kind);
return result;
}
@@ -5594,16 +5638,22 @@
if (const ExtVectorType *LV = lhsType->getAs<ExtVectorType>()) {
QualType EltTy = LV->getElementType();
if (EltTy->isIntegralType(Context) && rhsType->isIntegralType(Context)) {
- if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) {
- ImpCastExprToType(rex, lhsType, CK_IntegralCast);
+ int order = Context.getIntegerTypeOrder(EltTy, rhsType);
+ if (order > 0)
+ ImpCastExprToType(rex, EltTy, CK_IntegralCast);
+ if (order >= 0) {
+ ImpCastExprToType(rex, lhsType, CK_VectorSplat);
if (swapped) std::swap(rex, lex);
return lhsType;
}
}
if (EltTy->isRealFloatingType() && rhsType->isScalarType() &&
rhsType->isRealFloatingType()) {
- if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) {
- ImpCastExprToType(rex, lhsType, CK_FloatingCast);
+ int order = Context.getFloatingTypeOrder(EltTy, rhsType);
+ if (order > 0)
+ ImpCastExprToType(rex, EltTy, CK_FloatingCast);
+ if (order >= 0) {
+ ImpCastExprToType(rex, lhsType, CK_VectorSplat);
if (swapped) std::swap(rex, lex);
return lhsType;
}
@@ -6583,7 +6633,8 @@
}
} else {
// Compound assignment "x += y"
- ConvTy = CheckAssignmentConstraints(LHSType, RHSType);
+ CastKind Kind = CK_Invalid; // forgotten?
+ ConvTy = CheckAssignmentConstraints(LHSType, RHSType, Kind);
}
if (DiagnoseAssignmentResult(ConvTy, Loc, LHSType, RHSType,
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Nov 15 03:13:47 2010
@@ -604,7 +604,7 @@
// corresponding cast expression.
//
if (NumExprs == 1) {
- CastKind Kind = CK_Unknown;
+ CastKind Kind = CK_Invalid;
CXXCastPath BasePath;
if (CheckCastTypes(TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0],
Kind, BasePath,
@@ -1708,7 +1708,7 @@
case ImplicitConversionSequence::UserDefinedConversion: {
FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
- CastKind CastKind = CK_Unknown;
+ CastKind CastKind;
QualType BeforeToType;
if (const CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(FD)) {
CastKind = CK_UserDefinedConversion;
@@ -1893,9 +1893,23 @@
break;
case ICK_Complex_Promotion:
- case ICK_Complex_Conversion:
- ImpCastExprToType(From, ToType, CK_Unknown);
+ case ICK_Complex_Conversion: {
+ QualType FromEl = From->getType()->getAs<ComplexType>()->getElementType();
+ QualType ToEl = ToType->getAs<ComplexType>()->getElementType();
+ CastKind CK;
+ if (FromEl->isRealFloatingType()) {
+ if (ToEl->isRealFloatingType())
+ CK = CK_FloatingComplexCast;
+ else
+ CK = CK_FloatingComplexToIntegralComplex;
+ } else if (ToEl->isRealFloatingType()) {
+ CK = CK_IntegralComplexToFloatingComplex;
+ } else {
+ CK = CK_IntegralComplexCast;
+ }
+ ImpCastExprToType(From, ToType, CK);
break;
+ }
case ICK_Floating_Integral:
if (ToType->isRealFloatingType())
@@ -1916,9 +1930,8 @@
<< From->getType() << ToType << Action
<< From->getSourceRange();
}
-
- CastKind Kind = CK_Unknown;
+ CastKind Kind = CK_Invalid;
CXXCastPath BasePath;
if (CheckPointerConversion(From, ToType, Kind, BasePath, IgnoreBaseAccess))
return true;
@@ -1927,7 +1940,7 @@
}
case ICK_Pointer_Member: {
- CastKind Kind = CK_Unknown;
+ CastKind Kind = CK_Invalid;
CXXCastPath BasePath;
if (CheckMemberPointerConversion(From, ToType, Kind, BasePath,
IgnoreBaseAccess))
@@ -1938,9 +1951,16 @@
break;
}
case ICK_Boolean_Conversion: {
- CastKind Kind = CK_Unknown;
- if (FromType->isMemberPointerType())
- Kind = CK_MemberPointerToBoolean;
+ CastKind Kind = CK_Invalid;
+ switch (FromType->getScalarTypeKind()) {
+ case Type::STK_Pointer: Kind = CK_PointerToBoolean; break;
+ case Type::STK_MemberPointer: Kind = CK_MemberPointerToBoolean; break;
+ case Type::STK_Bool: llvm_unreachable("bool -> bool conversion?");
+ case Type::STK_Integral: Kind = CK_IntegralToBoolean; break;
+ case Type::STK_Floating: Kind = CK_FloatingToBoolean; break;
+ case Type::STK_IntegralComplex: Kind = CK_IntegralComplexToBoolean; break;
+ case Type::STK_FloatingComplex: Kind = CK_FloatingComplexToBoolean; break;
+ }
ImpCastExprToType(From, Context.BoolTy, Kind);
break;
@@ -1971,7 +1991,52 @@
break;
case ICK_Complex_Real:
- ImpCastExprToType(From, ToType, CK_Unknown);
+ // Case 1. x -> _Complex y
+ if (const ComplexType *ToComplex = ToType->getAs<ComplexType>()) {
+ QualType ElType = ToComplex->getElementType();
+ bool isFloatingComplex = ElType->isRealFloatingType();
+
+ // x -> y
+ if (Context.hasSameUnqualifiedType(ElType, From->getType())) {
+ // do nothing
+ } else if (From->getType()->isRealFloatingType()) {
+ ImpCastExprToType(From, ElType,
+ isFloatingComplex ? CK_FloatingCast : CK_FloatingToIntegral);
+ } else {
+ assert(From->getType()->isIntegerType());
+ ImpCastExprToType(From, ElType,
+ isFloatingComplex ? CK_IntegralToFloating : CK_IntegralCast);
+ }
+ // y -> _Complex y
+ ImpCastExprToType(From, ToType,
+ isFloatingComplex ? CK_FloatingRealToComplex
+ : CK_IntegralRealToComplex);
+
+ // Case 2. _Complex x -> y
+ } else {
+ const ComplexType *FromComplex = From->getType()->getAs<ComplexType>();
+ assert(FromComplex);
+
+ QualType ElType = FromComplex->getElementType();
+ bool isFloatingComplex = ElType->isRealFloatingType();
+
+ // _Complex x -> x
+ ImpCastExprToType(From, ElType,
+ isFloatingComplex ? CK_FloatingComplexToReal
+ : CK_IntegralComplexToReal);
+
+ // x -> y
+ if (Context.hasSameUnqualifiedType(ElType, ToType)) {
+ // do nothing
+ } else if (ToType->isRealFloatingType()) {
+ ImpCastExprToType(From, ToType,
+ isFloatingComplex ? CK_FloatingCast : CK_IntegralToFloating);
+ } else {
+ assert(ToType->isIntegerType());
+ ImpCastExprToType(From, ToType,
+ isFloatingComplex ? CK_FloatingToIntegral : CK_IntegralCast);
+ }
+ }
break;
case ICK_Lvalue_To_Rvalue:
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Nov 15 03:13:47 2010
@@ -3745,7 +3745,7 @@
case SK_UserConversion: {
// We have a user-defined conversion that invokes either a constructor
// or a conversion function.
- CastKind CastKind = CK_Unknown;
+ CastKind CastKind;
bool IsCopy = false;
FunctionDecl *Fn = Step->Function.Function;
DeclAccessPair FoundFn = Step->Function.FoundDecl;
Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Mon Nov 15 03:13:47 2010
@@ -424,8 +424,11 @@
Context.canAssignObjCInterfaces(
PropType->getAs<ObjCObjectPointerType>(),
IvarType->getAs<ObjCObjectPointerType>());
- else
- compat = (CheckAssignmentConstraints(PropType, IvarType) == Compatible);
+ else {
+ CastKind K = CK_Invalid;
+ compat = (CheckAssignmentConstraints(PropType, IvarType, K)
+ == Compatible);
+ }
if (!compat) {
Diag(PropertyLoc, diag::error_property_ivar_type)
<< property->getDeclName() << PropType
@@ -644,9 +647,11 @@
if (GetterMethod &&
GetterMethod->getResultType() != property->getType()) {
AssignConvertType result = Incompatible;
- if (property->getType()->isObjCObjectPointerType())
+ if (property->getType()->isObjCObjectPointerType()) {
+ CastKind Kind = CK_Invalid;
result = CheckAssignmentConstraints(GetterMethod->getResultType(),
- property->getType());
+ property->getType(), Kind);
+ }
if (result != Compatible) {
Diag(Loc, diag::warn_accessor_property_type_mismatch)
<< property->getDeclName()
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Nov 15 03:13:47 2010
@@ -1064,17 +1064,26 @@
// Complex promotion (Clang extension)
SCS.Second = ICK_Complex_Promotion;
FromType = ToType.getUnqualifiedType();
+ } else if (ToType->isBooleanType() &&
+ (FromType->isArithmeticType() ||
+ FromType->isAnyPointerType() ||
+ FromType->isBlockPointerType() ||
+ FromType->isMemberPointerType() ||
+ FromType->isNullPtrType())) {
+ // Boolean conversions (C++ 4.12).
+ SCS.Second = ICK_Boolean_Conversion;
+ FromType = S.Context.BoolTy;
} else if (FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isIntegralType(S.Context)) {
// Integral conversions (C++ 4.7).
SCS.Second = ICK_Integral_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if (FromType->isComplexType() && ToType->isComplexType()) {
+ } else if (FromType->isAnyComplexType() && ToType->isComplexType()) {
// Complex conversions (C99 6.3.1.6)
SCS.Second = ICK_Complex_Conversion;
FromType = ToType.getUnqualifiedType();
- } else if ((FromType->isComplexType() && ToType->isArithmeticType()) ||
- (ToType->isComplexType() && FromType->isArithmeticType())) {
+ } else if ((FromType->isAnyComplexType() && ToType->isArithmeticType()) ||
+ (ToType->isAnyComplexType() && FromType->isArithmeticType())) {
// Complex-real conversions (C99 6.3.1.7)
SCS.Second = ICK_Complex_Real;
FromType = ToType.getUnqualifiedType();
@@ -1083,7 +1092,7 @@
SCS.Second = ICK_Floating_Conversion;
FromType = ToType.getUnqualifiedType();
} else if ((FromType->isRealFloatingType() &&
- ToType->isIntegralType(S.Context) && !ToType->isBooleanType()) ||
+ ToType->isIntegralType(S.Context)) ||
(FromType->isIntegralOrUnscopedEnumerationType() &&
ToType->isRealFloatingType())) {
// Floating-integral conversions (C++ 4.9).
@@ -1098,15 +1107,6 @@
InOverloadResolution, FromType)) {
// Pointer to member conversions (4.11).
SCS.Second = ICK_Pointer_Member;
- } else if (ToType->isBooleanType() &&
- (FromType->isArithmeticType() ||
- FromType->isAnyPointerType() ||
- FromType->isBlockPointerType() ||
- FromType->isMemberPointerType() ||
- FromType->isNullPtrType())) {
- // Boolean conversions (C++ 4.12).
- SCS.Second = ICK_Boolean_Conversion;
- FromType = S.Context.BoolTy;
} else if (IsVectorConversion(S.Context, FromType, ToType, SecondICK)) {
SCS.Second = SecondICK;
FromType = ToType.getUnqualifiedType();
@@ -1755,6 +1755,8 @@
QualType FromType = From->getType();
bool IsCStyleOrFunctionalCast = IgnoreBaseAccess;
+ Kind = CK_BitCast;
+
if (CXXBoolLiteralExpr* LitBool
= dyn_cast<CXXBoolLiteralExpr>(From->IgnoreParens()))
if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false)
@@ -1781,7 +1783,7 @@
}
}
if (const ObjCObjectPointerType *FromPtrType =
- FromType->getAs<ObjCObjectPointerType>())
+ FromType->getAs<ObjCObjectPointerType>()) {
if (const ObjCObjectPointerType *ToPtrType =
ToType->getAs<ObjCObjectPointerType>()) {
// Objective-C++ conversions are always okay.
@@ -1789,8 +1791,14 @@
// Objective-C++ implicit conversions.
if (FromPtrType->isObjCBuiltinType() || ToPtrType->isObjCBuiltinType())
return false;
-
+ }
}
+
+ // We shouldn't fall into this case unless it's valid for other
+ // reasons.
+ if (From->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
+ Kind = CK_NullToPointer;
+
return false;
}
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=119138&r1=119137&r2=119138&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Nov 15 03:13:47 2010
@@ -3087,7 +3087,10 @@
Diag(StartLoc, diag::err_deduced_non_type_template_arg_type_mismatch)
<< ArgType << ParamType;
Diag(Param->getLocation(), diag::note_template_param_here);
- return true;
+ return true;
+ } else if (ParamType->isBooleanType()) {
+ // This is an integral-to-boolean conversion.
+ ImpCastExprToType(Arg, ParamType, CK_IntegralToBoolean);
} else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||
!ParamType->isEnumeralType()) {
// This is an integral promotion or conversion.
More information about the cfe-commits
mailing list