diff options
-rw-r--r-- | include/clang/AST/Expr.h | 24 | ||||
-rw-r--r-- | include/clang/AST/OperationKinds.h | 17 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 12 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 3 | ||||
-rw-r--r-- | lib/AST/Expr.cpp | 8 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 32 | ||||
-rw-r--r-- | lib/Checker/GRExprEngine.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CGExpr.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CGExprScalar.cpp | 76 | ||||
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 24 | ||||
-rw-r--r-- | lib/Sema/SemaChecking.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 267 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 87 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 13 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 38 | ||||
-rw-r--r-- | 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<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 |