]> granicus.if.org Git - clang/commitdiff
Fix PointerExprEvaluator::VisitCastExpr so it doesn't misfold C++ casts which
authorEli Friedman <eli.friedman@gmail.com>
Sun, 27 Dec 2009 05:43:15 +0000 (05:43 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Sun, 27 Dec 2009 05:43:15 +0000 (05:43 +0000)
it doesn't know how to fold, like derived-to-base casts.

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

lib/AST/ExprConstant.cpp
test/CodeGenCXX/const-base-cast.cpp [new file with mode: 0644]

index ec61d598a378e232650d67ff7003f0cef0d10ff2..06afec7675f1243494a65af458458966ae182ed8 100644 (file)
@@ -222,7 +222,6 @@ public:
 
   APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
   APValue VisitDeclRefExpr(DeclRefExpr *E);
-  APValue VisitBlockExpr(BlockExpr *E);
   APValue VisitPredefinedExpr(PredefinedExpr *E) { return APValue(E, 0); }
   APValue VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
   APValue VisitMemberExpr(MemberExpr *E);
@@ -270,13 +269,6 @@ APValue LValueExprEvaluator::VisitDeclRefExpr(DeclRefExpr *E) {
   return APValue();
 }
 
-APValue LValueExprEvaluator::VisitBlockExpr(BlockExpr *E) {
-  if (E->hasBlockDeclRefExprs())
-    return APValue();
-
-  return APValue(E, 0);
-}
-
 APValue LValueExprEvaluator::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
   if (!Info.AnyLValue && !E->isFileScope())
     return APValue();
@@ -366,7 +358,7 @@ public:
   APValue VisitParenExpr(ParenExpr *E) { return Visit(E->getSubExpr()); }
 
   APValue VisitBinaryOperator(const BinaryOperator *E);
-  APValue VisitCastExpr(const CastExpr* E);
+  APValue VisitCastExpr(CastExpr* E);
   APValue VisitUnaryExtension(const UnaryOperator *E)
       { return Visit(E->getSubExpr()); }
   APValue VisitUnaryAddrOf(const UnaryOperator *E);
@@ -443,23 +435,49 @@ APValue PointerExprEvaluator::VisitUnaryAddrOf(const UnaryOperator *E) {
 }
 
 
-APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
-  const Expr* SubExpr = E->getSubExpr();
+APValue PointerExprEvaluator::VisitCastExpr(CastExpr* E) {
+  Expr* SubExpr = E->getSubExpr();
 
-   // Check for pointer->pointer cast
-  if (SubExpr->getType()->isPointerType() ||
-      SubExpr->getType()->isObjCObjectPointerType() ||
-      SubExpr->getType()->isNullPtrType()) {
-    APValue Result;
-    if (EvaluatePointer(SubExpr, Result, Info))
+  switch (E->getCastKind()) {
+  default:
+    break;
+
+  case CastExpr::CK_Unknown: {
+    // FIXME: The handling for CK_Unknown is ugly/shouldn't be necessary!
+
+    // Check for pointer->pointer cast
+    if (SubExpr->getType()->isPointerType() ||
+        SubExpr->getType()->isObjCObjectPointerType() ||
+        SubExpr->getType()->isNullPtrType() ||
+        SubExpr->getType()->isBlockPointerType())
+      return Visit(SubExpr);
+
+    if (SubExpr->getType()->isIntegralType()) {
+      APValue Result;
+      if (!EvaluateIntegerOrLValue(SubExpr, Result, Info))
+        break;
+
+      if (Result.isInt()) {
+        Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
+        return APValue(0, Result.getInt().getZExtValue());
+      }
+
+      // Cast is of an lvalue, no need to change value.
       return Result;
-    return APValue();
+    }
+    break;
   }
 
-  if (SubExpr->getType()->isIntegralType()) {
+  case CastExpr::CK_NoOp:
+  case CastExpr::CK_BitCast:
+  case CastExpr::CK_AnyPointerToObjCPointerCast:
+  case CastExpr::CK_AnyPointerToBlockPointerCast:
+    return Visit(SubExpr);
+
+  case CastExpr::CK_IntegralToPointer: {
     APValue Result;
     if (!EvaluateIntegerOrLValue(SubExpr, Result, Info))
-      return APValue();
+      break;
 
     if (Result.isInt()) {
       Result.getInt().extOrTrunc((unsigned)Info.Ctx.getTypeSize(E->getType()));
@@ -469,14 +487,13 @@ APValue PointerExprEvaluator::VisitCastExpr(const CastExpr* E) {
     // Cast is of an lvalue, no need to change value.
     return Result;
   }
-
-  if (SubExpr->getType()->isFunctionType() ||
-      SubExpr->getType()->isBlockPointerType() ||
-      SubExpr->getType()->isArrayType()) {
+  case CastExpr::CK_ArrayToPointerDecay:
+  case CastExpr::CK_FunctionToPointerDecay: {
     APValue Result;
     if (EvaluateLValue(SubExpr, Result, Info))
       return Result;
-    return APValue();
+    break;
+  }
   }
 
   return APValue();
diff --git a/test/CodeGenCXX/const-base-cast.cpp b/test/CodeGenCXX/const-base-cast.cpp
new file mode 100644 (file)
index 0000000..a71384d
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: clang -cc1 -O1 -emit-llvm %s -o - | FileCheck %s
+
+// Check that the following construct, which is similar to one which occurs
+// in Firefox, is not misfolded (folding it correctly would be a bonus, but
+// that doesn't work at the moment, hence the -O1 in the runline).
+struct A { char x; };
+struct B { char y; };
+struct C : A,B {};
+unsigned char x = ((char*)(B*)(C*)0x1000) - (char*)0x1000;
+
+// CHECK: @x = global i8 1