aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Expr.h24
-rw-r--r--include/clang/AST/OperationKinds.h17
-rw-r--r--include/clang/AST/Type.h12
-rw-r--r--include/clang/Sema/Sema.h3
-rw-r--r--lib/AST/Expr.cpp8
-rw-r--r--lib/AST/Type.cpp32
-rw-r--r--lib/Checker/GRExprEngine.cpp4
-rw-r--r--lib/CodeGen/CGExpr.cpp10
-rw-r--r--lib/CodeGen/CGExprScalar.cpp76
-rw-r--r--lib/Sema/SemaCXXCast.cpp24
-rw-r--r--lib/Sema/SemaChecking.cpp2
-rw-r--r--lib/Sema/SemaDeclAttr.cpp3
-rw-r--r--lib/Sema/SemaExpr.cpp267
-rw-r--r--lib/Sema/SemaExprCXX.cpp87
-rw-r--r--lib/Sema/SemaInit.cpp2
-rw-r--r--lib/Sema/SemaObjCProperty.cpp13
-rw-r--r--lib/Sema/SemaOverload.cpp38
-rw-r--r--lib/Sema/SemaTemplate.cpp5
18 files changed, 440 insertions, 187 deletions
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index 950f579c51..98056c45eb 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -1961,7 +1961,7 @@ public:
private:
Stmt *Op;
- void CheckBasePath() const {
+ void CheckCastConsistency() const {
#ifndef NDEBUG
switch (getCastKind()) {
case CK_DerivedToBase:
@@ -1973,17 +1973,14 @@ private:
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 @@ private:
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 @@ protected:
// 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.
diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h
index d6a7ecf43b..d8aa934385 100644
--- a/include/clang/AST/OperationKinds.h
+++ b/include/clang/AST/OperationKinds.h
@@ -25,6 +25,10 @@ enum CastKind {
/// 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 @@ enum CastKind {
/// 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 @@ enum CastKind {
/// 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 @@ enum CastKind {
CK_IntegralComplexToFloatingComplex
};
+#define CK_Invalid ((CastKind) -1)
enum BinaryOperatorKind {
// Operators listed in order of precedence.
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 7afb2ebb3c..7586e2d7ec 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -1123,6 +1123,18 @@ public:
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]).
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index cae67dbe89..6409b992f0 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4109,7 +4109,8 @@ public:
/// 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,
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index d5bdc88ccf..d6c6bf67ac 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -742,6 +742,8 @@ const char *CastExpr::getCastKindName() const {
switch (getCastKind()) {
case CK_Unknown:
return "Unknown";
+ case CK_Dependent:
+ return "Dependent";
case CK_BitCast:
return "BitCast";
case CK_LValueBitCast:
@@ -778,18 +780,24 @@ const char *CastExpr::getCastKindName() const {
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:
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index b9bf260d58..cad5f8c1e3 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -572,7 +572,8 @@ bool Type::isArithmeticType() const {
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 @@ bool Type::isScalarType() const {
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.
///
diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp
index d57bbc2dc1..ecf21035cf 100644
--- a/lib/Checker/GRExprEngine.cpp
+++ b/lib/Checker/GRExprEngine.cpp
@@ -2541,6 +2541,7 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
return;
case CK_Unknown:
+ case CK_Dependent:
case CK_ArrayToPointerDecay:
case CK_BitCast:
case CK_LValueBitCast:
@@ -2548,8 +2549,11 @@ void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
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:
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 3356cf46fb..ac40f3d580 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1783,7 +1783,10 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
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 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
return LV;
}
// Fall through to synthesize a temporary.
-
+
case CK_Unknown:
case CK_BitCast:
case CK_ArrayToPointerDecay:
@@ -1809,10 +1812,13 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
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:
diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp
index 8d72e47fb8..183afbe72b 100644
--- a/lib/CodeGen/CGExprScalar.cpp
+++ b/lib/CodeGen/CGExprScalar.cpp
@@ -110,6 +110,41 @@ public:
/// 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 @@ public:
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 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) {
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 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
// 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 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
// 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>();
diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp
index baeebe1e40..e8e9deddc2 100644
--- a/lib/Sema/SemaCXXCast.cpp
+++ b/lib/Sema/SemaCXXCast.cpp
@@ -157,7 +157,7 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
<< 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 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
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 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
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 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
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 @@ CheckStaticCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
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 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
// 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 @@ static TryCastResult TryStaticCast(Sema &Self, Expr *&SrcExpr,
}
// 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 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,
}
// 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);
diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 56a0c076ad..e11d68ca19 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -547,7 +547,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
// 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();
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 8b7863107b..e07b1ac471 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1375,7 +1375,8 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) {
// 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;
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 687b92e21b..ae38a597e8 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -4252,33 +4252,6 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,
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 @@ static CastKind PrepareScalarCast(Sema &S, Expr *&Src, QualType DestTy) {
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 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, ParsedType Ty,
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 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
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 @@ Sema::CheckObjCPointerTypesForAssignment(QualType lhsType, QualType rhsType) {
/// 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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) {
// lhsType so tha