From e02cb164b186edacb700f4b67d8f9e713b63d8de Mon Sep 17 00:00:00 2001
From: Chris Lattner <sabre@nondot.org>
Date: Wed, 27 Jun 2001 23:27:42 +0000
Subject: [PATCH] Add a new slew of functions to allow dynamic_cast<> like
 operation for upcasting Value's to their subclasses.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/llvm/Value.h | 60 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 59 insertions(+), 1 deletion(-)

diff --git a/include/llvm/Value.h b/include/llvm/Value.h
index b334d47e6e0..43373321c70 100644
--- a/include/llvm/Value.h
+++ b/include/llvm/Value.h
@@ -13,6 +13,12 @@
 
 class User;
 class Type;
+class ConstPoolVal;
+class MethodArgument;
+class Instruction;
+class BasicBlock;
+class Method;
+class Module;
 template<class ValueSubclass, class ItemParentType> class ValueHolder;
 
 //===----------------------------------------------------------------------===//
@@ -46,12 +52,64 @@ public:
   virtual ~Value();
 
   inline const Type *getType() const { return Ty; }
-  inline ValueTy getValueType() const { return VTy; }
 
+  // All values can potentially be named...
   inline bool hasName() const { return Name != ""; }
   inline const string &getName() const { return Name; }
   virtual void setName(const string &name) { Name = name; }
 
+  // Methods for determining the subtype of this Value.  The getValueType()
+  // method returns the type of the value directly.  The cast*() methods are
+  // equilivent to using dynamic_cast<>... if the cast is successful, this is
+  // returned, otherwise you get a null pointer, allowing expressions like this:
+  //
+  // if (Instruction *I = Val->castInstruction()) { ... }
+  //
+  // This section also defines a family of isType, isConstant, isMethodArgument,
+  // etc functions...
+  //
+  // The family of functions Val->cast<type>Asserting() is used in the same
+  // way as the Val->cast<type>() instructions, but they assert the expected
+  // type instead of checking it at runtime.
+  //
+  inline ValueTy getValueType() const { return VTy; }
+
+  // Use a macro to define the functions, otherwise these definitions are just
+  // really long and ugly.
+#define CAST_FN(NAME, CLASS)                                              \
+  inline bool is##NAME() const { return VTy == NAME##Val; }               \
+  inline const CLASS *cast##NAME() const { /*const version */             \
+    return is##NAME() ? (const CLASS*)this : 0;                           \
+  }                                                                       \
+  inline CLASS *cast##NAME() {         /* nonconst version */             \
+    return is##NAME() ? (CLASS*)this : 0;                                 \
+  }                                                                       \
+  inline const CLASS *cast##NAME##Asserting() const { /*const version */  \
+    assert(is##NAME() && "Expected Value Type: " #NAME);                  \
+    return (const CLASS*)this;                                            \
+  }                                                                       \
+  inline CLASS *cast##NAME##Asserting() {         /* nonconst version */  \
+    assert(is##NAME() && "Expected Value Type: " #NAME);                  \
+    return (CLASS*)this;                                                  \
+  }                                                                       \
+
+  CAST_FN(Constant      ,       ConstPoolVal  )
+  CAST_FN(MethodArgument,       MethodArgument)
+  CAST_FN(Instruction   ,       Instruction   )
+  CAST_FN(BasicBlock    ,       BasicBlock    )
+  CAST_FN(Method        ,       Method        )
+  CAST_FN(Module        ,       Module        )
+#undef CAST_FN
+
+  // Type value is special, because there is no nonconst version of functions!
+  inline bool isType() const { return VTy == TypeVal; }
+  inline const Type *castType() const {
+    return (VTy == TypeVal) ? (const Type*)this : 0;
+  }
+  inline const Type *castTypeAsserting() const {
+    assert(isType() && "Expected Value Type: Type");
+    return (const Type*)this;
+  }
 
   // replaceAllUsesWith - Go through the uses list for this definition and make
   // each use point to "D" instead of "this".  After this completes, 'this's