Reorganize the value-dominance metaprogram and introduce a specialization
for CodeGen's RValue type.

llvm-svn: 124483
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 995a1b0..4683c96 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -97,26 +97,27 @@
   llvm::BranchInst *InitialBranch;
 };
 
-/// A metaprogramming class which decides whether a type is a subclass
-/// of llvm::Value that needs to be saved if it's used in a
-/// conditional cleanup.
-template
-  <class T,
-   bool mustSave =
-     llvm::is_base_of<llvm::Value,
-                      typename llvm::remove_pointer<T>::type>::value
-     && !llvm::is_base_of<llvm::Constant,
-                          typename llvm::remove_pointer<T>::type>::value
-     && !llvm::is_base_of<llvm::BasicBlock,
-                          typename llvm::remove_pointer<T>::type>::value>
-struct SavedValueInCond {
+template <class T> struct InvariantValue {
   typedef T type;
   typedef T saved_type;
   static bool needsSaving(type value) { return false; }
   static saved_type save(CodeGenFunction &CGF, type value) { return value; }
   static type restore(CodeGenFunction &CGF, saved_type value) { return value; }
 };
-// Partial specialization for true arguments at end of file.
+
+/// A metaprogramming class for ensuring that a value will dominate an
+/// arbitrary position in a function.
+template <class T> struct DominatingValue : InvariantValue<T> {};
+
+template <class T, bool mightBeInstruction =
+            llvm::is_base_of<llvm::Value, T>::value &&
+            !llvm::is_base_of<llvm::Constant, T>::value &&
+            !llvm::is_base_of<llvm::BasicBlock, T>::value>
+struct DominatingPointer;
+template <class T> struct DominatingPointer<T,false> : InvariantValue<T*> {};
+// template <class T> struct DominatingPointer<T,true> at end of file
+
+template <class T> struct DominatingValue<T*> : DominatingPointer<T> {};
 
 enum CleanupKind {
   EHCleanup = 0x1,
@@ -222,11 +223,11 @@
   /// then restores them and performs the cleanup.
   template <class T, class A0>
   class ConditionalCleanup1 : public Cleanup {
-    typedef typename SavedValueInCond<A0>::saved_type A0_saved;
+    typedef typename DominatingValue<A0>::saved_type A0_saved;
     A0_saved a0_saved;
 
     void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
-      A0 a0 = SavedValueInCond<A0>::restore(CGF, a0_saved);
+      A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
       T::Emit(CGF, IsForEHCleanup, a0);
     }
 
@@ -237,14 +238,14 @@
 
   template <class T, class A0, class A1>
   class ConditionalCleanup2 : public Cleanup {
-    typedef typename SavedValueInCond<A0>::saved_type A0_saved;
-    typedef typename SavedValueInCond<A1>::saved_type A1_saved;
+    typedef typename DominatingValue<A0>::saved_type A0_saved;
+    typedef typename DominatingValue<A1>::saved_type A1_saved;
     A0_saved a0_saved;
     A1_saved a1_saved;
 
     void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
-      A0 a0 = SavedValueInCond<A0>::restore(CGF, a0_saved);
-      A1 a1 = SavedValueInCond<A1>::restore(CGF, a1_saved);
+      A0 a0 = DominatingValue<A0>::restore(CGF, a0_saved);
+      A1 a1 = DominatingValue<A1>::restore(CGF, a1_saved);
       T::Emit(CGF, IsForEHCleanup, a0, a1);
     }
 
@@ -619,8 +620,8 @@
   void initFullExprCleanup();
 
   template <class T>
-  typename SavedValueInCond<T>::saved_type saveValueInCond(T value) {
-    return SavedValueInCond<T>::save(*this, value);
+  typename DominatingValue<T>::saved_type saveValueInCond(T value) {
+    return DominatingValue<T>::save(*this, value);
   }
 
 public:
@@ -651,7 +652,7 @@
       return EHStack.pushCleanup<CleanupType>(kind, a0);
     }
 
-    typename SavedValueInCond<A0>::saved_type a0_saved = saveValueInCond(a0);
+    typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
 
     typedef EHScopeStack::ConditionalCleanup1<T, A0> CleanupType;
     EHStack.pushCleanup<CleanupType>(kind, a0_saved);
@@ -670,8 +671,8 @@
       return EHStack.pushCleanup<CleanupType>(kind, a0, a1);
     }
 
-    typename SavedValueInCond<A0>::saved_type a0_saved = saveValueInCond(a0);
-    typename SavedValueInCond<A1>::saved_type a1_saved = saveValueInCond(a1);
+    typename DominatingValue<A0>::saved_type a0_saved = saveValueInCond(a0);
+    typename DominatingValue<A1>::saved_type a1_saved = saveValueInCond(a1);
 
     typedef EHScopeStack::ConditionalCleanup2<T, A0, A1> CleanupType;
     EHStack.pushCleanup<CleanupType>(kind, a0_saved, a1_saved);
@@ -1946,7 +1947,7 @@
 
 /// Helper class with most of the code for saving a value for a
 /// conditional expression cleanup.
-struct SavedValueInCondImpl {
+struct DominatingLLVMValue {
   typedef llvm::PointerIntPair<llvm::Value*, 1, bool> saved_type;
 
   /// Answer whether the given value needs extra work to be saved.
@@ -1977,12 +1978,42 @@
   }
 };
 
-/// Partial specialization of SavedValueInCond for when a value really
-/// requires saving.
-template <class T> struct SavedValueInCond<T,true> : SavedValueInCondImpl {
-  typedef T type;
+/// A partial specialization of DominatingValue for llvm::Values that
+/// might be llvm::Instructions.
+template <class T> struct DominatingPointer<T,true> : DominatingLLVMValue {
+  typedef T *type;
   static type restore(CodeGenFunction &CGF, saved_type value) {
-    return static_cast<T>(SavedValueInCondImpl::restore(CGF, value));
+    return static_cast<T*>(DominatingLLVMValue::restore(CGF, value));
+  }
+};
+
+/// A specialization of DominatingValue for RValue.
+template <> struct DominatingValue<RValue> {
+  typedef RValue type;
+  class saved_type {
+    enum Kind { ScalarLiteral, ScalarAddress, AggregateLiteral,
+                AggregateAddress, ComplexAddress };
+
+    llvm::Value *Value;
+    Kind K;
+    saved_type(llvm::Value *v, Kind k) : Value(v), K(k) {}
+
+  public:
+    static bool needsSaving(RValue value);
+    static saved_type save(CodeGenFunction &CGF, RValue value);
+    RValue restore(CodeGenFunction &CGF);
+
+    // implementations in CGExprCXX.cpp
+  };
+
+  static bool needsSaving(type value) {
+    return saved_type::needsSaving(value);
+  }
+  static saved_type save(CodeGenFunction &CGF, type value) {
+    return saved_type::save(CGF, value);
+  }
+  static type restore(CodeGenFunction &CGF, saved_type value) {
+    return value.restore(CGF);
   }
 };