From b50451a188b8b360e9a361d31e9c823cc31515c7 Mon Sep 17 00:00:00 2001 From: John McCall Date: Wed, 5 Oct 2011 07:41:44 +0000 Subject: [PATCH] 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 --- clang/include/clang/Sema/Sema.h | 25 +-- clang/lib/Sema/SemaCXXCast.cpp | 334 ++++++++++++++++---------------- clang/lib/Sema/SemaChecking.cpp | 15 +- clang/lib/Sema/SemaExpr.cpp | 50 ++--- clang/lib/Sema/SemaExprCXX.cpp | 21 +- 5 files changed, 222 insertions(+), 223 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 5ed595ac587c..b1b4da37af0c 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -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,12 +5778,17 @@ 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. void CheckObjCARCConversion(SourceRange castRange, QualType castType, diff --git a/clang/lib/Sema/SemaCXXCast.cpp b/clang/lib/Sema/SemaCXXCast.cpp index 583a7fa3dd09..5c5c702fd505 100644 --- a/clang/lib/Sema/SemaCXXCast.cpp +++ b/clang/lib/Sema/SemaCXXCast.cpp @@ -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())); + return Owned(CXXDynamicCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, + Op.SrcExpr.take(), &Op.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()) + Op.CheckReinterpretCast(); + if (Op.SrcExpr.isInvalid()) return ExprError(); } - return Owned(CXXReinterpretCastExpr::Create(Context, - DestType.getNonLValueExprType(Context), - VK, Kind, Ex.take(), 0, - DestTInfo, OpLoc, Parens.getEnd())); + return Owned(CXXReinterpretCastExpr::Create(Context, Op.ResultType, + Op.ValueKind, Op.Kind, + Op.SrcExpr.take(), 0, + DestTInfo, OpLoc, + Parens.getEnd())); } case tok::kw_static_cast: { - CastKind Kind = CK_Dependent; - CXXCastPath BasePath; if (!TypeDependent) { - CheckStaticCast(*this, Ex, DestType, VK, OpRange, Kind, BasePath); - if (Ex.isInvalid()) + 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\(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())) { DestPointee = DestReference->getPointeeType(); - VK = isa(DestReference) ? VK_LValue - : isa(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\(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\(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\(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,16 +695,12 @@ 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 @@ -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()); + if (SrcExpr.get()->getType() == Self.Context.BoundMemberTy) { + Self.CheckPlaceholderExpr(SrcExpr.take()); // will always fail + return; + } - return Owned(CastExpr); + assert(!SrcExpr.get()->getType()->isPlaceholderType()); + + return; } - // Make sure we determine the value kind before we bail out for - // dependent types. - VK = Expr::getValueKindForType(CastTy); - // 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()) + if (const VectorType *vecTy = DestType->getAs()) 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,47 +1747,79 @@ 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, - /* Complain */ true, + FunctionDecl *Fn = Self.ResolveAddressOfOverloadedFunction(SrcExpr.get(), + DestType, + /*Complain*/ true, Found); assert(!Fn && "cast failed but able to resolve overload expression!!"); (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)); } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index e0b24c4be6eb..c25429c9ab9d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -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(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 242fcfacde56..7721caf93974 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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, - SourceRange TypeRange, QualType CastType, - Expr *CastExpr, CastKind &Kind, - ExprValueKind &VK, CXXCastPath &BasePath, - bool FunctionalStyle) { - if (CastExpr->getType() == Context.UnknownAnyTy) +/// 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); + } - 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,9 +4203,9 @@ 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()), + CheckObjCARCConversion(SourceRange(CastStartLoc, CastExpr->getLocEnd()), CastType, CastExpr, CCK_CStyleCast); if (const PointerType *CastPtr = CastType->getAs()) { @@ -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, diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 946f02c567dd..7571f7610c9d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -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);