Introduce a new cast kind for an "lvalue bitcast", which handles

reinterpret_casts (possibly indirectly via C-style/functional casts)
on values, e.g., 

  int i;
  reinterpret_cast<short&>(i);

The IR generated for this is essentially the same as for

  *reinterpret_cast<short*>(&i).

Fixes PR6437, PR7593, and PR7344. 

llvm-svn: 108294
This commit is contained in:
Douglas Gregor 2010-07-13 23:17:26 +00:00
parent 11e8f3ba37
commit 51954276cc
8 changed files with 29 additions and 3 deletions

View File

@ -1854,6 +1854,10 @@ public:
/// CK_BitCast - Used for reinterpret_cast.
CK_BitCast,
/// CK_LValueBitCast - Used for reinterpret_cast of expressions to
/// a reference type.
CK_LValueBitCast,
/// CK_NoOp - Used for const_cast.
CK_NoOp,
@ -1957,6 +1961,7 @@ private:
// These should not have an inheritance path.
case CK_Unknown:
case CK_BitCast:
case CK_LValueBitCast:
case CK_NoOp:
case CK_Dynamic:
case CK_ToUnion:

View File

@ -684,6 +684,8 @@ const char *CastExpr::getCastKindName() const {
return "Unknown";
case CastExpr::CK_BitCast:
return "BitCast";
case CastExpr::CK_LValueBitCast:
return "LValueBitCast";
case CastExpr::CK_NoOp:
return "NoOp";
case CastExpr::CK_BaseToDerived:

View File

@ -563,6 +563,7 @@ bool PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
case CastExpr::CK_NoOp:
case CastExpr::CK_BitCast:
case CastExpr::CK_LValueBitCast:
case CastExpr::CK_AnyPointerToObjCPointerCast:
case CastExpr::CK_AnyPointerToBlockPointerCast:
return Visit(SubExpr);

View File

@ -2438,6 +2438,7 @@ void GRExprEngine::VisitCast(CastExpr *CastE, Expr *Ex, ExplodedNode *Pred,
case CastExpr::CK_Unknown:
case CastExpr::CK_ArrayToPointerDecay:
case CastExpr::CK_BitCast:
case CastExpr::CK_LValueBitCast:
case CastExpr::CK_IntegralCast:
case CastExpr::CK_IntegralToPointer:
case CastExpr::CK_PointerToIntegral:

View File

@ -1816,7 +1816,8 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {
return LValue::MakeAddr(Derived, MakeQualifiers(E->getType()));
}
case CastExpr::CK_BitCast: {
case CastExpr::CK_BitCast:
case CastExpr::CK_LValueBitCast: {
// This must be a reinterpret_cast (or c-style equivalent).
const ExplicitCastExpr *CE = cast<ExplicitCastExpr>(E);

View File

@ -307,6 +307,10 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
break;
}
case CastExpr::CK_LValueBitCast:
llvm_unreachable("there are no lvalue bit-casts on aggregates");
break;
case CastExpr::CK_BitCast: {
// This must be a member function pointer cast.
Visit(E->getSubExpr());

View File

@ -925,6 +925,15 @@ Value *ScalarExprEmitter::EmitCastExpr(CastExpr *CE) {
//assert(0 && "Unknown cast kind!");
break;
case CastExpr::CK_LValueBitCast: {
Value *V = EmitLValue(E).getAddress();
V = Builder.CreateBitCast(V,
ConvertType(CGF.getContext().getPointerType(DestTy)));
// FIXME: Are the qualifiers correct here?
return EmitLoadOfLValue(LValue::MakeAddr(V, CGF.MakeQualifiers(DestTy)),
DestTy);
}
case CastExpr::CK_AnyPointerToObjCPointerCast:
case CastExpr::CK_AnyPointerToBlockPointerCast:
case CastExpr::CK_BitCast: {

View File

@ -1052,6 +1052,8 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
const SourceRange &OpRange,
unsigned &msg,
CastExpr::CastKind &Kind) {
bool IsLValueCast = false;
DestType = Self.Context.getCanonicalType(DestType);
QualType SrcType = SrcExpr->getType();
if (const ReferenceType *DestTypeTmp = DestType->getAs<ReferenceType>()) {
@ -1069,6 +1071,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
// This code does this transformation for the checked types.
DestType = Self.Context.getPointerType(DestTypeTmp->getPointeeType());
SrcType = Self.Context.getPointerType(SrcType);
IsLValueCast = true;
}
// Canonicalize source for comparison.
@ -1095,7 +1098,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
}
// A valid member pointer cast.
Kind = CastExpr::CK_BitCast;
Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast;
return TC_Success;
}
@ -1212,7 +1215,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,
// Not casting away constness, so the only remaining check is for compatible
// pointer categories.
Kind = CastExpr::CK_BitCast;
Kind = IsLValueCast? CastExpr::CK_LValueBitCast : CastExpr::CK_BitCast;
if (SrcType->isFunctionPointerType()) {
if (DestType->isFunctionPointerType()) {