michael@0: # HG changeset patch michael@0: # User Ted Mielczarek michael@0: # Date 1362600444 18000 michael@0: # Node ID 0eb3c7ba8a38a269ab975eff3f95a1a5d5d937b9 michael@0: # Parent 6b68e82037b8322fb392cea369d517aeeaaee9d3 michael@0: Stop using dynamic_cast in dwarf2reader michael@0: Patch by Julian Seward , R=ted michael@0: michael@0: diff --git a/src/common/dwarf/dwarf2reader.cc b/src/common/dwarf/dwarf2reader.cc michael@0: --- a/src/common/dwarf/dwarf2reader.cc michael@0: +++ b/src/common/dwarf/dwarf2reader.cc michael@0: @@ -887,68 +887,80 @@ michael@0: michael@0: // If this is a base+offset rule, change its base register to REG. michael@0: // Otherwise, do nothing. (Ugly, but required for DW_CFA_def_cfa_register.) michael@0: virtual void SetBaseRegister(unsigned reg) { } michael@0: michael@0: // If this is a base+offset rule, change its offset to OFFSET. Otherwise, michael@0: // do nothing. (Ugly, but required for DW_CFA_def_cfa_offset.) michael@0: virtual void SetOffset(long long offset) { } michael@0: + michael@0: + // A RTTI workaround, to make it possible to implement equality michael@0: + // comparisons on classes derived from this one. michael@0: + enum CFIRTag { michael@0: + CFIR_UNDEFINED_RULE, michael@0: + CFIR_SAME_VALUE_RULE, michael@0: + CFIR_OFFSET_RULE, michael@0: + CFIR_VAL_OFFSET_RULE, michael@0: + CFIR_REGISTER_RULE, michael@0: + CFIR_EXPRESSION_RULE, michael@0: + CFIR_VAL_EXPRESSION_RULE michael@0: + }; michael@0: + michael@0: + // Produce the tag that identifies the child class of this object. michael@0: + virtual CFIRTag getTag() const = 0; michael@0: }; michael@0: michael@0: // Rule: the value the register had in the caller cannot be recovered. michael@0: class CallFrameInfo::UndefinedRule: public CallFrameInfo::Rule { michael@0: public: michael@0: UndefinedRule() { } michael@0: ~UndefinedRule() { } michael@0: + CFIRTag getTag() const { return CFIR_UNDEFINED_RULE; } michael@0: bool Handle(Handler *handler, uint64 address, int reg) const { michael@0: return handler->UndefinedRule(address, reg); michael@0: } michael@0: bool operator==(const Rule &rhs) const { michael@0: - // dynamic_cast is allowed by the Google C++ Style Guide, if the use has michael@0: - // been carefully considered; cheap RTTI-like workarounds are forbidden. michael@0: - const UndefinedRule *our_rhs = dynamic_cast(&rhs); michael@0: - return (our_rhs != NULL); michael@0: + if (rhs.getTag() != CFIR_UNDEFINED_RULE) return false; michael@0: + return true; michael@0: } michael@0: Rule *Copy() const { return new UndefinedRule(*this); } michael@0: }; michael@0: michael@0: // Rule: the register's value is the same as that it had in the caller. michael@0: class CallFrameInfo::SameValueRule: public CallFrameInfo::Rule { michael@0: public: michael@0: SameValueRule() { } michael@0: ~SameValueRule() { } michael@0: + CFIRTag getTag() const { return CFIR_SAME_VALUE_RULE; } michael@0: bool Handle(Handler *handler, uint64 address, int reg) const { michael@0: return handler->SameValueRule(address, reg); michael@0: } michael@0: bool operator==(const Rule &rhs) const { michael@0: - // dynamic_cast is allowed by the Google C++ Style Guide, if the use has michael@0: - // been carefully considered; cheap RTTI-like workarounds are forbidden. michael@0: - const SameValueRule *our_rhs = dynamic_cast(&rhs); michael@0: - return (our_rhs != NULL); michael@0: + if (rhs.getTag() != CFIR_SAME_VALUE_RULE) return false; michael@0: + return true; michael@0: } michael@0: Rule *Copy() const { return new SameValueRule(*this); } michael@0: }; michael@0: michael@0: // Rule: the register is saved at OFFSET from BASE_REGISTER. BASE_REGISTER michael@0: // may be CallFrameInfo::Handler::kCFARegister. michael@0: class CallFrameInfo::OffsetRule: public CallFrameInfo::Rule { michael@0: public: michael@0: OffsetRule(int base_register, long offset) michael@0: : base_register_(base_register), offset_(offset) { } michael@0: ~OffsetRule() { } michael@0: + CFIRTag getTag() const { return CFIR_OFFSET_RULE; } michael@0: bool Handle(Handler *handler, uint64 address, int reg) const { michael@0: return handler->OffsetRule(address, reg, base_register_, offset_); michael@0: } michael@0: bool operator==(const Rule &rhs) const { michael@0: - // dynamic_cast is allowed by the Google C++ Style Guide, if the use has michael@0: - // been carefully considered; cheap RTTI-like workarounds are forbidden. michael@0: - const OffsetRule *our_rhs = dynamic_cast(&rhs); michael@0: - return (our_rhs && michael@0: - base_register_ == our_rhs->base_register_ && michael@0: + if (rhs.getTag() != CFIR_OFFSET_RULE) return false; michael@0: + const OffsetRule *our_rhs = static_cast(&rhs); michael@0: + return (base_register_ == our_rhs->base_register_ && michael@0: offset_ == our_rhs->offset_); michael@0: } michael@0: Rule *Copy() const { return new OffsetRule(*this); } michael@0: // We don't actually need SetBaseRegister or SetOffset here, since they michael@0: // are only ever applied to CFA rules, for DW_CFA_def_cfa_offset, and it michael@0: // doesn't make sense to use OffsetRule for computing the CFA: it michael@0: // computes the address at which a register is saved, not a value. michael@0: private: michael@0: @@ -959,90 +971,89 @@ michael@0: // Rule: the value the register had in the caller is the value of michael@0: // BASE_REGISTER plus offset. BASE_REGISTER may be michael@0: // CallFrameInfo::Handler::kCFARegister. michael@0: class CallFrameInfo::ValOffsetRule: public CallFrameInfo::Rule { michael@0: public: michael@0: ValOffsetRule(int base_register, long offset) michael@0: : base_register_(base_register), offset_(offset) { } michael@0: ~ValOffsetRule() { } michael@0: + CFIRTag getTag() const { return CFIR_VAL_OFFSET_RULE; } michael@0: bool Handle(Handler *handler, uint64 address, int reg) const { michael@0: return handler->ValOffsetRule(address, reg, base_register_, offset_); michael@0: } michael@0: bool operator==(const Rule &rhs) const { michael@0: - // dynamic_cast is allowed by the Google C++ Style Guide, if the use has michael@0: - // been carefully considered; cheap RTTI-like workarounds are forbidden. michael@0: - const ValOffsetRule *our_rhs = dynamic_cast(&rhs); michael@0: - return (our_rhs && michael@0: - base_register_ == our_rhs->base_register_ && michael@0: + if (rhs.getTag() != CFIR_VAL_OFFSET_RULE) return false; michael@0: + const ValOffsetRule *our_rhs = static_cast(&rhs); michael@0: + return (base_register_ == our_rhs->base_register_ && michael@0: offset_ == our_rhs->offset_); michael@0: } michael@0: Rule *Copy() const { return new ValOffsetRule(*this); } michael@0: void SetBaseRegister(unsigned reg) { base_register_ = reg; } michael@0: void SetOffset(long long offset) { offset_ = offset; } michael@0: private: michael@0: int base_register_; michael@0: long offset_; michael@0: }; michael@0: michael@0: // Rule: the register has been saved in another register REGISTER_NUMBER_. michael@0: class CallFrameInfo::RegisterRule: public CallFrameInfo::Rule { michael@0: public: michael@0: explicit RegisterRule(int register_number) michael@0: : register_number_(register_number) { } michael@0: ~RegisterRule() { } michael@0: + CFIRTag getTag() const { return CFIR_REGISTER_RULE; } michael@0: bool Handle(Handler *handler, uint64 address, int reg) const { michael@0: return handler->RegisterRule(address, reg, register_number_); michael@0: } michael@0: bool operator==(const Rule &rhs) const { michael@0: - // dynamic_cast is allowed by the Google C++ Style Guide, if the use has michael@0: - // been carefully considered; cheap RTTI-like workarounds are forbidden. michael@0: - const RegisterRule *our_rhs = dynamic_cast(&rhs); michael@0: - return (our_rhs && register_number_ == our_rhs->register_number_); michael@0: + if (rhs.getTag() != CFIR_REGISTER_RULE) return false; michael@0: + const RegisterRule *our_rhs = static_cast(&rhs); michael@0: + return (register_number_ == our_rhs->register_number_); michael@0: } michael@0: Rule *Copy() const { return new RegisterRule(*this); } michael@0: private: michael@0: int register_number_; michael@0: }; michael@0: michael@0: // Rule: EXPRESSION evaluates to the address at which the register is saved. michael@0: class CallFrameInfo::ExpressionRule: public CallFrameInfo::Rule { michael@0: public: michael@0: explicit ExpressionRule(const string &expression) michael@0: : expression_(expression) { } michael@0: ~ExpressionRule() { } michael@0: + CFIRTag getTag() const { return CFIR_EXPRESSION_RULE; } michael@0: bool Handle(Handler *handler, uint64 address, int reg) const { michael@0: return handler->ExpressionRule(address, reg, expression_); michael@0: } michael@0: bool operator==(const Rule &rhs) const { michael@0: - // dynamic_cast is allowed by the Google C++ Style Guide, if the use has michael@0: - // been carefully considered; cheap RTTI-like workarounds are forbidden. michael@0: - const ExpressionRule *our_rhs = dynamic_cast(&rhs); michael@0: - return (our_rhs && expression_ == our_rhs->expression_); michael@0: + if (rhs.getTag() != CFIR_EXPRESSION_RULE) return false; michael@0: + const ExpressionRule *our_rhs = static_cast(&rhs); michael@0: + return (expression_ == our_rhs->expression_); michael@0: } michael@0: Rule *Copy() const { return new ExpressionRule(*this); } michael@0: private: michael@0: string expression_; michael@0: }; michael@0: michael@0: // Rule: EXPRESSION evaluates to the address at which the register is saved. michael@0: class CallFrameInfo::ValExpressionRule: public CallFrameInfo::Rule { michael@0: public: michael@0: explicit ValExpressionRule(const string &expression) michael@0: : expression_(expression) { } michael@0: ~ValExpressionRule() { } michael@0: + CFIRTag getTag() const { return CFIR_VAL_EXPRESSION_RULE; } michael@0: bool Handle(Handler *handler, uint64 address, int reg) const { michael@0: return handler->ValExpressionRule(address, reg, expression_); michael@0: } michael@0: bool operator==(const Rule &rhs) const { michael@0: - // dynamic_cast is allowed by the Google C++ Style Guide, if the use has michael@0: - // been carefully considered; cheap RTTI-like workarounds are forbidden. michael@0: + if (rhs.getTag() != CFIR_VAL_EXPRESSION_RULE) return false; michael@0: const ValExpressionRule *our_rhs = michael@0: - dynamic_cast(&rhs); michael@0: - return (our_rhs && expression_ == our_rhs->expression_); michael@0: + static_cast(&rhs); michael@0: + return (expression_ == our_rhs->expression_); michael@0: } michael@0: Rule *Copy() const { return new ValExpressionRule(*this); } michael@0: private: michael@0: string expression_; michael@0: }; michael@0: michael@0: // A map from register numbers to rules. michael@0: class CallFrameInfo::RuleMap {