Move type-checking for C-style casts in C into the now-misnamed

SemaCXXCast.cpp.  Should have no functionality change.

llvm-svn: 141336
This commit is contained in:
John McCall
2011-10-06 23:25:11 +00:00
parent c281c96675
commit 9776e438cf
4 changed files with 321 additions and 295 deletions

View File

@@ -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);

View File

@@ -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,

View File

@@ -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();

View File

@@ -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;
}