Reinstate r151879, r151880, reverted in r151922, along with a bugfix for
scalar emission of DeclRefExprs to const bools: emit scalar bools as i1,
not as i8.

In addition to the extra unit testing, this has successfully bootstrapped.

llvm-svn: 151955
diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp
index 2803640..61c10bb 100644
--- a/clang/lib/CodeGen/CGExprConstant.cpp
+++ b/clang/lib/CodeGen/CGExprConstant.cpp
@@ -511,7 +511,7 @@
     const APValue &FieldValue =
       RD->isUnion() ? Val.getUnionValue() : Val.getStructField(FieldNo);
     llvm::Constant *EltInit =
-      CGM.EmitConstantValue(FieldValue, Field->getType(), CGF);
+      CGM.EmitConstantValueForMemory(FieldValue, Field->getType(), CGF);
     assert(EltInit && "EmitConstantValue can't fail");
 
     if (!Field->isBitField()) {
@@ -1015,7 +1015,7 @@
 llvm::Constant *CodeGenModule::EmitConstantInit(const VarDecl &D,
                                                 CodeGenFunction *CGF) {
   if (const APValue *Value = D.evaluateValue())
-    return EmitConstantValue(*Value, D.getType(), CGF);
+    return EmitConstantValueForMemory(*Value, D.getType(), CGF);
 
   // FIXME: Implement C++11 [basic.start.init]p2: if the initializer of a
   // reference is a constant expression, and the reference binds to a temporary,
@@ -1049,10 +1049,12 @@
   else
     Success = E->EvaluateAsRValue(Result, Context);
 
+  llvm::Constant *C = 0;
   if (Success && !Result.HasSideEffects)
-    return EmitConstantValue(Result.Val, DestType, CGF);
+    C = EmitConstantValue(Result.Val, DestType, CGF);
+  else
+    C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
 
-  llvm::Constant* C = ConstExprEmitter(*this, CGF).Visit(const_cast<Expr*>(E));
   if (C && C->getType()->isIntegerTy(1)) {
     llvm::Type *BoolTy = getTypes().ConvertTypeForMem(E->getType());
     C = llvm::ConstantExpr::getZExt(C, BoolTy);
@@ -1110,16 +1112,8 @@
       return C;
     }
   }
-  case APValue::Int: {
-    llvm::Constant *C = llvm::ConstantInt::get(VMContext,
-                                               Value.getInt());
-
-    if (C->getType()->isIntegerTy(1)) {
-      llvm::Type *BoolTy = getTypes().ConvertTypeForMem(DestType);
-      C = llvm::ConstantExpr::getZExt(C, BoolTy);
-    }
-    return C;
-  }
+  case APValue::Int:
+    return llvm::ConstantInt::get(VMContext, Value.getInt());
   case APValue::ComplexInt: {
     llvm::Constant *Complex[2];
 
@@ -1199,16 +1193,16 @@
     // Emit array filler, if there is one.
     llvm::Constant *Filler = 0;
     if (Value.hasArrayFiller())
-      Filler = EmitConstantValue(Value.getArrayFiller(),
-                                 CAT->getElementType(), CGF);
+      Filler = EmitConstantValueForMemory(Value.getArrayFiller(),
+                                          CAT->getElementType(), CGF);
 
     // Emit initializer elements.
     llvm::Type *CommonElementType = 0;
     for (unsigned I = 0; I < NumElements; ++I) {
       llvm::Constant *C = Filler;
       if (I < NumInitElts)
-        C = EmitConstantValue(Value.getArrayInitializedElt(I),
-                              CAT->getElementType(), CGF);
+        C = EmitConstantValueForMemory(Value.getArrayInitializedElt(I),
+                                       CAT->getElementType(), CGF);
       if (I == 0)
         CommonElementType = C->getType();
       else if (C->getType() != CommonElementType)
@@ -1237,6 +1231,18 @@
 }
 
 llvm::Constant *
+CodeGenModule::EmitConstantValueForMemory(const APValue &Value,
+                                          QualType DestType,
+                                          CodeGenFunction *CGF) {
+  llvm::Constant *C = EmitConstantValue(Value, DestType, CGF);
+  if (C->getType()->isIntegerTy(1)) {
+    llvm::Type *BoolTy = getTypes().ConvertTypeForMem(DestType);
+    C = llvm::ConstantExpr::getZExt(C, BoolTy);
+  }
+  return C;
+}
+
+llvm::Constant *
 CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
   assert(E->isFileScope() && "not a file-scope compound literal expr");
   return ConstExprEmitter(*this, 0).EmitLValue(E);
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index 125e431..f7ab880 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -212,18 +212,21 @@
   // l-values.
   Value *VisitDeclRefExpr(DeclRefExpr *E) {
     Expr::EvalResult Result;
-    if (!E->EvaluateAsRValue(Result, CGF.getContext()))
-      return EmitLoadOfLValue(E);
+    bool IsReferenceConstant = false;
+    QualType EvalTy = E->getType();
+    if (!E->EvaluateAsRValue(Result, CGF.getContext())) {
+      // If this is a reference, try to determine what it is bound to.
+      if (!E->getDecl()->getType()->isReferenceType() ||
+          !E->EvaluateAsLValue(Result, CGF.getContext()))
+        return EmitLoadOfLValue(E);
+
+      IsReferenceConstant = true;
+      EvalTy = E->getDecl()->getType();
+    }
 
     assert(!Result.HasSideEffects && "Constant declref with side-effect?!");
 
-    llvm::Constant *C;
-    if (Result.Val.isInt())
-      C = Builder.getInt(Result.Val.getInt());
-    else if (Result.Val.isFloat())
-      C = llvm::ConstantFP::get(VMContext, Result.Val.getFloat());
-    else
-      return EmitLoadOfLValue(E);
+    llvm::Constant *C = CGF.CGM.EmitConstantValue(Result.Val, EvalTy, &CGF);
 
     // Make sure we emit a debug reference to the global variable.
     if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) {
@@ -233,6 +236,9 @@
       CGF.EmitDeclRefExprDbgValue(E, C);
     }
 
+    if (IsReferenceConstant)
+      return EmitLoadOfLValue(CGF.MakeNaturalAlignAddrLValue(C, E->getType()));
+
     return C;
   }
   Value *VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index a3a71b7..922a5df 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -1472,7 +1472,8 @@
   }
 
   // Emit the constant for the initializer_list.
-  llvm::Constant *llvmInit = EmitConstantValue(initListValue, D->getType());
+  llvm::Constant *llvmInit =
+      EmitConstantValueForMemory(initListValue, D->getType());
   assert(llvmInit && "failed to initialize as constant");
   return llvmInit;
 }
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 8bbee6a2..ba4887d 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -706,11 +706,17 @@
   llvm::Constant *EmitConstantExpr(const Expr *E, QualType DestType,
                                    CodeGenFunction *CGF = 0);
 
-  /// EmitConstantValue - Try to emit the given constant value as a
-  /// constant; returns 0 if the value cannot be emitted as a constant.
+  /// EmitConstantValue - Emit the given constant value as a constant, in the
+  /// type's scalar representation.
   llvm::Constant *EmitConstantValue(const APValue &Value, QualType DestType,
                                     CodeGenFunction *CGF = 0);
 
+  /// EmitConstantValueForMemory - Emit the given constant value as a constant,
+  /// in the type's memory representation.
+  llvm::Constant *EmitConstantValueForMemory(const APValue &Value,
+                                             QualType DestType,
+                                             CodeGenFunction *CGF = 0);
+
   /// EmitNullConstant - Return the result of value-initializing the given
   /// type, i.e. a null expression of the given type.  This is usually,
   /// but not always, an LLVM null constant.