Add an APValue representation for the difference between two address-of-label expressions.  Add support to Evaluate and CGExprConstant for generating/handling them.  Remove the special-case for such differences in Expr::isConstantInitializer.

With that done, remove a bunch of buggy code from CGExprConstant for handling scalar expressions which is no longer necessary.

Fixes PR11705.

llvm-svn: 147561
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 1bd9429..2c15132 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -500,27 +500,6 @@
     return 0;
   }
     
-  llvm::Constant *VisitBinSub(BinaryOperator *E) {
-    // This must be a pointer/pointer subtraction.  This only happens for
-    // address of label.
-    if (!isa<AddrLabelExpr>(E->getLHS()->IgnoreParenNoopCasts(CGM.getContext())) ||
-       !isa<AddrLabelExpr>(E->getRHS()->IgnoreParenNoopCasts(CGM.getContext())))
-      return 0;
-    
-    llvm::Constant *LHS = CGM.EmitConstantExpr(E->getLHS(),
-                                               E->getLHS()->getType(), CGF);
-    llvm::Constant *RHS = CGM.EmitConstantExpr(E->getRHS(),
-                                               E->getRHS()->getType(), CGF);
-
-    llvm::Type *ResultType = ConvertType(E->getType());
-    LHS = llvm::ConstantExpr::getPtrToInt(LHS, ResultType);
-    RHS = llvm::ConstantExpr::getPtrToInt(RHS, ResultType);
-        
-    // No need to divide by element size, since addr of label is always void*,
-    // which has size 1 in GNUish.
-    return llvm::ConstantExpr::getSub(LHS, RHS);
-  }
-    
   llvm::Constant *VisitCastExpr(CastExpr* E) {
     Expr *subExpr = E->getSubExpr();
     llvm::Constant *C = CGM.EmitConstantExpr(subExpr, subExpr->getType(), CGF);
@@ -570,13 +549,6 @@
     case CK_NoOp:
       return C;
 
-    case CK_CPointerToObjCPointerCast:
-    case CK_BlockPointerToObjCPointerCast:
-    case CK_AnyPointerToBlockPointerCast:
-    case CK_BitCast:
-      if (C->getType() == destType) return C;
-      return llvm::ConstantExpr::getBitCast(C, destType);
-
     case CK_Dependent: llvm_unreachable("saw dependent cast!");
 
     // These will never be supported.
@@ -595,7 +567,12 @@
     case CK_ConstructorConversion:
       return 0;
 
-    // These should eventually be supported.
+    // These don't need to be handled here because Evaluate knows how to
+    // evaluate all scalar expressions which can be constant-evaluated.
+    case CK_CPointerToObjCPointerCast:
+    case CK_BlockPointerToObjCPointerCast:
+    case CK_AnyPointerToBlockPointerCast:
+    case CK_BitCast:
     case CK_ArrayToPointerDecay:
     case CK_FunctionToPointerDecay:
     case CK_BaseToDerived:
@@ -613,53 +590,17 @@
     case CK_IntegralComplexToBoolean:
     case CK_IntegralComplexCast:
     case CK_IntegralComplexToFloatingComplex:
-      return 0;
-
     case CK_PointerToIntegral:
-      if (!E->getType()->isBooleanType())
-        return llvm::ConstantExpr::getPtrToInt(C, destType);
-      // fallthrough
-
     case CK_PointerToBoolean:
-      return llvm::ConstantExpr::getICmp(llvm::CmpInst::ICMP_EQ, C,
-        llvm::ConstantPointerNull::get(cast<llvm::PointerType>(C->getType())));
-
     case CK_NullToPointer:
-      return llvm::ConstantPointerNull::get(cast<llvm::PointerType>(destType));
-
-    case CK_IntegralCast: {
-      bool isSigned = subExpr->getType()->isSignedIntegerOrEnumerationType();
-      return llvm::ConstantExpr::getIntegerCast(C, destType, isSigned);
-    }
-
-    case CK_IntegralToPointer: {
-      bool isSigned = subExpr->getType()->isSignedIntegerOrEnumerationType();
-      C = llvm::ConstantExpr::getIntegerCast(C, CGM.IntPtrTy, isSigned);
-      return llvm::ConstantExpr::getIntToPtr(C, destType);
-    }
-
+    case CK_IntegralCast:
+    case CK_IntegralToPointer:
     case CK_IntegralToBoolean:
-      return llvm::ConstantExpr::getICmp(llvm::CmpInst::ICMP_EQ, C,
-                             llvm::Constant::getNullValue(C->getType()));
-
     case CK_IntegralToFloating:
-      if (subExpr->getType()->isSignedIntegerOrEnumerationType())
-        return llvm::ConstantExpr::getSIToFP(C, destType);
-      else
-        return llvm::ConstantExpr::getUIToFP(C, destType);
-
     case CK_FloatingToIntegral:
-      if (E->getType()->isSignedIntegerOrEnumerationType())
-        return llvm::ConstantExpr::getFPToSI(C, destType);
-      else
-        return llvm::ConstantExpr::getFPToUI(C, destType);
-
     case CK_FloatingToBoolean:
-      return llvm::ConstantExpr::getFCmp(llvm::CmpInst::FCMP_UNE, C,
-                             llvm::Constant::getNullValue(C->getType()));
-
     case CK_FloatingCast:
-      return llvm::ConstantExpr::getFPCast(C, destType);
+      return 0;
     }
     llvm_unreachable("Invalid CastKind");
   }
@@ -1081,6 +1022,23 @@
       }
       return llvm::ConstantVector::get(Inits);
     }
+    case APValue::AddrLabelDiff: {
+      const AddrLabelExpr *LHSExpr = Result.Val.getAddrLabelDiffLHS();
+      const AddrLabelExpr *RHSExpr = Result.Val.getAddrLabelDiffRHS();
+      llvm::Constant *LHS = EmitConstantExpr(LHSExpr, LHSExpr->getType(), CGF);
+      llvm::Constant *RHS = EmitConstantExpr(RHSExpr, RHSExpr->getType(), CGF);
+
+      // Compute difference
+      llvm::Type *ResultType = getTypes().ConvertType(E->getType());
+      LHS = llvm::ConstantExpr::getPtrToInt(LHS, IntPtrTy);
+      RHS = llvm::ConstantExpr::getPtrToInt(RHS, IntPtrTy);
+      llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);
+
+      // LLVM os a bit sensitive about the exact format of the
+      // address-of-label difference; make sure to truncate after
+      // the subtraction.
+      return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
+    }
     case APValue::Array:
     case APValue::Struct:
     case APValue::Union: