mirror of
https://github.com/intel/llvm.git
synced 2026-01-22 23:49:22 +08:00
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:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user