diff options
-rw-r--r-- | include/clang/AST/Type.h | 10 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 12 | ||||
-rw-r--r-- | lib/Sema/SemaCXXCast.cpp | 319 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 275 |
4 files changed, 321 insertions, 295 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 4a44710938..73bf9810b7 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -1362,6 +1362,7 @@ public: /// various convenient purposes within Clang. All such types are /// BuiltinTypes. bool isPlaceholderType() const; + const BuiltinType *getAsPlaceholderType() const; /// isSpecificPlaceholderType - Test for a specific placeholder type. bool isSpecificPlaceholderType(unsigned K) const; @@ -4753,11 +4754,18 @@ inline bool Type::isSpecificBuiltinType(unsigned K) const { } inline bool Type::isPlaceholderType() const { - if (const BuiltinType *BT = getAs<BuiltinType>()) + if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) return BT->isPlaceholderType(); return false; } +inline const BuiltinType *Type::getAsPlaceholderType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (BT->isPlaceholderType()) + return BT; + return 0; +} + inline bool Type::isSpecificPlaceholderType(unsigned K) const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) return (BT->getKind() == (BuiltinType::Kind) K); diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 7c86a15c2d..357b7696ae 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -2493,6 +2493,7 @@ public: TypeSourceInfo *Ty, SourceLocation RParenLoc, Expr *Op); + CastKind PrepareScalarCast(ExprResult &src, QualType destType); /// \brief Build an altivec or OpenCL literal. ExprResult BuildVectorLiteral(SourceLocation LParenLoc, @@ -5769,11 +5770,6 @@ public: bool &ObjCConversion, bool &ObjCLifetimeConversion); - /// CheckCCastTypes - Check type constraints for casting between - /// types under C semantics. - ExprResult CheckCCastTypes(SourceLocation CastStartLoc, SourceRange TypeRange, - QualType CastType, Expr *CastExpr, CastKind &Kind); - ExprResult checkUnknownAnyCast(SourceRange TypeRange, QualType CastType, Expr *CastExpr, CastKind &CastKind, ExprValueKind &VK, CXXCastPath &Path); @@ -5793,12 +5789,6 @@ public: ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr, CastKind &Kind); - /// CXXBuildCStyleCastExpr - Check constraints of a C-style or function-style - /// cast under C++ semantics. - ExprResult CXXBuildCStyleCastExpr(SourceLocation LParenLoc, - TypeSourceInfo *TInfo, - SourceLocation RParenLoc, - Expr *CastExpr); ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo, SourceLocation LParenLoc, Expr *CastExpr, diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 5c5c702fd5..1f386388be 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -1,4 +1,4 @@ -//===--- SemaNamedCast.cpp - Semantic Analysis for Named Casts ------------===// +//===--- SemaCXXCast.cpp - Semantic Analysis for Casts --------------------===// // // The LLVM Compiler Infrastructure // @@ -7,13 +7,14 @@ // //===----------------------------------------------------------------------===// // -// This file implements semantic analysis for C++ named casts. +// This file implements semantic analysis for casts. // //===----------------------------------------------------------------------===// #include "clang/Sema/SemaInternal.h" #include "clang/Sema/Initialization.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/ASTContext.h" #include "clang/AST/CXXInheritance.h" #include "clang/Basic/PartialDiagnostic.h" @@ -45,7 +46,15 @@ namespace { : Self(S), SrcExpr(src), DestType(destType), ResultType(destType.getNonLValueExprType(S.Context)), ValueKind(Expr::getValueKindForType(destType)), - Kind(CK_Dependent), IsARCUnbridgedCast(false) {} + Kind(CK_Dependent), IsARCUnbridgedCast(false) { + + if (const BuiltinType *placeholder = + src.get()->getType()->getAsPlaceholderType()) { + PlaceholderKind = placeholder->getKind(); + } else { + PlaceholderKind = (BuiltinType::Kind) 0; + } + } Sema &Self; ExprResult SrcExpr; @@ -54,16 +63,38 @@ namespace { ExprValueKind ValueKind; CastKind Kind; bool IsARCUnbridgedCast; + BuiltinType::Kind PlaceholderKind; CXXCastPath BasePath; SourceRange OpRange; SourceRange DestRange; + // Top-level semantics-checking routines. void CheckConstCast(); void CheckReinterpretCast(); void CheckStaticCast(); void CheckDynamicCast(); - void CheckCStyleCast(bool FunctionalCast); + void CheckCXXCStyleCast(bool FunctionalCast); + void CheckCStyleCast(); + + // Internal convenience methods. + + /// Try to handle the given placeholder expression kind. Return + /// true if the source expression has the appropriate placeholder + /// kind. A placeholder can only be claimed once. + bool claimPlaceholder(BuiltinType::Kind K) { + if (PlaceholderKind != K) return false; + + PlaceholderKind = (BuiltinType::Kind) 0; + return true; + } + + bool isPlaceholder() const { + return PlaceholderKind != 0; + } + bool isPlaceholder(BuiltinType::Kind K) const { + return PlaceholderKind == K; + } void checkCastAlign() { Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange); @@ -74,6 +105,17 @@ namespace { Self.CheckObjCARCConversion(OpRange, DestType, src, CCK); SrcExpr = src; } + + /// Check for and handle non-overload placeholder expressions. + void checkNonOverloadPlaceholders() { + if (!isPlaceholder() || isPlaceholder(BuiltinType::Overload)) + return; + + SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take()); + if (SrcExpr.isInvalid()) + return; + PlaceholderKind = (BuiltinType::Kind) 0; + } }; } @@ -647,27 +689,29 @@ void CastOperation::CheckReinterpretCast() { /// Refer to C++ 5.2.9 for details. Static casts are mostly used for making /// implicit conversions explicit and getting rid of data loss warnings. void CastOperation::CheckStaticCast() { + if (isPlaceholder()) { + checkNonOverloadPlaceholders(); + if (SrcExpr.isInvalid()) + return; + } + // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { - SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); - if (SrcExpr.isInvalid()) // if conversion failed, don't report another error - return; - if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + Kind = CK_ToVoid; + + if (claimPlaceholder(BuiltinType::Overload)) { ExprResult SingleFunctionExpression = - Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), false, // Decay Function to ptr true, // Complain OpRange, DestType, diag::err_bad_static_cast_overload); - if (SingleFunctionExpression.isUsable()) - { - SrcExpr = SingleFunctionExpression; - Kind = CK_ToVoid; - } + if (SingleFunctionExpression.isUsable()) + SrcExpr = SingleFunctionExpression; } - else - Kind = CK_ToVoid; + + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); return; } @@ -1666,26 +1710,29 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return TC_Success; } -void CastOperation::CheckCStyleCast(bool FunctionalStyle) { - // Check for casts from __unknown_any before anything else. - if (SrcExpr.get()->getType() == Self.Context.UnknownAnyTy) { - SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, - SrcExpr.get(), Kind, - ValueKind, BasePath); - return; - } +void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { + // Handle placeholders. + if (isPlaceholder()) { + // C-style casts can resolve __unknown_any types. + if (claimPlaceholder(BuiltinType::UnknownAny)) { + SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, + SrcExpr.get(), Kind, + ValueKind, BasePath); + return; + } + checkNonOverloadPlaceholders(); + if (SrcExpr.isInvalid()) + return; + } + + // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". // This test is outside everything else because it's the only case where // a non-lvalue-reference target type does not lead to decay. - // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". if (DestType->isVoidType()) { Kind = CK_ToVoid; - SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); - if (SrcExpr.isInvalid()) - return; - - if (SrcExpr.get()->getType() == Self.Context.OverloadTy) { + if (claimPlaceholder(BuiltinType::Overload)) { SrcExpr = Self.ResolveAndFixSingleFunctionTemplateSpecialization( SrcExpr.take(), /* Decay Function to ptr */ false, /* Complain */ true, DestRange, DestType, @@ -1694,12 +1741,9 @@ void CastOperation::CheckCStyleCast(bool FunctionalStyle) { return; } - if (SrcExpr.get()->getType() == Self.Context.BoundMemberTy) { - Self.CheckPlaceholderExpr(SrcExpr.take()); // will always fail + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); + if (SrcExpr.isInvalid()) return; - } - - assert(!SrcExpr.get()->getType()->isPlaceholderType()); return; } @@ -1788,15 +1832,208 @@ void CastOperation::CheckCStyleCast(bool FunctionalStyle) { SrcExpr = ExprError(); } -ExprResult Sema::CXXBuildCStyleCastExpr(SourceLocation LPLoc, - TypeSourceInfo *CastTypeInfo, - SourceLocation RPLoc, - Expr *CastExpr) { +/// Check the semantics of a C-style cast operation, in C. +void CastOperation::CheckCStyleCast() { + assert(!Self.getLangOptions().CPlusPlus); + + // Handle placeholders. + if (isPlaceholder()) { + // C-style casts can resolve __unknown_any types. + if (claimPlaceholder(BuiltinType::UnknownAny)) { + SrcExpr = Self.checkUnknownAnyCast(DestRange, DestType, + SrcExpr.get(), Kind, + ValueKind, BasePath); + return; + } + + checkNonOverloadPlaceholders(); + if (SrcExpr.isInvalid()) + return; + } + + assert(!isPlaceholder()); + + // C99 6.5.4p2: the cast type needs to be void or scalar and the expression + // type needs to be scalar. + if (DestType->isVoidType()) { + // We don't necessarily do lvalue-to-rvalue conversions on this. + SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); + if (SrcExpr.isInvalid()) + return; + + // Cast to void allows any expr type. + Kind = CK_ToVoid; + return; + } + + SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); + if (SrcExpr.isInvalid()) + return; + QualType SrcType = SrcExpr.get()->getType(); + + if (Self.RequireCompleteType(OpRange.getBegin(), DestType, + diag::err_typecheck_cast_to_incomplete)) { + SrcExpr = ExprError(); + return; + } + + if (!DestType->isScalarType() && !DestType->isVectorType()) { + const RecordType *DestRecordTy = DestType->getAs<RecordType>(); + + if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){ + // GCC struct/union extension: allow cast to self. + Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_nonscalar) + << DestType << SrcExpr.get()->getSourceRange(); + Kind = CK_NoOp; + return; + } + + // GCC's cast to union extension. + if (DestRecordTy && DestRecordTy->getDecl()->isUnion()) { + RecordDecl *RD = DestRecordTy->getDecl(); + RecordDecl::field_iterator Field, FieldEnd; + for (Field = RD->field_begin(), FieldEnd = RD->field_end(); + Field != FieldEnd; ++Field) { + if (Self.Context.hasSameUnqualifiedType(Field->getType(), SrcType) && + !Field->isUnnamedBitfield()) { + Self.Diag(OpRange.getBegin(), diag::ext_typecheck_cast_to_union) + << SrcExpr.get()->getSourceRange(); + break; + } + } + if (Field == FieldEnd) { + Self.Diag(OpRange.getBegin(), diag::err_typecheck_cast_to_union_no_type) + << SrcType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + Kind = CK_ToUnion; + return; + } + + // Reject any other conversions to non-scalar types. + Self.Diag(OpRange.getBegin(), diag::err_typecheck_cond_expect_scalar) + << DestType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + + // The type we're casting to is known to be a scalar or vector. + + // Require the operand to be a scalar or vector. + if (!SrcType->isScalarType() && !SrcType->isVectorType()) { + Self.Diag(SrcExpr.get()->getExprLoc(), + diag::err_typecheck_expect_scalar_operand) + << SrcType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + + if (DestType->isExtVectorType()) { + SrcExpr = Self.CheckExtVectorCast(OpRange, DestType, SrcExpr.take(), Kind); + return; + } + + if (const VectorType *DestVecTy = DestType->getAs<VectorType>()) { + if (DestVecTy->getVectorKind() == VectorType::AltiVecVector && + (SrcType->isIntegerType() || SrcType->isFloatingType())) { + Kind = CK_VectorSplat; + } else if (Self.CheckVectorCast(OpRange, DestType, SrcType, Kind)) { + SrcExpr = ExprError(); + } + return; + } + + if (SrcType->isVectorType()) { + if (Self.CheckVectorCast(OpRange, SrcType, DestType, Kind)) + SrcExpr = ExprError(); + return; + } + + // The source and target types are both scalars, i.e. + // - arithmetic types (fundamental, enum, and complex) + // - all kinds of pointers + // Note that member pointers were filtered out with C++, above. + + if (isa<ObjCSelectorExpr>(SrcExpr.get())) { + Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_cast_selector_expr); + SrcExpr = ExprError(); + return; + } + + // If either type is a pointer, the other type has to be either an + // integer or a pointer. + if (!DestType->isArithmeticType()) { + if (!SrcType->isIntegralType(Self.Context) && SrcType->isArithmeticType()) { + Self.Diag(SrcExpr.get()->getExprLoc(), + diag::err_cast_pointer_from_non_pointer_int) + << SrcType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + } else if (!SrcType->isArithmeticType()) { + if (!DestType->isIntegralType(Self.Context) && + DestType->isArithmeticType()) { + Self.Diag(SrcExpr.get()->getLocStart(), + diag::err_cast_pointer_to_non_pointer_int) + << SrcType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + } + + // ARC imposes extra restrictions on casts. + if (Self.getLangOptions().ObjCAutoRefCount) { + checkObjCARCConversion(Sema::CCK_CStyleCast); + if (SrcExpr.isInvalid()) + return; + + if (const PointerType *CastPtr = DestType->getAs<PointerType>()) { + if (const PointerType *ExprPtr = SrcType->getAs<PointerType>()) { + Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers(); + Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers(); + if (CastPtr->getPointeeType()->isObjCLifetimeType() && + ExprPtr->getPointeeType()->isObjCLifetimeType() && + !CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) { + Self.Diag(SrcExpr.get()->getLocStart(), + diag::err_typecheck_incompatible_ownership) + << SrcType << DestType << Sema::AA_Casting + << SrcExpr.get()->getSourceRange(); + return; + } + } + } + else if (!Self.CheckObjCARCUnavailableWeakConversion(DestType, SrcType)) { + Self.Diag(SrcExpr.get()->getLocStart(), + diag::err_arc_convesion_of_weak_unavailable) + << 1 << SrcType << DestType << SrcExpr.get()->getSourceRange(); + SrcExpr = ExprError(); + return; + } + } + + Kind = Self.PrepareScalarCast(SrcExpr, DestType); + if (SrcExpr.isInvalid()) + return; + + if (Kind == CK_BitCast) + checkCastAlign(); +} + +ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, + TypeSourceInfo *CastTypeInfo, + SourceLocation RPLoc, + Expr *CastExpr) { CastOperation Op(*this, CastTypeInfo->getType(), CastExpr); Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); Op.OpRange = SourceRange(LPLoc, CastExpr->getLocEnd()); - Op.CheckCStyleCast(/*FunctionalStyle=*/ false); + if (getLangOptions().CPlusPlus) { + Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ false); + } else { + Op.CheckCStyleCast(); + } + if (Op.SrcExpr.isInvalid()) return ExprError(); @@ -1813,7 +2050,7 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd()); - Op.CheckCStyleCast(/*FunctionalStyle=*/ true); + Op.CheckCXXCStyleCast(/*FunctionalStyle=*/ true); if (Op.SrcExpr.isInvalid()) return ExprError(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 96af0e4c8e..de35ec8525 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3896,13 +3896,13 @@ CastKind Sema::PrepareCastToObjCObjectPointer(ExprResult &E) { /// Prepares for a scalar cast, performing all the necessary stages /// except the final cast and returning the kind required. -static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { +CastKind Sema::PrepareScalarCast(ExprResult &Src, QualType DestTy) { // Both Src and Dest are scalar types, i.e. arithmetic or pointer. // Also, callers should have filtered out the invalid cases with // pointers. Everything else should be possible. QualType SrcTy = Src.get()->getType(); - if (S.Context.hasSameUnqualifiedType(SrcTy, DestTy)) + if (Context.hasSameUnqualifiedType(SrcTy, DestTy)) return CK_NoOp; switch (Type::ScalarTypeKind SrcKind = SrcTy->getScalarTypeKind()) { @@ -3924,7 +3924,7 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { else if (SrcKind == Type::STK_CPointer) return CK_CPointerToObjCPointerCast; else { - maybeExtendBlockObject(S, Src); + maybeExtendBlockObject(*this, Src); return CK_BlockPointerToObjCPointerCast; } case Type::STK_Bool: @@ -3945,7 +3945,7 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { case Type::STK_CPointer: case Type::STK_ObjCObjectPointer: case Type::STK_BlockPointer: - if (Src.get()->isNullPointerConstant(S.Context, + if (Src.get()->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) return CK_NullToPointer; return CK_IntegralToPointer; @@ -3956,14 +3956,14 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { case Type::STK_Floating: return CK_IntegralToFloating; case Type::STK_IntegralComplex: - Src = S.ImpCastExprToType(Src.take(), - DestTy->getAs<ComplexType>()->getElementType(), - CK_IntegralCast); + Src = ImpCastExprToType(Src.take(), + DestTy->castAs<ComplexType>()->getElementType(), + CK_IntegralCast); return CK_IntegralRealToComplex; case Type::STK_FloatingComplex: - Src = S.ImpCastExprToType(Src.take(), - DestTy->getAs<ComplexType>()->getElementType(), - CK_IntegralToFloating); + Src = ImpCastExprToType(Src.take(), + DestTy->castAs<ComplexType>()->getElementType(), + CK_IntegralToFloating); return CK_FloatingRealToComplex; case Type::STK_MemberPointer: llvm_unreachable("member pointer type in C"); @@ -3979,14 +3979,14 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { case Type::STK_Integral: return CK_FloatingToIntegral; case Type::STK_FloatingComplex: - Src = S.ImpCastExprToType(Src.take(), - DestTy->getAs<ComplexType>()->getElementType(), - CK_FloatingCast); + Src = ImpCastExprToType(Src.take(), + DestTy->castAs<ComplexType>()->getElementType(), + CK_FloatingCast); return CK_FloatingRealToComplex; case Type::STK_IntegralComplex: - Src = S.ImpCastExprToType(Src.take(), - DestTy->getAs<ComplexType>()->getElementType(), - CK_FloatingToIntegral); + Src = ImpCastExprToType(Src.take(), + DestTy->castAs<ComplexType>()->getElementType(), + CK_FloatingToIntegral); return CK_IntegralRealToComplex; case Type::STK_CPointer: case Type::STK_ObjCObjectPointer: @@ -4004,18 +4004,18 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { case Type::STK_IntegralComplex: return CK_FloatingComplexToIntegralComplex; case Type::STK_Floating: { - QualType ET = SrcTy->getAs<ComplexType>()->getElementType(); - if (S.Context.hasSameType(ET, DestTy)) + QualType ET = SrcTy->castAs<ComplexType>()->getElementType(); + if (Context.hasSameType(ET, DestTy)) return CK_FloatingComplexToReal; - Src = S.ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal); + Src = ImpCastExprToType(Src.take(), ET, CK_FloatingComplexToReal); return CK_FloatingCast; } case Type::STK_Bool: return CK_FloatingComplexToBoolean; case Type::STK_Integral: - Src = S.ImpCastExprToType(Src.take(), - SrcTy->getAs<ComplexType>()->getElementType(), - CK_FloatingComplexToReal); + Src = ImpCastExprToType(Src.take(), + SrcTy->castAs<ComplexType>()->getElementType(), + CK_FloatingComplexToReal); return CK_FloatingToIntegral; case Type::STK_CPointer: case Type::STK_ObjCObjectPointer: @@ -4033,18 +4033,18 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { case Type::STK_IntegralComplex: return CK_IntegralComplexCast; case Type::STK_Integral: { - QualType ET = SrcTy->getAs<ComplexType>()->getElementType(); - if (S.Context.hasSameType(ET, DestTy)) + QualType ET = SrcTy->castAs<ComplexType>()->getElementType(); + if (Context.hasSameType(ET, DestTy)) return CK_IntegralComplexToReal; - Src = S.ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal); + Src = ImpCastExprToType(Src.take(), ET, CK_IntegralComplexToReal); return CK_IntegralCast; } case Type::STK_Bool: return CK_IntegralComplexToBoolean; case Type::STK_Floating: - Src = S.ImpCastExprToType(Src.take(), - SrcTy->getAs<ComplexType>()->getElementType(), - CK_IntegralComplexToReal); + Src = ImpCastExprToType(Src.take(), + SrcTy->castAs<ComplexType>()->getElementType(), + CK_IntegralComplexToReal); return CK_IntegralToFloating; case Type::STK_CPointer: case Type::STK_ObjCObjectPointer: @@ -4059,196 +4059,6 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) { llvm_unreachable("Unhandled scalar cast"); } -/// CheckCastTypes - Check type constraints for casting between types in C. -ExprResult Sema::CheckCCastTypes(SourceLocation CastStartLoc, - SourceRange TypeRange, QualType CastType, - Expr *CastExpr, CastKind &Kind) { - assert(!getLangOptions().CPlusPlus); - - if (CastExpr->getType() == Context.UnknownAnyTy) { - // We can safely ignore these here because C never has base paths - // or casts to l-values. - CXXCastPath BasePath; - ExprValueKind VK = VK_RValue; - return checkUnknownAnyCast(TypeRange, CastType, CastExpr, Kind, VK, - BasePath); - } - - ExprResult Result = CheckPlaceholderExpr(CastExpr); - if (Result.isInvalid()) - return ExprError(); - CastExpr = Result.take(); - - assert(!CastExpr->getType()->isPlaceholderType()); - - // C99 6.5.4p2: the cast type needs to be void or scalar and the expression - // type needs to be scalar. - if (CastType->isVoidType()) { - // We don't necessarily do lvalue-to-rvalue conversions on this. - ExprResult castExprRes = IgnoredValueConversions(CastExpr); - if (castExprRes.isInvalid()) - return ExprError(); - CastExpr = castExprRes.take(); - - // Cast to void allows any expr type. - Kind = CK_ToVoid; - return Owned(CastExpr); - } - - ExprResult castExprRes = DefaultFunctionArrayLvalueConversion(CastExpr); - if (castExprRes.isInvalid()) - return ExprError(); - CastExpr = castExprRes.take(); - - if (RequireCompleteType(TypeRange.getBegin(), CastType, - diag::err_typecheck_cast_to_incomplete)) - return ExprError(); - - if (!CastType->isScalarType() && !CastType->isVectorType()) { - if (Context.hasSameUnqualifiedType(CastType, CastExpr->getType()) && - (CastType->isStructureType() || CastType->isUnionType())) { - // GCC struct/union extension: allow cast to self. - // FIXME: Check that the cast destination type is complete. - Diag(TypeRange.getBegin(), diag::ext_typecheck_cast_nonscalar) - << CastType << CastExpr->getSourceRange(); - Kind = CK_NoOp; - return Owned(CastExpr); - } - - if (CastType->isUnionType()) { - // GCC cast to union extension - RecordDecl *RD = CastType->getAs<RecordType>()->getDecl(); - RecordDecl::field_iterator Field, FieldEnd; - for (Field = RD->field_begin(), FieldEnd = RD->field_end(); - Field != FieldEnd; ++Field) { - if (Context.hasSameUnqualifiedType(Field->getType(), - CastExpr->getType()) && - !Field->isUnnamedBitfield()) { - Diag(TypeRange.getBegin(), diag::ext_typecheck_cast_to_union) - << CastExpr->getSourceRange(); - break; - } - } - if (Field == FieldEnd) { - Diag(TypeRange.getBegin(), diag::err_typecheck_cast_to_union_no_type) - << CastExpr->getType() << CastExpr->getSourceRange(); - return ExprError(); - } - Kind = CK_ToUnion; - return Owned(CastExpr); - } - - // Reject any other conversions to non-scalar types. - Diag(TypeRange.getBegin(), diag::err_typecheck_cond_expect_scalar) - << CastType << CastExpr->getSourceRange(); - return ExprError(); - } - - // The type we're casting to is known to be a scalar or vector. - - // Require the operand to be a scalar or vector. - if (!CastExpr->getType()->isScalarType() && - !CastExpr->getType()->isVectorType()) { - Diag(CastExpr->getLocStart(), - diag::err_typecheck_expect_scalar_operand) - << CastExpr->getType() << CastExpr->getSourceRange(); - return ExprError(); - } - - if (CastType->isExtVectorType()) - return CheckExtVectorCast(TypeRange, CastType, CastExpr, Kind); - - if (CastType->isVectorType()) { - if (CastType->getAs<VectorType>()->getVectorKind() == - VectorType::AltiVecVector && - (CastExpr->getType()->isIntegerType() || - CastExpr->getType()->isFloatingType())) { - Kind = CK_VectorSplat; - return Owned(CastExpr); - } else if (CheckVectorCast(TypeRange, CastType, CastExpr->getType(), - Kind)) { - return ExprError(); - } else - return Owned(CastExpr); - } - if (CastExpr->getType()->isVectorType()) { - if (CheckVectorCast(TypeRange, CastExpr->getType(), CastType, Kind)) - return ExprError(); - else - return Owned(CastExpr); - } - - // The source and target types are both scalars, i.e. - // - arithmetic types (fundamental, enum, and complex) - // - all kinds of pointers - // Note that member pointers were filtered out with C++, above. - - if (isa<ObjCSelectorExpr>(CastExpr)) { - Diag(CastExpr->getLocStart(), diag::err_cast_selector_expr); - return ExprError(); - } - - // If either type is a pointer, the other type has to be either an - // integer or a pointer. - QualType CastExprType = CastExpr->getType(); - if (!CastType->isArithmeticType()) { - if (!CastExprType->isIntegralType(Context) && - CastExprType->isArithmeticType()) { - Diag(CastExpr->getLocStart(), - diag::err_cast_pointer_from_non_pointer_int) - << CastExprType << CastExpr->getSourceRange(); - return ExprError(); - } - } else if (!CastExpr->getType()->isArithmeticType()) { - if (!CastType->isIntegralType(Context) && CastType->isArithmeticType()) { - Diag(CastExpr->getLocStart(), diag::err_cast_pointer_to_non_pointer_int) - << CastType << CastExpr->getSourceRange(); - return ExprError(); - } - } - - // ARC imposes extra restrictions on casts. - if (getLangOptions().ObjCAutoRefCount) { - CheckObjCARCConversion(SourceRange(CastStartLoc, CastExpr->getLocEnd()), - CastType, CastExpr, CCK_CStyleCast); - - if (const PointerType *CastPtr = CastType->getAs<PointerType>()) { - if (const PointerType *ExprPtr = CastExprType->getAs<PointerType>()) { - Qualifiers CastQuals = CastPtr->getPointeeType().getQualifiers(); - Qualifiers ExprQuals = ExprPtr->getPointeeType().getQualifiers(); - if (CastPtr->getPointeeType()->isObjCLifetimeType() && - ExprPtr->getPointeeType()->isObjCLifetimeType() && - !CastQuals.compatiblyIncludesObjCLifetime(ExprQuals)) { - Diag(CastExpr->getLocStart(), - diag::err_typecheck_incompatible_ownership) - << CastExprType << CastType << AA_Casting - << CastExpr->getSourceRange(); - - return ExprError(); - } - } - } - else if (!CheckObjCARCUnavailableWeakConversion(CastType, CastExprType)) { - Diag(CastExpr->getLocStart(), - diag::err_arc_convesion_of_weak_unavailable) << 1 - << CastExprType << CastType - << CastExpr->getSourceRange(); - return ExprError(); - } - } - - castExprRes = Owned(CastExpr); - Kind = PrepareScalarCast(*this, castExprRes, CastType); - if (castExprRes.isInvalid()) - return ExprError(); - CastExpr = castExprRes.take(); - - if (Kind == CK_BitCast) - CheckCastAlign(CastExpr, CastType, TypeRange); - - return Owned(CastExpr); -} - bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, CastKind &Kind) { assert(VectorTy->isVectorType() && "Not a vector type!"); @@ -4301,7 +4111,7 @@ ExprResult Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType(); ExprResult CastExprRes = Owned(CastExpr); - CastKind CK = PrepareScalarCast(*this, CastExprRes, DestElemTy); + CastKind CK = PrepareScalarCast(CastExprRes, DestElemTy); if (CastExprRes.isInvalid()) return ExprError(); CastExpr = ImpCastExprToType(CastExprRes.take(), DestElemTy, CK).take(); @@ -4369,25 +4179,6 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc, return BuildCStyleCastExpr(LParenLoc, castTInfo, RParenLoc, CastExpr); } -ExprResult -Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty, - SourceLocation RParenLoc, Expr *CastExpr) { - if (getLangOptions().CPlusPlus) - return CXXBuildCStyleCastExpr(LParenLoc, Ty, RParenLoc, CastExpr); - - CastKind Kind = CK_Invalid; - ExprResult CastResult = - CheckCCastTypes(LParenLoc, SourceRange(LParenLoc, RParenLoc), - Ty->getType(), CastExpr, Kind); - if (CastResult.isInvalid()) - return ExprError(); - CastExpr = CastResult.take(); - - return Owned(CStyleCastExpr::Create(Context, Ty->getType(), VK_RValue, Kind, - CastExpr, /*base path*/ 0, Ty, - LParenLoc, RParenLoc)); -} - ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, SourceLocation RParenLoc, Expr *E, TypeSourceInfo *TInfo) { @@ -4425,7 +4216,7 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); ExprResult Literal = Owned(exprs[0]); Literal = ImpCastExprToType(Literal.take(), ElemTy, - PrepareScalarCast(*this, Literal, ElemTy)); + PrepareScalarCast(Literal, ElemTy)); return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); } else if (numExprs < numElems) { @@ -4446,7 +4237,7 @@ ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc, QualType ElemTy = Ty->getAs<VectorType>()->getElementType(); ExprResult Literal = Owned(exprs[0]); Literal = ImpCastExprToType(Literal.take(), ElemTy, - PrepareScalarCast(*this, Literal, ElemTy)); + PrepareScalarCast(Literal, ElemTy)); return BuildCStyleCastExpr(LParenLoc, TInfo, RParenLoc, Literal.take()); } @@ -5432,7 +5223,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // element type. QualType elType = cast<ExtVectorType>(LHSType)->getElementType(); if (elType != RHSType) { - Kind = PrepareScalarCast(*this, RHS, elType); + Kind = PrepareScalarCast(RHS, elType); RHS = ImpCastExprToType(RHS.take(), elType, Kind); } Kind = CK_VectorSplat; @@ -5465,7 +5256,7 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, // Arithmetic conversions. if (LHSType->isArithmeticType() && RHSType->isArithmeticType() && !(getLangOptions().CPlusPlus && LHSType->isEnumeralType())) { - Kind = PrepareScalarCast(*this, RHS, LHSType); + Kind = PrepareScalarCast(RHS, LHSType); return Compatible; } |