From daa8e4e888758d55a7a759dd4a91b83921cef222 Mon Sep 17 00:00:00 2001 From: John McCall Date: Mon, 15 Nov 2010 09:13:47 +0000 Subject: [PATCH] Assorted work leading towards the elimination of CK_Unknown. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119138 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 24 ++- include/clang/AST/OperationKinds.h | 17 +- include/clang/AST/Type.h | 12 ++ include/clang/Sema/Sema.h | 3 +- lib/AST/Expr.cpp | 8 + lib/AST/Type.cpp | 32 +++- lib/Checker/GRExprEngine.cpp | 4 + lib/CodeGen/CGExpr.cpp | 10 +- lib/CodeGen/CGExprScalar.cpp | 76 +++++--- lib/Sema/SemaCXXCast.cpp | 24 ++- lib/Sema/SemaChecking.cpp | 2 +- lib/Sema/SemaDeclAttr.cpp | 3 +- lib/Sema/SemaExpr.cpp | 267 +++++++++++++++++------------ lib/Sema/SemaExprCXX.cpp | 87 ++++++++-- lib/Sema/SemaInit.cpp | 2 +- lib/Sema/SemaObjCProperty.cpp | 13 +- lib/Sema/SemaOverload.cpp | 38 ++-- lib/Sema/SemaTemplate.cpp | 5 +- 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(CanonicalType)) - return BT->getKind() != BuiltinType::Void && !BT->isPlaceholderType(); + return BT->getKind() > BuiltinType::Void && + BT->getKind() <= BuiltinType::NullPtr; if (const EnumType *ET = dyn_cast(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(CanonicalType); } +Type::ScalarTypeKind Type::getScalarTypeKind() const { + assert(isScalarType()); + + const Type *T = CanonicalType.getTypePtr(); + if (const BuiltinType *BT = dyn_cast(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(T) || + isa(T) || + isa(T)) { + return STK_Pointer; + } else if (isa(T)) { + return STK_MemberPointer; + } else if (isa(T)) { + assert(cast(T)->getDecl()->isComplete()); + return STK_Integral; + } else if (const ComplexType *CT = dyn_cast(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(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(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(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(SrcType)) return CGF.CGM.getCXXABI().EmitMemberPointerIsNotNull(CGF, Src, MPT); @@ -473,25 +505,11 @@ Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { assert((SrcType->isIntegerType() || isa(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(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(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(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 Args; unsigned NumElements = cast(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(); 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()->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(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(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(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(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(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 that the resulting expression does not have reference // type. if (const ReferenceType *lhsTypeRef = lhsType->getAs()) { - 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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { // 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(lhsType)) { - if (rhsType->isIntegerType()) + if (rhsType->isIntegerType()) { + Kind = CK_IntegralToPointer; // FIXME: null? return IntToPointer; + } - if (isa(rhsType)) + if (isa(rhsType)) { + Kind = CK_BitCast; return CheckPointerTypesForAssignment(lhsType, rhsType); + } // In general, C pointers are not compatible with ObjC object pointers. if (isa(rhsType)) { + Kind = CK_AnyPointerToObjCPointerCast; if (lhsType->isVoidPointerType()) // an exception to the rule. return Compatible; return IncompatiblePointer; } if (rhsType->getAs()) { - if (lhsType->getAs()->getPointeeType()->isVoidType()) + if (lhsType->getAs()->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(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 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { if (rhsType->isBlockPointerType()) return CheckBlockPointerTypesForAssignment(lhsType, rhsType); - if (const PointerType *RHSPT = rhsType->getAs()) { + if (const PointerType *RHSPT = rhsType->getAs()) if (RHSPT->getPointeeType()->isVoidType()) return Compatible; - } + return Incompatible; } if (isa(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(rhsType)) { @@ -5367,27 +5397,36 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { } if (isa(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(lhsType)) - return CheckPointerTypesForAssignment(lhsType, rhsType); + } if (isa(lhsType) && - rhsType->getAs()->getPointeeType()->isVoidType()) + rhsType->getAs()->getPointeeType()->isVoidType()) { + Kind = CK_AnyPointerToBlockPointerCast; return Compatible; + } return Incompatible; } if (isa(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(lhsType)) { @@ -5396,14 +5435,18 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return IncompatiblePointer; } if (isa(lhsType) && - rhsType->getAs()->getPointeeType()->isVoidType()) + rhsType->getAs()->getPointeeType()->isVoidType()) { + Kind = CK_AnyPointerToBlockPointerCast; return Compatible; + } return Incompatible; } if (isa(lhsType) && isa(rhsType)) { - if (Context.typesAreCompatible(lhsType, rhsType)) + if (Context.typesAreCompatible(lhsType, rhsType)) { + Kind = CK_NoOp; return Compatible; + } } return Incompatible; } @@ -5463,9 +5506,10 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { } } - 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 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { lhsType->isBlockPointerType()) && rExpr->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { - ImpCastExprToType(rExpr, lhsType, CK_Unknown); + ImpCastExprToType(rExpr, lhsType, CK_NullToPointer); return Compatible; } @@ -5515,8 +5559,9 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { 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 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) { // 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 @@ QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) { if (const ExtVectorType *LV = lhsType->getAs()) { 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 @@ QualType Sema::CheckAssignmentOperands(Expr *LHS, Expr *&RHS, } } 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, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index b6a02518a7..70e9a97fc6 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -604,7 +604,7 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, case ImplicitConversionSequence::UserDefinedConversion: { FunctionDecl *FD = ICS.UserDefined.ConversionFunction; - CastKind CastKind = CK_Unknown; + CastKind CastKind; QualType BeforeToType; if (const CXXConversionDecl *Conv = dyn_cast(FD)) { CastKind = CK_UserDefinedConversion; @@ -1893,9 +1893,23 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; case ICK_Complex_Promotion: - case ICK_Complex_Conversion: - ImpCastExprToType(From, ToType, CK_Unknown); + case ICK_Complex_Conversion: { + QualType FromEl = From->getType()->getAs()->getElementType(); + QualType ToEl = ToType->getAs()->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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, << 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, } 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, 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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType, break; case ICK_Complex_Real: - ImpCastExprToType(From, ToType, CK_Unknown); + // Case 1. x -> _Complex y + if (const ComplexType *ToComplex = ToType->getAs()) { + 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(); + 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: diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 7025369b85..77b620b9e9 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -3745,7 +3745,7 @@ InitializationSequence::Perform(Sema &S, 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; diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index e1c0f4af99..4c439f90e8 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -424,8 +424,11 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S, Context.canAssignObjCInterfaces( PropType->getAs(), IvarType->getAs()); - 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 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, 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() diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 7c51548b2b..0c8d78025b 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1064,17 +1064,26 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // 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 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, 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 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, 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 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, QualType FromType = From->getType(); bool IsCStyleOrFunctionalCast = IgnoreBaseAccess; + Kind = CK_BitCast; + if (CXXBoolLiteralExpr* LitBool = dyn_cast(From->IgnoreParens())) if (!IsCStyleOrFunctionalCast && LitBool->getValue() == false) @@ -1781,7 +1783,7 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, } } if (const ObjCObjectPointerType *FromPtrType = - FromType->getAs()) + FromType->getAs()) { if (const ObjCObjectPointerType *ToPtrType = ToType->getAs()) { // Objective-C++ conversions are always okay. @@ -1789,8 +1791,14 @@ bool Sema::CheckPointerConversion(Expr *From, QualType ToType, // 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; } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 3243903863..3f4a1af772 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -3087,7 +3087,10 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param, 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. -- 2.40.0