]> granicus.if.org Git - clang/commitdiff
Introduce a new cast kind for an "lvalue bitcast", which handles
authorDouglas Gregor <dgregor@apple.com>
Tue, 13 Jul 2010 23:17:26 +0000 (23:17 +0000)
committerDouglas Gregor <dgregor@apple.com>
Tue, 13 Jul 2010 23:17:26 +0000 (23:17 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108294 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Expr.h
lib/AST/Expr.cpp
lib/AST/ExprConstant.cpp
lib/Checker/GRExprEngine.cpp
lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGExprAgg.cpp
lib/CodeGen/CGExprScalar.cpp
lib/Sema/SemaCXXCast.cpp

index 807644349e567730f1dc3cab83c03ed24ada388f..ade2b09c80c256c6d9f456b2cb019980176ee76a 100644 (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:
index bd97b886fe1e9d40b1dbd0be81eb081d812b4683..6524a312dc8b8a1ba7344c759a05ad9ca54c0915 100644 (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:
index a963182ae88b9eff012b68b242e8411e47a2249b..3c9742033265598504369b67f22c7b766e46f03c 100644 (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);
index 4652a4c89ff3bee4dcb30fd29d77652c093a10c2..07fee9d39e493840485fb10d10f97b9f090fb414 100644 (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:
index 0426a60f0c37fc517a730834523c6e6d0d3a7ff1..5a4808bce9d6553df56140c9ca4508a1a55a40cc 100644 (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);
     
index 20722f7799cfb55d93141447ea4a7cadf58193e6..219a5f9153290e0e321a1de64461b901ef5e00cf 100644 (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());
index 1ebc2c571a017cc62f95d5c86ddb979091a79f57..ef38209e1eaf42b9a992e6f5016e978abc06e070 100644 (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: {
index 911578622d23ac637e3082f0822e247ba9f7757f..b8e27e7b7285a56e87ca18eb37b29a2e4049087d 100644 (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()) {