From e02cb164b186edacb700f4b67d8f9e713b63d8de Mon Sep 17 00:00:00 2001 From: Chris Lattner 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 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->castAsserting() is used in the same + // way as the Val->cast() 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 -- 2.34.1