-//===--- SemaNamedCast.cpp - Semantic Analysis for Named Casts ------------===//
+//===--- SemaCXXCast.cpp - Semantic Analysis for Casts --------------------===//
//
// The LLVM Compiler Infrastructure
//
//
//===----------------------------------------------------------------------===//
//
-// 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"
: 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;
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);
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;
+ }
};
}
/// 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;
}
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,
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;
}
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();
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();
/// 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()) {
else if (SrcKind == Type::STK_CPointer)
return CK_CPointerToObjCPointerCast;
else {
- maybeExtendBlockObject(S, Src);
+ maybeExtendBlockObject(*this, Src);
return CK_BlockPointerToObjCPointerCast;
}
case Type::STK_Bool:
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;
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");
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:
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:
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:
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!");
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();
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) {
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) {
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());
}
// 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;
// Arithmetic conversions.
if (LHSType->isArithmeticType() && RHSType->isArithmeticType() &&
!(getLangOptions().CPlusPlus && LHSType->isEnumeralType())) {
- Kind = PrepareScalarCast(*this, RHS, LHSType);
+ Kind = PrepareScalarCast(RHS, LHSType);
return Compatible;
}