Fix powerpc-power8.exp test with new mnemonics
[deliverable/binutils-gdb.git] / gdb / expop.h
index cbd4d6267dad5ee467df31fedd0c18be64162347..b8e28b5a59025cf3c87d6bbf6c8da587230a8ca7 100644 (file)
@@ -40,6 +40,10 @@ extern void gen_expr_structop (struct expression *exp,
                               expr::operation *lhs,
                               const char *name,
                               struct agent_expr *ax, struct axs_value *value);
+extern void gen_expr_unop (struct expression *exp,
+                          enum exp_opcode op,
+                          expr::operation *lhs,
+                          struct agent_expr *ax, struct axs_value *value);
 
 extern struct value *eval_op_scope (struct type *expect_type,
                                    struct expression *exp,
@@ -49,8 +53,7 @@ extern struct value *eval_op_var_msym_value (struct type *expect_type,
                                             struct expression *exp,
                                             enum noside noside,
                                             bool outermost_p,
-                                            minimal_symbol *msymbol,
-                                            struct objfile *objfile);
+                                            bound_minimal_symbol msymbol);
 extern struct value *eval_op_var_entry_value (struct type *expect_type,
                                              struct expression *exp,
                                              enum noside noside, symbol *sym);
@@ -84,10 +87,127 @@ extern struct value *eval_op_member (struct type *expect_type,
                                     struct expression *exp,
                                     enum noside noside,
                                     struct value *arg1, struct value *arg2);
+extern struct value *eval_op_concat (struct type *expect_type,
+                                    struct expression *exp,
+                                    enum noside noside,
+                                    struct value *arg1, struct value *arg2);
+extern struct value *eval_op_add (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside,
+                                 struct value *arg1, struct value *arg2);
+extern struct value *eval_op_sub (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside,
+                                 struct value *arg1, struct value *arg2);
+extern struct value *eval_op_binary (struct type *expect_type,
+                                    struct expression *exp,
+                                    enum noside noside, enum exp_opcode op,
+                                    struct value *arg1, struct value *arg2);
+extern struct value *eval_op_subscript (struct type *expect_type,
+                                       struct expression *exp,
+                                       enum noside noside, enum exp_opcode op,
+                                       struct value *arg1,
+                                       struct value *arg2);
+extern struct value *eval_op_equal (struct type *expect_type,
+                                   struct expression *exp,
+                                   enum noside noside, enum exp_opcode op,
+                                   struct value *arg1,
+                                   struct value *arg2);
+extern struct value *eval_op_notequal (struct type *expect_type,
+                                      struct expression *exp,
+                                      enum noside noside, enum exp_opcode op,
+                                      struct value *arg1,
+                                      struct value *arg2);
+extern struct value *eval_op_less (struct type *expect_type,
+                                  struct expression *exp,
+                                  enum noside noside, enum exp_opcode op,
+                                  struct value *arg1,
+                                  struct value *arg2);
+extern struct value *eval_op_gtr (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside, enum exp_opcode op,
+                                 struct value *arg1,
+                                 struct value *arg2);
+extern struct value *eval_op_geq (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside, enum exp_opcode op,
+                                 struct value *arg1,
+                                 struct value *arg2);
+extern struct value *eval_op_leq (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside, enum exp_opcode op,
+                                 struct value *arg1,
+                                 struct value *arg2);
+extern struct value *eval_op_repeat (struct type *expect_type,
+                                    struct expression *exp,
+                                    enum noside noside, enum exp_opcode op,
+                                    struct value *arg1,
+                                    struct value *arg2);
+extern struct value *eval_op_plus (struct type *expect_type,
+                                  struct expression *exp,
+                                  enum noside noside, enum exp_opcode op,
+                                  struct value *arg1);
+extern struct value *eval_op_neg (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside, enum exp_opcode op,
+                                 struct value *arg1);
+extern struct value *eval_op_complement (struct type *expect_type,
+                                        struct expression *exp,
+                                        enum noside noside,
+                                        enum exp_opcode op,
+                                        struct value *arg1);
+extern struct value *eval_op_lognot (struct type *expect_type,
+                                    struct expression *exp,
+                                    enum noside noside,
+                                    enum exp_opcode op,
+                                    struct value *arg1);
+extern struct value *eval_op_preinc (struct type *expect_type,
+                                    struct expression *exp,
+                                    enum noside noside,
+                                    enum exp_opcode op,
+                                    struct value *arg1);
+extern struct value *eval_op_predec (struct type *expect_type,
+                                    struct expression *exp,
+                                    enum noside noside,
+                                    enum exp_opcode op,
+                                    struct value *arg1);
+extern struct value *eval_op_postinc (struct type *expect_type,
+                                     struct expression *exp,
+                                     enum noside noside,
+                                     enum exp_opcode op,
+                                     struct value *arg1);
+extern struct value *eval_op_postdec (struct type *expect_type,
+                                     struct expression *exp,
+                                     enum noside noside,
+                                     enum exp_opcode op,
+                                     struct value *arg1);
+extern struct value *eval_op_ind (struct type *expect_type,
+                                 struct expression *exp,
+                                 enum noside noside,
+                                 struct value *arg1);
+extern struct value *eval_op_type (struct type *expect_type,
+                                  struct expression *exp,
+                                  enum noside noside, struct type *type);
+extern struct value *eval_op_alignof (struct type *expect_type,
+                                     struct expression *exp,
+                                     enum noside noside,
+                                     struct value *arg1);
+extern struct value *eval_op_memval (struct type *expect_type,
+                                    struct expression *exp,
+                                    enum noside noside,
+                                    struct value *arg1, struct type *type);
+extern struct value *eval_binop_assign_modify (struct type *expect_type,
+                                              struct expression *exp,
+                                              enum noside noside,
+                                              enum exp_opcode op,
+                                              struct value *arg1,
+                                              struct value *arg2);
 
 namespace expr
 {
 
+class ada_component;
+
 /* The check_objfile overloads are used to check whether a particular
    component of some operation references an objfile.  The passed-in
    objfile will never be a debug objfile.  */
@@ -101,7 +221,7 @@ check_objfile (struct objfile *exp_objfile, struct objfile *objfile)
   return exp_objfile == objfile;
 }
 
-static inline bool 
+static inline bool
 check_objfile (struct type *type, struct objfile *objfile)
 {
   struct objfile *ty_objfile = type->objfile_owner ();
@@ -110,24 +230,29 @@ check_objfile (struct type *type, struct objfile *objfile)
   return false;
 }
 
-static inline bool 
+static inline bool
 check_objfile (struct symbol *sym, struct objfile *objfile)
 {
   return check_objfile (symbol_objfile (sym), objfile);
 }
 
-static inline bool 
+static inline bool
 check_objfile (const struct block *block, struct objfile *objfile)
 {
   return check_objfile (block_objfile (block), objfile);
 }
 
 static inline bool
-check_objfile (minimal_symbol *minsym, struct objfile *objfile)
+check_objfile (const block_symbol &sym, struct objfile *objfile)
 {
-  /* This may seem strange but minsyms are only used with an objfile
-     as well.  */
-  return false;
+  return (check_objfile (sym.symbol, objfile)
+         || check_objfile (sym.block, objfile));
+}
+
+static inline bool
+check_objfile (bound_minimal_symbol minsym, struct objfile *objfile)
+{
+  return check_objfile (minsym.objfile, objfile);
 }
 
 static inline bool
@@ -142,7 +267,7 @@ check_objfile (const std::string &str, struct objfile *objfile)
   return false;
 }
 
-static inline bool 
+static inline bool
 check_objfile (const operation_up &op, struct objfile *objfile)
 {
   return op->uses_objfile (objfile);
@@ -168,7 +293,7 @@ check_objfile (enum_flags<T> val, struct objfile *objfile)
 }
 
 template<typename T>
-static inline bool 
+static inline bool
 check_objfile (const std::vector<T> &collection, struct objfile *objfile)
 {
   for (const auto &item : collection)
@@ -180,13 +305,16 @@ check_objfile (const std::vector<T> &collection, struct objfile *objfile)
 }
 
 template<typename S, typename T>
-static inline bool 
+static inline bool
 check_objfile (const std::pair<S, T> &item, struct objfile *objfile)
 {
   return (check_objfile (item.first, objfile)
          || check_objfile (item.second, objfile));
 }
 
+extern bool check_objfile (const std::unique_ptr<ada_component> &comp,
+                          struct objfile *objfile);
+
 static inline void
 dump_for_expression (struct ui_file *stream, int depth,
                     const operation_up &op)
@@ -207,7 +335,9 @@ extern void dump_for_expression (struct ui_file *stream, int depth,
 extern void dump_for_expression (struct ui_file *stream, int depth,
                                 symbol *sym);
 extern void dump_for_expression (struct ui_file *stream, int depth,
-                                minimal_symbol *msym);
+                                const block_symbol &sym);
+extern void dump_for_expression (struct ui_file *stream, int depth,
+                                bound_minimal_symbol msym);
 extern void dump_for_expression (struct ui_file *stream, int depth,
                                 const block *bl);
 extern void dump_for_expression (struct ui_file *stream, int depth,
@@ -217,7 +347,7 @@ extern void dump_for_expression (struct ui_file *stream, int depth,
 extern void dump_for_expression (struct ui_file *stream, int depth,
                                 enum range_flag flags);
 extern void dump_for_expression (struct ui_file *stream, int depth,
-                                objfile *objf);
+                                const std::unique_ptr<ada_component> &comp);
 
 template<typename T>
 void
@@ -320,7 +450,7 @@ check_constant (const operation_up &item)
 }
 
 static inline bool
-check_constant (struct minimal_symbol *msym)
+check_constant (bound_minimal_symbol msym)
 {
   return false;
 }
@@ -343,12 +473,6 @@ check_constant (const std::string &str)
   return true;
 }
 
-static inline bool
-check_constant (struct objfile *objfile)
-{
-  return true;
-}
-
 static inline bool
 check_constant (ULONGEST cst)
 {
@@ -365,6 +489,14 @@ check_constant (struct symbol *sym)
          || sc == LOC_LABEL);
 }
 
+static inline bool
+check_constant (const block_symbol &sym)
+{
+  /* We know the block is constant, so we only need to check the
+     symbol.  */
+  return check_constant (sym.symbol);
+}
+
 template<typename T>
 static inline bool
 check_constant (const std::vector<T> &collection)
@@ -478,6 +610,11 @@ public:
   value *evaluate_for_address (struct expression *exp,
                               enum noside noside) override;
 
+  value *evaluate_funcall (struct type *expect_type,
+                          struct expression *exp,
+                          enum noside noside,
+                          const std::vector<operation_up> &args) override;
+
   enum exp_opcode opcode () const override
   { return OP_SCOPE; }
 
@@ -490,6 +627,54 @@ protected:
     override;
 };
 
+/* Compute the value of a variable.  */
+class var_value_operation
+  : public maybe_constant_operation<block_symbol>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  value *evaluate_with_coercion (struct expression *exp,
+                                enum noside noside) override;
+
+  value *evaluate_for_sizeof (struct expression *exp, enum noside noside)
+    override;
+
+  value *evaluate_for_cast (struct type *expect_type,
+                           struct expression *exp,
+                           enum noside noside) override;
+
+  value *evaluate_for_address (struct expression *exp, enum noside noside)
+    override;
+
+  value *evaluate_funcall (struct type *expect_type,
+                          struct expression *exp,
+                          enum noside noside,
+                          const std::vector<operation_up> &args) override;
+
+  enum exp_opcode opcode () const override
+  { return OP_VAR_VALUE; }
+
+  /* Return the symbol referenced by this object.  */
+  symbol *get_symbol () const
+  {
+    return std::get<0> (m_storage).symbol;
+  }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
 class long_const_operation
   : public tuple_holding_operation<struct type *, LONGEST>
 {
@@ -521,7 +706,7 @@ protected:
 };
 
 class var_msym_value_operation
-  : public maybe_constant_operation<minimal_symbol *, struct objfile *>
+  : public maybe_constant_operation<bound_minimal_symbol>
 {
 public:
 
@@ -532,8 +717,7 @@ public:
                   enum noside noside) override
   {
     return eval_op_var_msym_value (expect_type, exp, noside, m_outermost,
-                                  std::get<0> (m_storage),
-                                  std::get<1> (m_storage));
+                                  std::get<0> (m_storage));
   }
 
   value *evaluate_for_sizeof (struct expression *exp, enum noside noside)
@@ -546,6 +730,15 @@ public:
                            struct expression *exp,
                            enum noside noside) override;
 
+  value *evaluate_funcall (struct type *expect_type,
+                          struct expression *exp,
+                          enum noside noside,
+                          const std::vector<operation_up> &args) override
+  {
+    const char *name = std::get<0> (m_storage).minsym->print_name ();
+    return operation::evaluate_funcall (expect_type, exp, noside, name, args);
+  }
+
   enum exp_opcode opcode () const override
   { return OP_VAR_MSYM_VALUE; }
 
@@ -641,6 +834,12 @@ public:
   enum exp_opcode opcode () const override
   { return OP_REGISTER; }
 
+  /* Return the name of the register.  */
+  const char *get_name () const
+  {
+    return std::get<0> (m_storage).c_str ();
+  }
+
 protected:
 
   void do_generate_ax (struct expression *exp,
@@ -818,6 +1017,11 @@ public:
                                              EVAL_AVOID_SIDE_EFFECTS);
   }
 
+  value *evaluate_funcall (struct type *expect_type,
+                          struct expression *exp,
+                          enum noside noside,
+                          const std::vector<operation_up> &args) override;
+
 protected:
 
   using tuple_holding_operation::tuple_holding_operation;
@@ -891,13 +1095,26 @@ protected:
   }
 };
 
-class structop_member_operation
+class structop_member_base
   : public tuple_holding_operation<operation_up, operation_up>
 {
 public:
 
   using tuple_holding_operation::tuple_holding_operation;
 
+  value *evaluate_funcall (struct type *expect_type,
+                          struct expression *exp,
+                          enum noside noside,
+                          const std::vector<operation_up> &args) override;
+};
+
+class structop_member_operation
+  : public structop_member_base
+{
+public:
+
+  using structop_member_base::structop_member_base;
+
   value *evaluate (struct type *expect_type,
                   struct expression *exp,
                   enum noside noside) override
@@ -914,11 +1131,11 @@ public:
 };
 
 class structop_mptr_operation
-  : public tuple_holding_operation<operation_up, operation_up>
+  : public structop_member_base
 {
 public:
 
-  using tuple_holding_operation::tuple_holding_operation;
+  using structop_member_base::structop_member_base;
 
   value *evaluate (struct type *expect_type,
                   struct expression *exp,
@@ -935,6 +1152,1037 @@ public:
   { return STRUCTOP_MPTR; }
 };
 
+class concat_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *lhs
+      = std::get<0> (m_storage)->evaluate_with_coercion (exp, noside);
+    value *rhs
+      = std::get<1> (m_storage)->evaluate_with_coercion (exp, noside);
+    return eval_op_concat (expect_type, exp, noside, lhs, rhs);
+  }
+
+  enum exp_opcode opcode () const override
+  { return BINOP_CONCAT; }
+};
+
+class add_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *lhs
+      = std::get<0> (m_storage)->evaluate_with_coercion (exp, noside);
+    value *rhs
+      = std::get<1> (m_storage)->evaluate_with_coercion (exp, noside);
+    return eval_op_add (expect_type, exp, noside, lhs, rhs);
+  }
+
+  enum exp_opcode opcode () const override
+  { return BINOP_ADD; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override
+  {
+    gen_expr_binop (exp, BINOP_ADD,
+                   std::get<0> (this->m_storage).get (),
+                   std::get<1> (this->m_storage).get (),
+                   ax, value);
+  }
+};
+
+class sub_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *lhs
+      = std::get<0> (m_storage)->evaluate_with_coercion (exp, noside);
+    value *rhs
+      = std::get<1> (m_storage)->evaluate_with_coercion (exp, noside);
+    return eval_op_sub (expect_type, exp, noside, lhs, rhs);
+  }
+
+  enum exp_opcode opcode () const override
+  { return BINOP_SUB; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override
+  {
+    gen_expr_binop (exp, BINOP_SUB,
+                   std::get<0> (this->m_storage).get (),
+                   std::get<1> (this->m_storage).get (),
+                   ax, value);
+  }
+};
+
+typedef struct value *binary_ftype (struct type *expect_type,
+                                   struct expression *exp,
+                                   enum noside noside, enum exp_opcode op,
+                                   struct value *arg1, struct value *arg2);
+
+template<enum exp_opcode OP, binary_ftype FUNC>
+class binop_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *lhs
+      = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+    value *rhs
+      = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+    return FUNC (expect_type, exp, noside, OP, lhs, rhs);
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP; }
+};
+
+template<enum exp_opcode OP, binary_ftype FUNC>
+class usual_ax_binop_operation
+  : public binop_operation<OP, FUNC>
+{
+public:
+
+  using binop_operation<OP, FUNC>::binop_operation;
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override
+  {
+    gen_expr_binop (exp, OP,
+                   std::get<0> (this->m_storage).get (),
+                   std::get<1> (this->m_storage).get (),
+                   ax, value);
+  }
+};
+
+using exp_operation = binop_operation<BINOP_EXP, eval_op_binary>;
+using intdiv_operation = binop_operation<BINOP_INTDIV, eval_op_binary>;
+using mod_operation = binop_operation<BINOP_MOD, eval_op_binary>;
+
+using mul_operation = usual_ax_binop_operation<BINOP_MUL, eval_op_binary>;
+using div_operation = usual_ax_binop_operation<BINOP_DIV, eval_op_binary>;
+using rem_operation = usual_ax_binop_operation<BINOP_REM, eval_op_binary>;
+using lsh_operation = usual_ax_binop_operation<BINOP_LSH, eval_op_binary>;
+using rsh_operation = usual_ax_binop_operation<BINOP_RSH, eval_op_binary>;
+using bitwise_and_operation
+     = usual_ax_binop_operation<BINOP_BITWISE_AND, eval_op_binary>;
+using bitwise_ior_operation
+     = usual_ax_binop_operation<BINOP_BITWISE_IOR, eval_op_binary>;
+using bitwise_xor_operation
+     = usual_ax_binop_operation<BINOP_BITWISE_XOR, eval_op_binary>;
+
+class subscript_operation
+  : public usual_ax_binop_operation<BINOP_SUBSCRIPT, eval_op_subscript>
+{
+public:
+  using usual_ax_binop_operation<BINOP_SUBSCRIPT,
+                                eval_op_subscript>::usual_ax_binop_operation;
+
+  value *evaluate_for_sizeof (struct expression *exp,
+                             enum noside noside) override;
+};
+
+/* Implementation of comparison operations.  */
+template<enum exp_opcode OP, binary_ftype FUNC>
+class comparison_operation
+  : public usual_ax_binop_operation<OP, FUNC>
+{
+public:
+
+  using usual_ax_binop_operation<OP, FUNC>::usual_ax_binop_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *lhs
+      = std::get<0> (this->m_storage)->evaluate (nullptr, exp, noside);
+    value *rhs
+      = std::get<1> (this->m_storage)->evaluate (value_type (lhs), exp,
+                                                noside);
+    return FUNC (expect_type, exp, noside, OP, lhs, rhs);
+  }
+};
+
+class equal_operation
+  : public comparison_operation<BINOP_EQUAL, eval_op_equal>
+{
+public:
+
+  using comparison_operation::comparison_operation;
+
+  operation *get_lhs () const
+  {
+    return std::get<0> (m_storage).get ();
+  }
+
+  operation *get_rhs () const
+  {
+    return std::get<1> (m_storage).get ();
+  }
+};
+
+using notequal_operation
+     = comparison_operation<BINOP_NOTEQUAL, eval_op_notequal>;
+using less_operation = comparison_operation<BINOP_LESS, eval_op_less>;
+using gtr_operation = comparison_operation<BINOP_GTR, eval_op_gtr>;
+using geq_operation = comparison_operation<BINOP_GEQ, eval_op_geq>;
+using leq_operation = comparison_operation<BINOP_LEQ, eval_op_leq>;
+
+/* Implement the GDB '@' repeat operator.  */
+class repeat_operation
+  : public binop_operation<BINOP_REPEAT, eval_op_repeat>
+{
+  using binop_operation<BINOP_REPEAT, eval_op_repeat>::binop_operation;
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* C-style comma operator.  */
+class comma_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    /* The left-hand-side is only evaluated for side effects, so don't
+       bother in other modes.  */
+    if (noside == EVAL_NORMAL)
+      std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+    return std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+  }
+
+  enum exp_opcode opcode () const override
+  { return BINOP_COMMA; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+typedef struct value *unary_ftype (struct type *expect_type,
+                                  struct expression *exp,
+                                  enum noside noside, enum exp_opcode op,
+                                  struct value *arg1);
+
+/* Base class for unary operations.  */
+template<enum exp_opcode OP, unary_ftype FUNC>
+class unop_operation
+  : public maybe_constant_operation<operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+    return FUNC (expect_type, exp, noside, OP, val);
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP; }
+};
+
+/* Unary operations that can also be turned into agent expressions in
+   the "usual" way.  */
+template<enum exp_opcode OP, unary_ftype FUNC>
+class usual_ax_unop_operation
+  : public unop_operation<OP, FUNC>
+{
+  using unop_operation<OP, FUNC>::unop_operation;
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override
+  {
+    gen_expr_unop (exp, OP,
+                  std::get<0> (this->m_storage).get (),
+                  ax, value);
+  }
+};
+
+using unary_plus_operation = usual_ax_unop_operation<UNOP_PLUS, eval_op_plus>;
+using unary_neg_operation = usual_ax_unop_operation<UNOP_NEG, eval_op_neg>;
+using unary_complement_operation
+     = usual_ax_unop_operation<UNOP_COMPLEMENT, eval_op_complement>;
+using unary_logical_not_operation
+     = usual_ax_unop_operation<UNOP_LOGICAL_NOT, eval_op_lognot>;
+
+/* Handle pre- and post- increment and -decrement.  */
+template<enum exp_opcode OP, unary_ftype FUNC>
+class unop_incr_operation
+  : public tuple_holding_operation<operation_up>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *val = std::get<0> (m_storage)->evaluate (expect_type, exp, noside);
+    return FUNC (expect_type, exp, noside, OP, val);
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP; }
+};
+
+using preinc_operation
+     = unop_incr_operation<UNOP_PREINCREMENT, eval_op_preinc>;
+using predec_operation
+     = unop_incr_operation<UNOP_PREDECREMENT, eval_op_predec>;
+using postinc_operation
+     = unop_incr_operation<UNOP_POSTINCREMENT, eval_op_postinc>;
+using postdec_operation
+     = unop_incr_operation<UNOP_POSTDECREMENT, eval_op_postdec>;
+
+/* Base class for implementations of UNOP_IND.  */
+class unop_ind_base_operation
+  : public tuple_holding_operation<operation_up>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    if (expect_type != nullptr && expect_type->code () == TYPE_CODE_PTR)
+      expect_type = TYPE_TARGET_TYPE (check_typedef (expect_type));
+    value *val = std::get<0> (m_storage)->evaluate (expect_type, exp, noside);
+    return eval_op_ind (expect_type, exp, noside, val);
+  }
+
+  value *evaluate_for_address (struct expression *exp,
+                              enum noside noside) override;
+
+  value *evaluate_for_sizeof (struct expression *exp,
+                             enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return UNOP_IND; }
+};
+
+/* Ordinary UNOP_IND implementation.  */
+class unop_ind_operation
+  : public unop_ind_base_operation
+{
+public:
+
+  using unop_ind_base_operation::unop_ind_base_operation;
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override
+  {
+    gen_expr_unop (exp, UNOP_IND,
+                  std::get<0> (this->m_storage).get (),
+                  ax, value);
+  }
+};
+
+/* Implement OP_TYPE.  */
+class type_operation
+  : public tuple_holding_operation<struct type *>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    return eval_op_type (expect_type, exp, noside, std::get<0> (m_storage));
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP_TYPE; }
+
+  bool constant_p () const override
+  { return true; }
+};
+
+/* Implement the "typeof" operation.  */
+class typeof_operation
+  : public maybe_constant_operation<operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    if (noside == EVAL_AVOID_SIDE_EFFECTS)
+      return std::get<0> (m_storage)->evaluate (nullptr, exp,
+                                               EVAL_AVOID_SIDE_EFFECTS);
+    else
+      error (_("Attempt to use a type as an expression"));
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP_TYPEOF; }
+};
+
+/* Implement 'decltype'.  */
+class decltype_operation
+  : public maybe_constant_operation<operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    if (noside == EVAL_AVOID_SIDE_EFFECTS)
+      {
+       value *result
+         = std::get<0> (m_storage)->evaluate (nullptr, exp,
+                                              EVAL_AVOID_SIDE_EFFECTS);
+       enum exp_opcode sub_op = std::get<0> (m_storage)->opcode ();
+       if (sub_op == BINOP_SUBSCRIPT
+           || sub_op == STRUCTOP_MEMBER
+           || sub_op == STRUCTOP_MPTR
+           || sub_op == UNOP_IND
+           || sub_op == STRUCTOP_STRUCT
+           || sub_op == STRUCTOP_PTR
+           || sub_op == OP_SCOPE)
+         {
+           struct type *type = value_type (result);
+
+           if (!TYPE_IS_REFERENCE (type))
+             {
+               type = lookup_lvalue_reference_type (type);
+               result = allocate_value (type);
+             }
+         }
+
+       return result;
+      }
+    else
+      error (_("Attempt to use a type as an expression"));
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP_DECLTYPE; }
+};
+
+/* Implement 'typeid'.  */
+class typeid_operation
+  : public tuple_holding_operation<operation_up>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    enum exp_opcode sub_op = std::get<0> (m_storage)->opcode ();
+    enum noside sub_noside
+      = ((sub_op == OP_TYPE || sub_op == OP_DECLTYPE || sub_op == OP_TYPEOF)
+        ? EVAL_AVOID_SIDE_EFFECTS
+        : noside);
+
+    value *result = std::get<0> (m_storage)->evaluate (nullptr, exp,
+                                                      sub_noside);
+    if (noside != EVAL_NORMAL)
+      return allocate_value (cplus_typeid_type (exp->gdbarch));
+    return cplus_typeid (result);
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP_TYPEID; }
+};
+
+/* Implement the address-of operation.  */
+class unop_addr_operation
+  : public maybe_constant_operation<operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    /* C++: check for and handle pointer to members.  */
+    return std::get<0> (m_storage)->evaluate_for_address (exp, noside);
+  }
+
+  enum exp_opcode opcode () const override
+  { return UNOP_ADDR; }
+
+  /* Return the subexpression.  */
+  const operation_up &get_expression () const
+  {
+    return std::get<0> (m_storage);
+  }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override
+  {
+    gen_expr_unop (exp, UNOP_ADDR,
+                  std::get<0> (this->m_storage).get (),
+                  ax, value);
+  }
+};
+
+/* Implement 'sizeof'.  */
+class unop_sizeof_operation
+  : public maybe_constant_operation<operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    return std::get<0> (m_storage)->evaluate_for_sizeof (exp, noside);
+  }
+
+  enum exp_opcode opcode () const override
+  { return UNOP_SIZEOF; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* Implement 'alignof'.  */
+class unop_alignof_operation
+  : public maybe_constant_operation<operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *val = std::get<0> (m_storage)->evaluate (nullptr, exp,
+                                                   EVAL_AVOID_SIDE_EFFECTS);
+    return eval_op_alignof (expect_type, exp, noside, val);
+  }
+
+  enum exp_opcode opcode () const override
+  { return UNOP_ALIGNOF; }
+};
+
+/* Implement UNOP_MEMVAL.  */
+class unop_memval_operation
+  : public tuple_holding_operation<operation_up, struct type *>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *val = std::get<0> (m_storage)->evaluate (expect_type, exp, noside);
+    return eval_op_memval (expect_type, exp, noside, val,
+                          std::get<1> (m_storage));
+  }
+
+  value *evaluate_for_sizeof (struct expression *exp,
+                             enum noside noside) override;
+
+  value *evaluate_for_address (struct expression *exp,
+                              enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return UNOP_MEMVAL; }
+
+  /* Return the type referenced by this object.  */
+  struct type *get_type () const
+  {
+    return std::get<1> (m_storage);
+  }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* Implement UNOP_MEMVAL_TYPE.  */
+class unop_memval_type_operation
+  : public tuple_holding_operation<operation_up, operation_up>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *typeval
+      = std::get<0> (m_storage)->evaluate (expect_type, exp,
+                                          EVAL_AVOID_SIDE_EFFECTS);
+    struct type *type = value_type (typeval);
+    value *val = std::get<1> (m_storage)->evaluate (expect_type, exp, noside);
+    return eval_op_memval (expect_type, exp, noside, val, type);
+  }
+
+  value *evaluate_for_sizeof (struct expression *exp,
+                             enum noside noside) override;
+
+  value *evaluate_for_address (struct expression *exp,
+                              enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return UNOP_MEMVAL_TYPE; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* Implement the 'this' expression.  */
+class op_this_operation
+  : public tuple_holding_operation<>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    return value_of_this (exp->language_defn);
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP_THIS; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* Implement the "type instance" operation.  */
+class type_instance_operation
+  : public tuple_holding_operation<type_instance_flags, std::vector<type *>,
+                                  operation_up>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return TYPE_INSTANCE; }
+};
+
+/* The assignment operator.  */
+class assign_operation
+  : public tuple_holding_operation<operation_up, operation_up>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *lhs = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
+    /* Special-case assignments where the left-hand-side is a
+       convenience variable -- in these, don't bother setting an
+       expected type.  This avoids a weird case where re-assigning a
+       string or array to an internal variable could error with "Too
+       many array elements".  */
+    struct type *xtype = (VALUE_LVAL (lhs) == lval_internalvar
+                         ? nullptr
+                         : value_type (lhs));
+    value *rhs = std::get<1> (m_storage)->evaluate (xtype, exp, noside);
+
+    if (noside == EVAL_AVOID_SIDE_EFFECTS)
+      return lhs;
+    if (binop_user_defined_p (BINOP_ASSIGN, lhs, rhs))
+      return value_x_binop (lhs, rhs, BINOP_ASSIGN, OP_NULL, noside);
+    else
+      return value_assign (lhs, rhs);
+  }
+
+  enum exp_opcode opcode () const override
+  { return BINOP_ASSIGN; }
+
+  /* Return the left-hand-side of the assignment.  */
+  operation *get_lhs () const
+  {
+    return std::get<0> (m_storage).get ();
+  }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* Assignment with modification, like "+=".  */
+class assign_modify_operation
+  : public tuple_holding_operation<exp_opcode, operation_up, operation_up>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *lhs = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
+    value *rhs = std::get<2> (m_storage)->evaluate (expect_type, exp, noside);
+    return eval_binop_assign_modify (expect_type, exp, noside,
+                                    std::get<0> (m_storage), lhs, rhs);
+  }
+
+  enum exp_opcode opcode () const override
+  { return BINOP_ASSIGN_MODIFY; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* A type cast.  */
+class unop_cast_operation
+  : public maybe_constant_operation<operation_up, struct type *>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    return std::get<0> (m_storage)->evaluate_for_cast (std::get<1> (m_storage),
+                                                      exp, noside);
+  }
+
+  enum exp_opcode opcode () const override
+  { return UNOP_CAST; }
+
+  /* Return the type referenced by this object.  */
+  struct type *get_type () const
+  {
+    return std::get<1> (m_storage);
+  }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* A cast, but the type comes from an expression, not a "struct
+   type".  */
+class unop_cast_type_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *val = std::get<0> (m_storage)->evaluate (nullptr, exp,
+                                                   EVAL_AVOID_SIDE_EFFECTS);
+    return std::get<1> (m_storage)->evaluate_for_cast (value_type (val),
+                                                      exp, noside);
+  }
+
+  enum exp_opcode opcode () const override
+  { return UNOP_CAST_TYPE; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+typedef value *cxx_cast_ftype (struct type *, value *);
+
+/* This implements dynamic_cast and reinterpret_cast.  static_cast and
+   const_cast are handled by the ordinary case operations.  */
+template<exp_opcode OP, cxx_cast_ftype FUNC>
+class cxx_cast_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    value *val = std::get<0> (m_storage)->evaluate (nullptr, exp,
+                                                   EVAL_AVOID_SIDE_EFFECTS);
+    struct type *type = value_type (val);
+    value *rhs = std::get<1> (m_storage)->evaluate (type, exp, noside);
+    return FUNC (type, rhs);
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP; }
+};
+
+using dynamic_cast_operation = cxx_cast_operation<UNOP_DYNAMIC_CAST,
+                                                 value_dynamic_cast>;
+using reinterpret_cast_operation = cxx_cast_operation<UNOP_REINTERPRET_CAST,
+                                                     value_reinterpret_cast>;
+
+/* Multi-dimensional subscripting.  */
+class multi_subscript_operation
+  : public tuple_holding_operation<operation_up, std::vector<operation_up>>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return MULTI_SUBSCRIPT; }
+};
+
+/* The "&&" operator.  */
+class logical_and_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return BINOP_LOGICAL_AND; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* The "||" operator.  */
+class logical_or_operation
+  : public maybe_constant_operation<operation_up, operation_up>
+{
+public:
+
+  using maybe_constant_operation::maybe_constant_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return BINOP_LOGICAL_OR; }
+
+protected:
+
+  void do_generate_ax (struct expression *exp,
+                      struct agent_expr *ax,
+                      struct axs_value *value,
+                      struct type *cast_type)
+    override;
+};
+
+/* This class implements ADL (aka Koenig) function calls for C++.  It
+   holds the name of the function to call, the block in which the
+   lookup should be done, and a vector of arguments.  */
+class adl_func_operation
+  : public tuple_holding_operation<std::string, const block *,
+                                  std::vector<operation_up>>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return OP_ADL_FUNC; }
+};
+
+/* The OP_ARRAY operation.  */
+class array_operation
+  : public tuple_holding_operation<int, int, std::vector<operation_up>>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override;
+
+  enum exp_opcode opcode () const override
+  { return OP_ARRAY; }
+
+private:
+
+  struct value *evaluate_struct_tuple (struct value *struct_val,
+                                      struct expression *exp,
+                                      enum noside noside, int nargs);
+};
+
+/* A function call.  This holds the callee operation and the
+   arguments.  */
+class funcall_operation
+  : public tuple_holding_operation<operation_up, std::vector<operation_up>>
+{
+public:
+
+  using tuple_holding_operation::tuple_holding_operation;
+
+  value *evaluate (struct type *expect_type,
+                  struct expression *exp,
+                  enum noside noside) override
+  {
+    return std::get<0> (m_storage)->evaluate_funcall (expect_type, exp, noside,
+                                                     std::get<1> (m_storage));
+  }
+
+  enum exp_opcode opcode () const override
+  { return OP_FUNCALL; }
+};
+
 } /* namespace expr */
 
 #endif /* EXPOP_H */
This page took 0.039357 seconds and 4 git commands to generate.