toolkit/crashreporter/breakpad-patches/08-dwarf2reader-dynamic-cast.patch
author J. Ryan Stinnett <jryans@gmail.com>
Fri, 23 Oct 2015 02:43:09 -0500
changeset 302911 7060ded3194d6d0b17949edc3e76d93e013497aa
parent 124140 e0d9902b2bbfe9829cdd888b58f6fa7d4e0e1507
child 326148 211a4c710fb6af2cad10102c4cabc7cb525998b8
permissions -rw-r--r--
Bug 1217687 - Revert back to including /devtools via toolkit. r=glandium

# HG changeset patch
# User Ted Mielczarek <ted@mielczarek.org>
# Date 1362600444 18000
# Node ID 0eb3c7ba8a38a269ab975eff3f95a1a5d5d937b9
# Parent  6b68e82037b8322fb392cea369d517aeeaaee9d3
Stop using dynamic_cast in dwarf2reader
Patch by Julian Seward <jseward@acm.org>, R=ted

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