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:
John McCall 2011-10-05 07:41:44 +00:00
parent ad33c139ac
commit b50451a188
5 changed files with 222 additions and 223 deletions

View File

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

View File

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

View File

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

View File

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

View File

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