Refactor the analysis of C++ cast expressions so that even
C-style and functional casts are built in SemaCXXCast.cpp. Introduce a helper class to encapsulate most of the random state being passed around, at least one level down. llvm-svn: 141170
This commit is contained in:
parent
ad33c139ac
commit
b50451a188
|
@ -5754,12 +5754,10 @@ public:
|
|||
bool &ObjCConversion,
|
||||
bool &ObjCLifetimeConversion);
|
||||
|
||||
/// CheckCastTypes - Check type constraints for casting between types under
|
||||
/// C semantics, or forward to CXXCheckCStyleCast in C++.
|
||||
ExprResult CheckCastTypes(SourceLocation CastStartLoc, SourceRange TypeRange,
|
||||
QualType CastType, Expr *CastExpr, CastKind &Kind,
|
||||
ExprValueKind &VK, CXXCastPath &BasePath,
|
||||
bool FunctionalStyle = false);
|
||||
/// 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,
|
||||
|
@ -5780,11 +5778,16 @@ public:
|
|||
ExprResult CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *CastExpr,
|
||||
CastKind &Kind);
|
||||
|
||||
/// CXXCheckCStyleCast - Check constraints of a C-style or function-style
|
||||
/// CXXBuildCStyleCastExpr - Check constraints of a C-style or function-style
|
||||
/// cast under C++ semantics.
|
||||
ExprResult CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
|
||||
Expr *CastExpr, CastKind &Kind,
|
||||
CXXCastPath &BasePath, bool FunctionalStyle);
|
||||
ExprResult CXXBuildCStyleCastExpr(SourceLocation LParenLoc,
|
||||
TypeSourceInfo *TInfo,
|
||||
SourceLocation RParenLoc,
|
||||
Expr *CastExpr);
|
||||
ExprResult BuildCXXFunctionalCastExpr(TypeSourceInfo *TInfo,
|
||||
SourceLocation LParenLoc,
|
||||
Expr *CastExpr,
|
||||
SourceLocation RParenLoc);
|
||||
|
||||
/// \brief Checks for invalid conversions and casts between
|
||||
/// retainable pointers and other pointer kinds.
|
||||
|
|
|
@ -39,29 +39,43 @@ enum CastType {
|
|||
CT_Functional ///< Type(expr)
|
||||
};
|
||||
|
||||
namespace {
|
||||
struct CastOperation {
|
||||
CastOperation(Sema &S, QualType destType, ExprResult src)
|
||||
: Self(S), SrcExpr(src), DestType(destType),
|
||||
ResultType(destType.getNonLValueExprType(S.Context)),
|
||||
ValueKind(Expr::getValueKindForType(destType)),
|
||||
Kind(CK_Dependent), IsARCUnbridgedCast(false) {}
|
||||
|
||||
Sema &Self;
|
||||
ExprResult SrcExpr;
|
||||
QualType DestType;
|
||||
QualType ResultType;
|
||||
ExprValueKind ValueKind;
|
||||
CastKind Kind;
|
||||
bool IsARCUnbridgedCast;
|
||||
CXXCastPath BasePath;
|
||||
|
||||
SourceRange OpRange;
|
||||
SourceRange DestRange;
|
||||
|
||||
static void CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
||||
ExprValueKind &VK,
|
||||
const SourceRange &OpRange,
|
||||
const SourceRange &DestRange);
|
||||
static void CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
||||
ExprValueKind &VK,
|
||||
const SourceRange &OpRange,
|
||||
const SourceRange &DestRange,
|
||||
CastKind &Kind);
|
||||
static void CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
||||
ExprValueKind &VK,
|
||||
const SourceRange &OpRange,
|
||||
CastKind &Kind,
|
||||
CXXCastPath &BasePath);
|
||||
static void CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
||||
ExprValueKind &VK,
|
||||
const SourceRange &OpRange,
|
||||
const SourceRange &DestRange,
|
||||
CastKind &Kind,
|
||||
CXXCastPath &BasePath);
|
||||
void CheckConstCast();
|
||||
void CheckReinterpretCast();
|
||||
void CheckStaticCast();
|
||||
void CheckDynamicCast();
|
||||
void CheckCStyleCast(bool FunctionalCast);
|
||||
|
||||
void checkCastAlign() {
|
||||
Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
|
||||
}
|
||||
|
||||
void checkObjCARCConversion(Sema::CheckedConversionKind CCK) {
|
||||
Expr *src = SrcExpr.get();
|
||||
Self.CheckObjCARCConversion(OpRange, DestType, src, CCK);
|
||||
SrcExpr = src;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static bool CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
|
||||
bool CheckCVR, bool CheckObjCLifetime);
|
||||
|
@ -162,70 +176,61 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
|
|||
ExprResult Ex = Owned(E);
|
||||
QualType DestType = DestTInfo->getType();
|
||||
|
||||
SourceRange OpRange(OpLoc, Parens.getEnd());
|
||||
SourceRange DestRange = AngleBrackets;
|
||||
|
||||
// If the type is dependent, we won't do the semantic analysis now.
|
||||
// FIXME: should we check this in a more fine-grained manner?
|
||||
bool TypeDependent = DestType->isDependentType() || Ex.get()->isTypeDependent();
|
||||
|
||||
ExprValueKind VK = VK_RValue;
|
||||
if (TypeDependent)
|
||||
VK = Expr::getValueKindForType(DestType);
|
||||
CastOperation Op(*this, DestType, E);
|
||||
Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
|
||||
Op.DestRange = AngleBrackets;
|
||||
|
||||
switch (Kind) {
|
||||
default: llvm_unreachable("Unknown C++ cast!");
|
||||
|
||||
case tok::kw_const_cast:
|
||||
if (!TypeDependent) {
|
||||
CheckConstCast(*this, Ex, DestType, VK, OpRange, DestRange);
|
||||
if (Ex.isInvalid())
|
||||
Op.CheckConstCast();
|
||||
if (Op.SrcExpr.isInvalid())
|
||||
return ExprError();
|
||||
}
|
||||
return Owned(CXXConstCastExpr::Create(Context,
|
||||
DestType.getNonLValueExprType(Context),
|
||||
VK, Ex.take(), DestTInfo, OpLoc,
|
||||
return Owned(CXXConstCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
|
||||
Op.SrcExpr.take(), DestTInfo, OpLoc,
|
||||
Parens.getEnd()));
|
||||
|
||||
case tok::kw_dynamic_cast: {
|
||||
CastKind Kind = CK_Dependent;
|
||||
CXXCastPath BasePath;
|
||||
if (!TypeDependent) {
|
||||
CheckDynamicCast(*this, Ex, DestType, VK, OpRange, DestRange,
|
||||
Kind, BasePath);
|
||||
if (Ex.isInvalid())
|
||||
Op.CheckDynamicCast();
|
||||
if (Op.SrcExpr.isInvalid())
|
||||
return ExprError();
|
||||
}
|
||||
return Owned(CXXDynamicCastExpr::Create(Context,
|
||||
DestType.getNonLValueExprType(Context),
|
||||
VK, Kind, Ex.take(), &BasePath, DestTInfo,
|
||||
OpLoc, Parens.getEnd()));
|
||||
}
|
||||
case tok::kw_reinterpret_cast: {
|
||||
CastKind Kind = CK_Dependent;
|
||||
if (!TypeDependent) {
|
||||
CheckReinterpretCast(*this, Ex, DestType, VK, OpRange, DestRange, Kind);
|
||||
if (Ex.isInvalid())
|
||||
return ExprError();
|
||||
}
|
||||
return Owned(CXXReinterpretCastExpr::Create(Context,
|
||||
DestType.getNonLValueExprType(Context),
|
||||
VK, Kind, Ex.take(), 0,
|
||||
return Owned(CXXDynamicCastExpr::Create(Context, Op.ResultType,
|
||||
Op.ValueKind, Op.Kind,
|
||||
Op.SrcExpr.take(), &Op.BasePath,
|
||||
DestTInfo, OpLoc, Parens.getEnd()));
|
||||
}
|
||||
case tok::kw_static_cast: {
|
||||
CastKind Kind = CK_Dependent;
|
||||
CXXCastPath BasePath;
|
||||
case tok::kw_reinterpret_cast: {
|
||||
if (!TypeDependent) {
|
||||
CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath);
|
||||
if (Ex.isInvalid())
|
||||
Op.CheckReinterpretCast();
|
||||
if (Op.SrcExpr.isInvalid())
|
||||
return ExprError();
|
||||
}
|
||||
return Owned(CXXReinterpretCastExpr::Create(Context, Op.ResultType,
|
||||
Op.ValueKind, Op.Kind,
|
||||
Op.SrcExpr.take(), 0,
|
||||
DestTInfo, OpLoc,
|
||||
Parens.getEnd()));
|
||||
}
|
||||
case tok::kw_static_cast: {
|
||||
if (!TypeDependent) {
|
||||
Op.CheckStaticCast();
|
||||
if (Op.SrcExpr.isInvalid())
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
return Owned(CXXStaticCastExpr::Create(Context,
|
||||
DestType.getNonLValueExprType(Context),
|
||||
VK, Kind, Ex.take(), &BasePath,
|
||||
DestTInfo, OpLoc, Parens.getEnd()));
|
||||
return Owned(CXXStaticCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
|
||||
Op.Kind, Op.SrcExpr.take(),
|
||||
&Op.BasePath, DestTInfo, OpLoc,
|
||||
Parens.getEnd()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,13 +466,9 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
|
|||
/// CheckDynamicCast - Check that a dynamic_cast\<DestType\>(SrcExpr) is valid.
|
||||
/// Refer to C++ 5.2.7 for details. Dynamic casts are used mostly for runtime-
|
||||
/// checked downcasts in class hierarchies.
|
||||
static void
|
||||
CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
||||
ExprValueKind &VK, const SourceRange &OpRange,
|
||||
const SourceRange &DestRange, CastKind &Kind,
|
||||
CXXCastPath &BasePath) {
|
||||
QualType OrigDestType = DestType, OrigSrcType = SrcExpr.get()->getType();
|
||||
DestType = Self.Context.getCanonicalType(DestType);
|
||||
void CastOperation::CheckDynamicCast() {
|
||||
QualType OrigSrcType = SrcExpr.get()->getType();
|
||||
QualType DestType = Self.Context.getCanonicalType(this->DestType);
|
||||
|
||||
// C++ 5.2.7p1: T shall be a pointer or reference to a complete class type,
|
||||
// or "pointer to cv void".
|
||||
|
@ -479,12 +480,9 @@ CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
DestPointee = DestPointer->getPointeeType();
|
||||
} else if ((DestReference = DestType->getAs<ReferenceType>())) {
|
||||
DestPointee = DestReference->getPointeeType();
|
||||
VK = isa<LValueReferenceType>(DestReference) ? VK_LValue
|
||||
: isa<RValueReferenceType>(DestReference) ? VK_XValue
|
||||
: VK_RValue;
|
||||
} else {
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
|
||||
<< OrigDestType << DestRange;
|
||||
<< this->DestType << DestRange;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -519,7 +517,7 @@ CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
} else if (DestReference->isLValueReferenceType()) {
|
||||
if (!SrcExpr.get()->isLValue()) {
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_rvalue)
|
||||
<< CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
|
||||
<< CT_Dynamic << OrigSrcType << this->DestType << OpRange;
|
||||
}
|
||||
SrcPointee = SrcType;
|
||||
} else {
|
||||
|
@ -547,7 +545,7 @@ CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
// C++ 5.2.7p1: The dynamic_cast operator shall not cast away constness.
|
||||
if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
|
||||
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away)
|
||||
<< CT_Dynamic << OrigSrcType << OrigDestType << OpRange;
|
||||
<< CT_Dynamic << OrigSrcType << this->DestType << OpRange;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -595,11 +593,8 @@ CheckDynamicCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
/// like this:
|
||||
/// const char *str = "literal";
|
||||
/// legacy_function(const_cast\<char*\>(str));
|
||||
void
|
||||
CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind &VK,
|
||||
const SourceRange &OpRange, const SourceRange &DestRange) {
|
||||
VK = Expr::getValueKindForType(DestType);
|
||||
if (VK == VK_RValue) {
|
||||
void CastOperation::CheckConstCast() {
|
||||
if (ValueKind == VK_RValue) {
|
||||
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
|
||||
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
|
||||
return;
|
||||
|
@ -617,12 +612,8 @@ CheckConstCast(Sema &Self, ExprResult &SrcExpr, QualType DestType, ExprValueKind
|
|||
/// Refer to C++ 5.2.10 for details. reinterpret_cast is typically used in code
|
||||
/// like this:
|
||||
/// char *bytes = reinterpret_cast\<char*\>(int_ptr);
|
||||
void
|
||||
CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
||||
ExprValueKind &VK, const SourceRange &OpRange,
|
||||
const SourceRange &DestRange, CastKind &Kind) {
|
||||
VK = Expr::getValueKindForType(DestType);
|
||||
if (VK == VK_RValue) {
|
||||
void CastOperation::CheckReinterpretCast() {
|
||||
if (ValueKind == VK_RValue) {
|
||||
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
|
||||
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
|
||||
return;
|
||||
|
@ -647,10 +638,7 @@ CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(), DestType);
|
||||
}
|
||||
} else if (tcr == TC_Success && Self.getLangOptions().ObjCAutoRefCount) {
|
||||
Expr *Exp = SrcExpr.get();
|
||||
// Note that Exp does not change with CCK_OtherCast cast type
|
||||
Self.CheckObjCARCConversion(OpRange, DestType,
|
||||
Exp, Sema::CCK_OtherCast);
|
||||
checkObjCARCConversion(Sema::CCK_OtherCast);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -658,10 +646,7 @@ CheckReinterpretCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
/// CheckStaticCast - Check that a static_cast\<DestType\>(SrcExpr) is valid.
|
||||
/// 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
|
||||
CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
||||
ExprValueKind &VK, const SourceRange &OpRange,
|
||||
CastKind &Kind, CXXCastPath &BasePath) {
|
||||
void CastOperation::CheckStaticCast() {
|
||||
// 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".
|
||||
|
@ -686,8 +671,7 @@ CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
return;
|
||||
}
|
||||
|
||||
VK = Expr::getValueKindForType(DestType);
|
||||
if (VK == VK_RValue && !DestType->isRecordType()) {
|
||||
if (ValueKind == VK_RValue && !DestType->isRecordType()) {
|
||||
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
|
||||
if (SrcExpr.isInvalid()) // if conversion failed, don't report another error
|
||||
return;
|
||||
|
@ -711,17 +695,13 @@ CheckStaticCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
|
|||
}
|
||||
} else if (tcr == TC_Success) {
|
||||
if (Kind == CK_BitCast)
|
||||
Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
|
||||
if (Self.getLangOptions().ObjCAutoRefCount) {
|
||||
Expr *Exp = SrcExpr.get();
|
||||
// Note that Exp does not change with CCK_OtherCast cast type
|
||||
Self.CheckObjCARCConversion(OpRange, DestType,
|
||||
Exp, Sema::CCK_OtherCast);
|
||||
checkCastAlign();
|
||||
if (Self.getLangOptions().ObjCAutoRefCount)
|
||||
checkObjCARCConversion(Sema::CCK_OtherCast);
|
||||
} else if (Kind == CK_BitCast) {
|
||||
checkCastAlign();
|
||||
}
|
||||
}
|
||||
else if (Kind == CK_BitCast)
|
||||
Self.CheckCastAlign(SrcExpr.get(), DestType, OpRange);
|
||||
}
|
||||
|
||||
/// TryStaticCast - Check if a static cast can be performed, and do so if
|
||||
/// possible. If @p CStyle, ignore access restrictions on hierarchy casting
|
||||
|
@ -1686,65 +1666,63 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
|
|||
return TC_Success;
|
||||
}
|
||||
|
||||
ExprResult
|
||||
Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
|
||||
Expr *CastExpr, CastKind &Kind,
|
||||
CXXCastPath &BasePath,
|
||||
bool FunctionalStyle) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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 (CastTy->isVoidType()) {
|
||||
if (DestType->isVoidType()) {
|
||||
Kind = CK_ToVoid;
|
||||
|
||||
ExprResult CastExprRes = IgnoredValueConversions(CastExpr);
|
||||
if (CastExprRes.isInvalid())
|
||||
return ExprError();
|
||||
CastExpr = CastExprRes.take();
|
||||
SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
|
||||
if (CastExpr->getType() == Context.BoundMemberTy)
|
||||
return CheckPlaceholderExpr(CastExpr); // will always fail
|
||||
|
||||
if (CastExpr->getType() == Context.OverloadTy) {
|
||||
ExprResult SingleFunctionExpr =
|
||||
ResolveAndFixSingleFunctionTemplateSpecialization(
|
||||
CastExpr, /* Decay Function to ptr */ false,
|
||||
/* Complain */ true, R, CastTy,
|
||||
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
|
||||
SrcExpr = Self.ResolveAndFixSingleFunctionTemplateSpecialization(
|
||||
SrcExpr.take(), /* Decay Function to ptr */ false,
|
||||
/* Complain */ true, DestRange, DestType,
|
||||
diag::err_bad_cstyle_cast_overload);
|
||||
if (SingleFunctionExpr.isInvalid())
|
||||
return ExprError();
|
||||
CastExpr = SingleFunctionExpr.take();
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
}
|
||||
|
||||
assert(!CastExpr->getType()->isPlaceholderType());
|
||||
|
||||
return Owned(CastExpr);
|
||||
if (SrcExpr.get()->getType() == Self.Context.BoundMemberTy) {
|
||||
Self.CheckPlaceholderExpr(SrcExpr.take()); // will always fail
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure we determine the value kind before we bail out for
|
||||
// dependent types.
|
||||
VK = Expr::getValueKindForType(CastTy);
|
||||
assert(!SrcExpr.get()->getType()->isPlaceholderType());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// If the type is dependent, we won't do any other semantic analysis now.
|
||||
if (CastTy->isDependentType() || CastExpr->isTypeDependent()) {
|
||||
Kind = CK_Dependent;
|
||||
return Owned(CastExpr);
|
||||
if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent()) {
|
||||
assert(Kind == CK_Dependent);
|
||||
return;
|
||||
}
|
||||
|
||||
if (VK == VK_RValue && !CastTy->isRecordType()) {
|
||||
ExprResult CastExprRes = DefaultFunctionArrayLvalueConversion(CastExpr);
|
||||
if (CastExprRes.isInvalid())
|
||||
return ExprError();
|
||||
CastExpr = CastExprRes.take();
|
||||
if (ValueKind == VK_RValue && !DestType->isRecordType()) {
|
||||
SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take());
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
}
|
||||
|
||||
// AltiVec vector initialization with a single literal.
|
||||
if (const VectorType *vecTy = CastTy->getAs<VectorType>())
|
||||
if (const VectorType *vecTy = DestType->getAs<VectorType>())
|
||||
if (vecTy->getVectorKind() == VectorType::AltiVecVector
|
||||
&& (CastExpr->getType()->isIntegerType()
|
||||
|| CastExpr->getType()->isFloatingType())) {
|
||||
&& (SrcExpr.get()->getType()->isIntegerType()
|
||||
|| SrcExpr.get()->getType()->isFloatingType())) {
|
||||
Kind = CK_VectorSplat;
|
||||
return Owned(CastExpr);
|
||||
return;
|
||||
}
|
||||
|
||||
// C++ [expr.cast]p5: The conversions performed by
|
||||
|
@ -1759,8 +1737,8 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
|
|||
// even if a cast resulting from that interpretation is ill-formed.
|
||||
// In plain language, this means trying a const_cast ...
|
||||
unsigned msg = diag::err_bad_cxx_cast_generic;
|
||||
TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,
|
||||
msg);
|
||||
TryCastResult tcr = TryConstCast(Self, SrcExpr.get(), DestType,
|
||||
/*CStyle*/true, msg);
|
||||
if (tcr == TC_Success)
|
||||
Kind = CK_NoOp;
|
||||
|
||||
|
@ -1769,31 +1747,28 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
|
|||
: Sema::CCK_CStyleCast;
|
||||
if (tcr == TC_NotApplicable) {
|
||||
// ... or if that is not possible, a static_cast, ignoring const, ...
|
||||
ExprResult CastExprRes = Owned(CastExpr);
|
||||
tcr = TryStaticCast(*this, CastExprRes, CastTy, CCK, R, msg, Kind,
|
||||
BasePath);
|
||||
if (CastExprRes.isInvalid())
|
||||
return ExprError();
|
||||
CastExpr = CastExprRes.take();
|
||||
tcr = TryStaticCast(Self, SrcExpr, DestType, CCK, OpRange,
|
||||
msg, Kind, BasePath);
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
|
||||
if (tcr == TC_NotApplicable) {
|
||||
// ... and finally a reinterpret_cast, ignoring const.
|
||||
CastExprRes = Owned(CastExpr);
|
||||
tcr = TryReinterpretCast(*this, CastExprRes, CastTy, /*CStyle*/true, R,
|
||||
msg, Kind);
|
||||
if (CastExprRes.isInvalid())
|
||||
return ExprError();
|
||||
CastExpr = CastExprRes.take();
|
||||
tcr = TryReinterpretCast(Self, SrcExpr, DestType, /*CStyle*/true,
|
||||
OpRange, msg, Kind);
|
||||
if (SrcExpr.isInvalid())
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (getLangOptions().ObjCAutoRefCount && tcr == TC_Success)
|
||||
CheckObjCARCConversion(R, CastTy, CastExpr, CCK);
|
||||
if (Self.getLangOptions().ObjCAutoRefCount && tcr == TC_Success)
|
||||
checkObjCARCConversion(CCK);
|
||||
|
||||
if (tcr != TC_Success && msg != 0) {
|
||||
if (CastExpr->getType() == Context.OverloadTy) {
|
||||
if (SrcExpr.get()->getType() == Self.Context.OverloadTy) {
|
||||
DeclAccessPair Found;
|
||||
FunctionDecl *Fn = ResolveAddressOfOverloadedFunction(CastExpr,
|
||||
CastTy,
|
||||
FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(),
|
||||
DestType,
|
||||
/*Complain*/ true,
|
||||
Found);
|
||||
|
||||
|
@ -1801,15 +1776,50 @@ Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK,
|
|||
(void)Fn;
|
||||
|
||||
} else {
|
||||
diagnoseBadCast(*this, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
|
||||
R, CastExpr, CastTy);
|
||||
diagnoseBadCast(Self, msg, (FunctionalStyle ? CT_Functional : CT_CStyle),
|
||||
OpRange, SrcExpr.get(), DestType);
|
||||
}
|
||||
} else if (Kind == CK_BitCast) {
|
||||
checkCastAlign();
|
||||
}
|
||||
else if (Kind == CK_BitCast)
|
||||
CheckCastAlign(CastExpr, CastTy, R);
|
||||
|
||||
// Clear out SrcExpr if there was a fatal error.
|
||||
if (tcr != TC_Success)
|
||||
SrcExpr = ExprError();
|
||||
}
|
||||
|
||||
ExprResult Sema::CXXBuildCStyleCastExpr(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 (Op.SrcExpr.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
return Owned(CastExpr);
|
||||
return Owned(CStyleCastExpr::Create(Context, Op.ResultType, Op.ValueKind,
|
||||
Op.Kind, Op.SrcExpr.take(), &Op.BasePath,
|
||||
CastTypeInfo, LPLoc, RPLoc));
|
||||
}
|
||||
|
||||
ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
|
||||
SourceLocation LPLoc,
|
||||
Expr *CastExpr,
|
||||
SourceLocation RPLoc) {
|
||||
CastOperation Op(*this, CastTypeInfo->getType(), CastExpr);
|
||||
Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange();
|
||||
Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd());
|
||||
|
||||
Op.CheckCStyleCast(/*FunctionalStyle=*/ true);
|
||||
if (Op.SrcExpr.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
return Owned(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
|
||||
Op.ValueKind, CastTypeInfo,
|
||||
Op.DestRange.getBegin(),
|
||||
Op.Kind, Op.SrcExpr.take(),
|
||||
&Op.BasePath, RPLoc));
|
||||
}
|
||||
|
|
|
@ -495,6 +495,9 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
|
|||
return ExprError();
|
||||
}
|
||||
|
||||
// Strip any qualifiers off ValType.
|
||||
ValType = ValType.getUnqualifiedType();
|
||||
|
||||
// The majority of builtins return a value, but a few have special return
|
||||
// types, so allow them to override appropriately below.
|
||||
QualType ResultType = ValType;
|
||||
|
@ -613,11 +616,10 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
|
|||
|
||||
// GCC does an implicit conversion to the pointer or integer ValType. This
|
||||
// can fail in some cases (1i -> int**), check for this error case now.
|
||||
CastKind Kind = CK_Invalid;
|
||||
ExprValueKind VK = VK_RValue;
|
||||
CXXCastPath BasePath;
|
||||
Arg = CheckCastTypes(Arg.get()->getLocStart(), Arg.get()->getSourceRange(),
|
||||
ValType, Arg.take(), Kind, VK, BasePath);
|
||||
// Initialize the argument.
|
||||
InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
|
||||
ValType, /*consume*/ false);
|
||||
Arg = PerformCopyInitialization(Entity, SourceLocation(), Arg);
|
||||
if (Arg.isInvalid())
|
||||
return ExprError();
|
||||
|
||||
|
@ -627,8 +629,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
|
|||
// pass in 42. The 42 gets converted to char. This is even more strange
|
||||
// for things like 45.123 -> char, etc.
|
||||
// FIXME: Do this check.
|
||||
Arg = ImpCastExprToType(Arg.take(), ValType, Kind, VK, &BasePath);
|
||||
TheCall->setArg(i+1, Arg.get());
|
||||
TheCall->setArg(i+1, Arg.take());
|
||||
}
|
||||
|
||||
ASTContext& Context = this->getASTContext();
|
||||
|
|
|
@ -4055,27 +4055,28 @@ static CastKind PrepareScalarCast(Sema &S, ExprResult &Src, QualType DestTy) {
|
|||
llvm_unreachable("Unhandled scalar cast");
|
||||
}
|
||||
|
||||
/// CheckCastTypes - Check type constraints for casting between types.
|
||||
ExprResult Sema::CheckCastTypes(SourceLocation CastStartLoc,
|
||||
/// CheckCastTypes - Check type constraints for casting between types in C.
|
||||
ExprResult Sema::CheckCCastTypes(SourceLocation CastStartLoc,
|
||||
SourceRange TypeRange, QualType CastType,
|
||||
Expr *CastExpr, CastKind &Kind,
|
||||
ExprValueKind &VK, CXXCastPath &BasePath,
|
||||
bool FunctionalStyle) {
|
||||
if (CastExpr->getType() == Context.UnknownAnyTy)
|
||||
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);
|
||||
}
|
||||
|
||||
if (getLangOptions().CPlusPlus)
|
||||
return CXXCheckCStyleCast(SourceRange(CastStartLoc,
|
||||
CastExpr->getLocEnd()),
|
||||
CastType, VK, CastExpr, Kind, BasePath,
|
||||
FunctionalStyle);
|
||||
ExprResult Result = CheckPlaceholderExpr(CastExpr);
|
||||
if (Result.isInvalid())
|
||||
return ExprError();
|
||||
CastExpr = Result.take();
|
||||
|
||||
assert(!CastExpr->getType()->isPlaceholderType());
|
||||
|
||||
// We only support r-value casts in C.
|
||||
VK = VK_RValue;
|
||||
|
||||
// C99 6.5.4p2: the cast type needs to be void or scalar and the expression
|
||||
// type needs to be scalar.
|
||||
if (CastType->isVoidType()) {
|
||||
|
@ -4202,8 +4203,8 @@ ExprResult Sema::CheckCastTypes(SourceLocation CastStartLoc,
|
|||
}
|
||||
}
|
||||
|
||||
// ARC imposes extra restrictions on casts.
|
||||
if (getLangOptions().ObjCAutoRefCount) {
|
||||
// Diagnose problems with Objective-C casts involving lifetime qualifiers.
|
||||
CheckObjCARCConversion(SourceRange(CastStartLoc, CastExpr->getLocEnd()),
|
||||
CastType, CastExpr, CCK_CStyleCast);
|
||||
|
||||
|
@ -4367,19 +4368,20 @@ Sema::ActOnCastExpr(Scope *S, SourceLocation LParenLoc,
|
|||
ExprResult
|
||||
Sema::BuildCStyleCastExpr(SourceLocation LParenLoc, TypeSourceInfo *Ty,
|
||||
SourceLocation RParenLoc, Expr *CastExpr) {
|
||||
if (getLangOptions().CPlusPlus)
|
||||
return CXXBuildCStyleCastExpr(LParenLoc, Ty, RParenLoc, CastExpr);
|
||||
|
||||
CastKind Kind = CK_Invalid;
|
||||
ExprValueKind VK = VK_RValue;
|
||||
CXXCastPath BasePath;
|
||||
ExprResult CastResult =
|
||||
CheckCastTypes(LParenLoc, SourceRange(LParenLoc, RParenLoc), Ty->getType(),
|
||||
CastExpr, Kind, VK, BasePath);
|
||||
CheckCCastTypes(LParenLoc, SourceRange(LParenLoc, RParenLoc),
|
||||
Ty->getType(), CastExpr, Kind);
|
||||
if (CastResult.isInvalid())
|
||||
return ExprError();
|
||||
CastExpr = CastResult.take();
|
||||
|
||||
return Owned(CStyleCastExpr::Create(
|
||||
Context, Ty->getType().getNonLValueExprType(Context), VK, Kind, CastExpr,
|
||||
&BasePath, Ty, LParenLoc, RParenLoc));
|
||||
return Owned(CStyleCastExpr::Create(Context, Ty->getType(), VK_RValue, Kind,
|
||||
CastExpr, /*base path*/ 0, Ty,
|
||||
LParenLoc, RParenLoc));
|
||||
}
|
||||
|
||||
ExprResult Sema::BuildVectorLiteral(SourceLocation LParenLoc,
|
||||
|
|
|
@ -739,27 +739,10 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo,
|
|||
// If the expression list is a single expression, the type conversion
|
||||
// expression is equivalent (in definedness, and if defined in meaning) to the
|
||||
// corresponding cast expression.
|
||||
//
|
||||
if (NumExprs == 1) {
|
||||
CastKind Kind = CK_Invalid;
|
||||
ExprValueKind VK = VK_RValue;
|
||||
CXXCastPath BasePath;
|
||||
ExprResult CastExpr =
|
||||
CheckCastTypes(TInfo->getTypeLoc().getBeginLoc(),
|
||||
TInfo->getTypeLoc().getSourceRange(), Ty, Exprs[0],
|
||||
Kind, VK, BasePath,
|
||||
/*FunctionalStyle=*/true);
|
||||
if (CastExpr.isInvalid())
|
||||
return ExprError();
|
||||
Exprs[0] = CastExpr.take();
|
||||
|
||||
Expr *Arg = Exprs[0];
|
||||
exprs.release();
|
||||
|
||||
return Owned(CXXFunctionalCastExpr::Create(Context,
|
||||
Ty.getNonLValueExprType(Context),
|
||||
VK, TInfo, TyBeginLoc, Kind,
|
||||
Exprs[0], &BasePath,
|
||||
RParenLoc));
|
||||
return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc);
|
||||
}
|
||||
|
||||
InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo);
|
||||
|
|
Loading…
Reference in New Issue