summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp142
1 files changed, 105 insertions, 37 deletions
diff --git a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
index eb11a57..ba00b71 100644
--- a/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
+++ b/contrib/llvm/tools/clang/lib/Sema/SemaCast.cpp
@@ -200,8 +200,9 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr,
unsigned &msg, CastKind &Kind,
CXXCastPath &BasePath,
bool ListInitialization);
-static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
- bool CStyle, unsigned &msg);
+static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
+ QualType DestType, bool CStyle,
+ unsigned &msg);
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
QualType DestType, bool CStyle,
const SourceRange &OpRange,
@@ -242,7 +243,9 @@ Sema::BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,
// 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();
+ bool TypeDependent = DestType->isDependentType() ||
+ Ex.get()->isTypeDependent() ||
+ Ex.get()->isValueDependent();
CastOperation Op(*this, DestType, E);
Op.OpRange = SourceRange(OpLoc, Parens.getEnd());
@@ -383,11 +386,6 @@ static bool tryDiagnoseOverloadedCast(Sema &S, CastType CT,
static void diagnoseBadCast(Sema &S, unsigned msg, CastType castType,
SourceRange opRange, Expr *src, QualType destType,
bool listInitialization) {
- if (src->getType() == S.Context.BoundMemberTy) {
- (void) S.CheckPlaceholderExpr(src); // will always fail
- return;
- }
-
if (msg == diag::err_bad_cxx_cast_generic &&
tryDiagnoseOverloadedCast(S, castType, opRange, src, destType,
listInitialization))
@@ -515,8 +513,8 @@ CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType,
QualType SrcConstruct = Self.Context.VoidTy;
QualType DestConstruct = Self.Context.VoidTy;
ASTContext &Context = Self.Context;
- for (SmallVector<Qualifiers, 8>::reverse_iterator i1 = cv1.rbegin(),
- i2 = cv2.rbegin();
+ for (SmallVectorImpl<Qualifiers>::reverse_iterator i1 = cv1.rbegin(),
+ i2 = cv2.rbegin();
i1 != cv1.rend(); ++i1, ++i2) {
SrcConstruct
= Context.getPointerType(Context.getQualifiedType(SrcConstruct, *i1));
@@ -558,6 +556,7 @@ void CastOperation::CheckDynamicCast() {
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ref_or_ptr)
<< this->DestType << DestRange;
+ SrcExpr = ExprError();
return;
}
@@ -567,11 +566,14 @@ void CastOperation::CheckDynamicCast() {
} else if (DestRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), DestPointee,
diag::err_bad_dynamic_cast_incomplete,
- DestRange))
+ DestRange)) {
+ SrcExpr = ExprError();
return;
+ }
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
<< DestPointee.getUnqualifiedType() << DestRange;
+ SrcExpr = ExprError();
return;
}
@@ -587,6 +589,7 @@ void CastOperation::CheckDynamicCast() {
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_ptr)
<< OrigSrcType << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
return;
}
} else if (DestReference->isLValueReferenceType()) {
@@ -603,11 +606,14 @@ void CastOperation::CheckDynamicCast() {
if (SrcRecord) {
if (Self.RequireCompleteType(OpRange.getBegin(), SrcPointee,
diag::err_bad_dynamic_cast_incomplete,
- SrcExpr.get()))
+ SrcExpr.get())) {
+ SrcExpr = ExprError();
return;
+ }
} else {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_class)
<< SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
return;
}
@@ -621,6 +627,7 @@ void CastOperation::CheckDynamicCast() {
if (!DestPointee.isAtLeastAsQualifiedAs(SrcPointee)) {
Self.Diag(OpRange.getBegin(), diag::err_bad_cxx_cast_qualifiers_away)
<< CT_Dynamic << OrigSrcType << this->DestType << OpRange;
+ SrcExpr = ExprError();
return;
}
@@ -636,8 +643,10 @@ void CastOperation::CheckDynamicCast() {
if (DestRecord && Self.IsDerivedFrom(SrcPointee, DestPointee)) {
if (Self.CheckDerivedToBaseConversion(SrcPointee, DestPointee,
OpRange.getBegin(), OpRange,
- &BasePath))
- return;
+ &BasePath)) {
+ SrcExpr = ExprError();
+ return;
+ }
Kind = CK_DerivedToBase;
@@ -655,10 +664,20 @@ void CastOperation::CheckDynamicCast() {
if (!cast<CXXRecordDecl>(SrcDecl)->isPolymorphic()) {
Self.Diag(OpRange.getBegin(), diag::err_bad_dynamic_cast_not_polymorphic)
<< SrcPointee.getUnqualifiedType() << SrcExpr.get()->getSourceRange();
+ SrcExpr = ExprError();
}
Self.MarkVTableUsed(OpRange.getBegin(),
cast<CXXRecordDecl>(SrcRecord->getDecl()));
+ // dynamic_cast is not available with -fno-rtti.
+ // As an exception, dynamic_cast to void* is available because it doesn't
+ // use RTTI.
+ if (!Self.getLangOpts().RTTI && !DestPointee->isVoidType()) {
+ Self.Diag(OpRange.getBegin(), diag::err_no_dynamic_cast_with_fno_rtti);
+ SrcExpr = ExprError();
+ return;
+ }
+
// Done. Everything else is run-time checks.
Kind = CK_Dynamic;
}
@@ -677,10 +696,12 @@ void CastOperation::CheckConstCast() {
return;
unsigned msg = diag::err_bad_cxx_cast_generic;
- if (TryConstCast(Self, SrcExpr.get(), DestType, /*CStyle*/false, msg) != TC_Success
- && msg != 0)
+ if (TryConstCast(Self, SrcExpr, DestType, /*CStyle*/false, msg) != TC_Success
+ && msg != 0) {
Self.Diag(OpRange.getBegin(), msg) << CT_Const
<< SrcExpr.get()->getType() << DestType << OpRange;
+ SrcExpr = ExprError();
+ }
}
/// Check that a reinterpret_cast\<DestType\>(SrcExpr) is not used as upcast
@@ -758,6 +779,7 @@ static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
VirtualBase = VirtualBase && IsVirtual;
}
+ (void) NonZeroOffset; // Silence set but not used warning.
assert((VirtualBase || NonZeroOffset) &&
"Should have returned if has non-virtual base with zero offset");
@@ -768,10 +790,10 @@ static void DiagnoseReinterpretUpDownCast(Sema &Self, const Expr *SrcExpr,
SourceLocation BeginLoc = OpRange.getBegin();
Self.Diag(BeginLoc, diag::warn_reinterpret_different_from_static)
- << DerivedType << BaseType << !VirtualBase << ReinterpretKind
+ << DerivedType << BaseType << !VirtualBase << int(ReinterpretKind)
<< OpRange;
Self.Diag(BeginLoc, diag::note_reinterpret_updowncast_use_static)
- << ReinterpretKind
+ << int(ReinterpretKind)
<< FixItHint::CreateReplacement(BeginLoc, "static_cast");
}
@@ -807,6 +829,7 @@ void CastOperation::CheckReinterpretCast() {
diagnoseBadCast(Self, msg, CT_Reinterpret, OpRange, SrcExpr.get(),
DestType, /*listInitialization=*/false);
}
+ SrcExpr = ExprError();
} else if (tcr == TC_Success) {
if (Self.getLangOpts().ObjCAutoRefCount)
checkObjCARCConversion(Sema::CCK_OtherCast);
@@ -868,6 +891,7 @@ void CastOperation::CheckStaticCast() {
diagnoseBadCast(Self, msg, CT_Static, OpRange, SrcExpr.get(), DestType,
/*listInitialization=*/false);
}
+ SrcExpr = ExprError();
} else if (tcr == TC_Success) {
if (Kind == CK_BitCast)
checkCastAlign();
@@ -1447,12 +1471,26 @@ TryStaticImplicitCast(Sema &Self, ExprResult &SrcExpr, QualType DestType,
/// TryConstCast - See if a const_cast from source to destination is allowed,
/// and perform it if it is.
-static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
- bool CStyle, unsigned &msg) {
+static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr,
+ QualType DestType, bool CStyle,
+ unsigned &msg) {
DestType = Self.Context.getCanonicalType(DestType);
- QualType SrcType = SrcExpr->getType();
+ QualType SrcType = SrcExpr.get()->getType();
+ bool NeedToMaterializeTemporary = false;
+
if (const ReferenceType *DestTypeTmp =DestType->getAs<ReferenceType>()) {
- if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr->isLValue()) {
+ // C++11 5.2.11p4:
+ // if a pointer to T1 can be explicitly converted to the type "pointer to
+ // T2" using a const_cast, then the following conversions can also be
+ // made:
+ // -- an lvalue of type T1 can be explicitly converted to an lvalue of
+ // type T2 using the cast const_cast<T2&>;
+ // -- a glvalue of type T1 can be explicitly converted to an xvalue of
+ // type T2 using the cast const_cast<T2&&>; and
+ // -- if T1 is a class type, a prvalue of type T1 can be explicitly
+ // converted to an xvalue of type T2 using the cast const_cast<T2&&>.
+
+ if (isa<LValueReferenceType>(DestTypeTmp) && !SrcExpr.get()->isLValue()) {
// Cannot const_cast non-lvalue to lvalue reference type. But if this
// is C-style, static_cast might find a way, so we simply suggest a
// message and tell the parent to keep searching.
@@ -1460,18 +1498,29 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
return TC_NotApplicable;
}
+ if (isa<RValueReferenceType>(DestTypeTmp) && SrcExpr.get()->isRValue()) {
+ if (!SrcType->isRecordType()) {
+ // Cannot const_cast non-class prvalue to rvalue reference type. But if
+ // this is C-style, static_cast can do this.
+ msg = diag::err_bad_cxx_cast_rvalue;
+ return TC_NotApplicable;
+ }
+
+ // Materialize the class prvalue so that the const_cast can bind a
+ // reference to it.
+ NeedToMaterializeTemporary = true;
+ }
+
// It's not completely clear under the standard whether we can
// const_cast bit-field gl-values. Doing so would not be
// intrinsically complicated, but for now, we say no for
// consistency with other compilers and await the word of the
// committee.
- if (SrcExpr->refersToBitField()) {
+ if (SrcExpr.get()->refersToBitField()) {
msg = diag::err_bad_cxx_cast_bitfield;
return TC_NotApplicable;
}
- // C++ 5.2.11p4: An lvalue of type T1 can be [cast] to an lvalue of type T2
- // [...] if a pointer to T1 can be [cast] to the type pointer to T2.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
}
@@ -1525,6 +1574,13 @@ static TryCastResult TryConstCast(Sema &Self, Expr *SrcExpr, QualType DestType,
if (SrcType != DestType)
return TC_NotApplicable;
+ if (NeedToMaterializeTemporary)
+ // This is a const_cast from a class prvalue to an rvalue reference type.
+ // Materialize a temporary to store the result of the conversion.
+ SrcExpr = new (Self.Context) MaterializeTemporaryExpr(
+ SrcType, SrcExpr.take(), /*IsLValueReference*/ false,
+ /*ExtendingDecl*/ 0);
+
return TC_Success;
}
@@ -1614,8 +1670,18 @@ static void checkIntToPointerCast(bool CStyle, SourceLocation Loc,
&& !SrcType->isBooleanType()
&& !SrcType->isEnumeralType()
&& !SrcExpr->isIntegerConstantExpr(Self.Context)
- && Self.Context.getTypeSize(DestType) > Self.Context.getTypeSize(SrcType))
- Self.Diag(Loc, diag::warn_int_to_pointer_cast) << SrcType << DestType;
+ && Self.Context.getTypeSize(DestType) >
+ Self.Context.getTypeSize(SrcType)) {
+ // Separate between casts to void* and non-void* pointers.
+ // Some APIs use (abuse) void* for something like a user context,
+ // and often that value is an integer even if it isn't a pointer itself.
+ // Having a separate warning flag allows users to control the warning
+ // for their workflow.
+ unsigned Diag = DestType->isVoidPointerType() ?
+ diag::warn_int_to_void_pointer_cast
+ : diag::warn_int_to_pointer_cast;
+ Self.Diag(Loc, Diag) << SrcType << DestType;
+ }
}
static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
@@ -1803,10 +1869,12 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr,
assert(srcIsPtr && "One type must be a pointer");
// C++ 5.2.10p4: A pointer can be explicitly converted to any integral
// type large enough to hold it; except in Microsoft mode, where the
- // integral type size doesn't matter.
+ // integral type size doesn't matter (except we don't allow bool).
+ bool MicrosoftException = Self.getLangOpts().MicrosoftExt &&
+ !DestType->isBooleanType();
if ((Self.Context.getTypeSize(SrcType) >
Self.Context.getTypeSize(DestType)) &&
- !Self.getLangOpts().MicrosoftExt) {
+ !MicrosoftException) {
msg = diag::err_bad_reinterpret_cast_small_int;
return TC_Failed;
}
@@ -1940,14 +2008,12 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
}
SrcExpr = Self.IgnoredValueConversions(SrcExpr.take());
- if (SrcExpr.isInvalid())
- return;
-
return;
}
// If the type is dependent, we won't do any other semantic analysis now.
- if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent()) {
+ if (DestType->isDependentType() || SrcExpr.get()->isTypeDependent() ||
+ SrcExpr.get()->isValueDependent()) {
assert(Kind == CK_Dependent);
return;
}
@@ -1980,8 +2046,10 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle,
// 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(Self, SrcExpr.get(), DestType,
+ TryCastResult tcr = TryConstCast(Self, SrcExpr, DestType,
/*CStyle*/true, msg);
+ if (SrcExpr.isInvalid())
+ return;
if (tcr == TC_Success)
Kind = CK_NoOp;
@@ -2298,9 +2366,9 @@ ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo,
return ExprError();
if (CXXConstructExpr *ConstructExpr = dyn_cast<CXXConstructExpr>(Op.SrcExpr.get()))
- ConstructExpr->setParenRange(SourceRange(LPLoc, RPLoc));
+ ConstructExpr->setParenOrBraceRange(SourceRange(LPLoc, RPLoc));
return Op.complete(CXXFunctionalCastExpr::Create(Context, Op.ResultType,
- Op.ValueKind, CastTypeInfo, Op.DestRange.getBegin(),
- Op.Kind, Op.SrcExpr.take(), &Op.BasePath, RPLoc));
+ Op.ValueKind, CastTypeInfo, Op.Kind,
+ Op.SrcExpr.take(), &Op.BasePath, LPLoc, RPLoc));
}
OpenPOWER on IntegriCloud