1 /* Definitions for expressions in GDB
3 Copyright (C) 2020 Free Software Foundation, Inc.
5 This file is part of GDB.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
26 #include "expression.h"
28 #include "gdbsupport/traits.h"
29 #include "gdbsupport/enum-flags.h"
34 extern void gen_expr_binop (struct expression
*exp
,
36 expr::operation
*lhs
, expr::operation
*rhs
,
37 struct agent_expr
*ax
, struct axs_value
*value
);
38 extern void gen_expr_structop (struct expression
*exp
,
42 struct agent_expr
*ax
, struct axs_value
*value
);
44 extern struct value
*eval_op_scope (struct type
*expect_type
,
45 struct expression
*exp
,
47 struct type
*type
, const char *string
);
48 extern struct value
*eval_op_var_msym_value (struct type
*expect_type
,
49 struct expression
*exp
,
52 minimal_symbol
*msymbol
,
53 struct objfile
*objfile
);
54 extern struct value
*eval_op_var_entry_value (struct type
*expect_type
,
55 struct expression
*exp
,
56 enum noside noside
, symbol
*sym
);
61 /* The check_objfile overloads are used to check whether a particular
62 component of some operation references an objfile. The passed-in
63 objfile will never be a debug objfile. */
65 /* See if EXP_OBJFILE matches OBJFILE. */
67 check_objfile (struct objfile
*exp_objfile
, struct objfile
*objfile
)
69 if (exp_objfile
->separate_debug_objfile_backlink
)
70 exp_objfile
= exp_objfile
->separate_debug_objfile_backlink
;
71 return exp_objfile
== objfile
;
75 check_objfile (struct type
*type
, struct objfile
*objfile
)
77 struct objfile
*ty_objfile
= type
->objfile_owner ();
78 if (ty_objfile
!= nullptr)
79 return check_objfile (ty_objfile
, objfile
);
84 check_objfile (struct symbol
*sym
, struct objfile
*objfile
)
86 return check_objfile (symbol_objfile (sym
), objfile
);
90 check_objfile (const struct block
*block
, struct objfile
*objfile
)
92 return check_objfile (block_objfile (block
), objfile
);
96 check_objfile (minimal_symbol
*minsym
, struct objfile
*objfile
)
98 /* This may seem strange but minsyms are only used with an objfile
104 check_objfile (internalvar
*ivar
, struct objfile
*objfile
)
110 check_objfile (const std::string
&str
, struct objfile
*objfile
)
116 check_objfile (const operation_up
&op
, struct objfile
*objfile
)
118 return op
->uses_objfile (objfile
);
122 check_objfile (enum exp_opcode val
, struct objfile
*objfile
)
128 check_objfile (ULONGEST val
, struct objfile
*objfile
)
135 check_objfile (enum_flags
<T
> val
, struct objfile
*objfile
)
142 check_objfile (const std::vector
<T
> &collection
, struct objfile
*objfile
)
144 for (const auto &item
: collection
)
146 if (check_objfile (item
, objfile
))
152 template<typename S
, typename T
>
154 check_objfile (const std::pair
<S
, T
> &item
, struct objfile
*objfile
)
156 return (check_objfile (item
.first
, objfile
)
157 || check_objfile (item
.second
, objfile
));
161 dump_for_expression (struct ui_file
*stream
, int depth
,
162 const operation_up
&op
)
164 op
->dump (stream
, depth
);
167 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
169 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
170 const std::string
&str
);
171 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
173 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
175 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
177 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
179 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
180 minimal_symbol
*msym
);
181 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
183 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
184 type_instance_flags flags
);
185 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
186 enum c_string_type_values flags
);
187 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
188 enum range_flag flags
);
189 extern void dump_for_expression (struct ui_file
*stream
, int depth
,
194 dump_for_expression (struct ui_file
*stream
, int depth
,
195 const std::vector
<T
> &vals
)
197 fprintf_filtered (stream
, _("%*sVector:\n"), depth
, "");
198 for (auto &item
: vals
)
199 dump_for_expression (stream
, depth
+ 1, item
);
202 template<typename X
, typename Y
>
204 dump_for_expression (struct ui_file
*stream
, int depth
,
205 const std::pair
<X
, Y
> &vals
)
207 dump_for_expression (stream
, depth
, vals
.first
);
208 dump_for_expression (stream
, depth
, vals
.second
);
211 /* Base class for most concrete operations. This class holds data,
212 specified via template parameters, and supplies generic
213 implementations of the 'dump' and 'uses_objfile' methods. */
214 template<typename
... Arg
>
215 class tuple_holding_operation
: public operation
219 explicit tuple_holding_operation (Arg
... args
)
220 : m_storage (std::forward
<Arg
> (args
)...)
224 DISABLE_COPY_AND_ASSIGN (tuple_holding_operation
);
226 bool uses_objfile (struct objfile
*objfile
) const override
228 return do_check_objfile
<0, Arg
...> (objfile
, m_storage
);
231 void dump (struct ui_file
*stream
, int depth
) const override
233 dump_for_expression (stream
, depth
, opcode ());
234 do_dump
<0, Arg
...> (stream
, depth
+ 1, m_storage
);
239 /* Storage for the data. */
240 std::tuple
<Arg
...> m_storage
;
244 /* do_dump does the work of dumping the data. */
245 template<int I
, typename
... T
>
246 typename
std::enable_if
<I
== sizeof... (T
), void>::type
247 do_dump (struct ui_file
*stream
, int depth
, const std::tuple
<T
...> &value
)
252 template<int I
, typename
... T
>
253 typename
std::enable_if
<I
< sizeof... (T
), void>::type
254 do_dump (struct ui_file
*stream
, int depth
, const std::tuple
<T
...> &value
)
257 dump_for_expression (stream
, depth
, std::get
<I
> (value
));
258 do_dump
<I
+ 1, T
...> (stream
, depth
, value
);
261 /* do_check_objfile does the work of checking whether this object
262 refers to OBJFILE. */
263 template<int I
, typename
... T
>
264 typename
std::enable_if
<I
== sizeof... (T
), bool>::type
265 do_check_objfile (struct objfile
*objfile
, const std::tuple
<T
...> &value
)
271 template<int I
, typename
... T
>
272 typename
std::enable_if
<I
< sizeof... (T
), bool>::type
273 do_check_objfile (struct objfile
*objfile
, const std::tuple
<T
...> &value
)
276 if (check_objfile (std::get
<I
> (value
), objfile
))
278 return do_check_objfile
<I
+ 1, T
...> (objfile
, value
);
282 /* The check_constant overloads are used to decide whether a given
283 concrete operation is a constant. This is done by checking the
287 check_constant (const operation_up
&item
)
289 return item
->constant_p ();
293 check_constant (struct minimal_symbol
*msym
)
299 check_constant (struct type
*type
)
305 check_constant (const struct block
*block
)
311 check_constant (const std::string
&str
)
317 check_constant (struct objfile
*objfile
)
323 check_constant (ULONGEST cst
)
329 check_constant (struct symbol
*sym
)
331 enum address_class sc
= SYMBOL_CLASS (sym
);
332 return (sc
== LOC_BLOCK
334 || sc
== LOC_CONST_BYTES
340 check_constant (const std::vector
<T
> &collection
)
342 for (const auto &item
: collection
)
343 if (!check_constant (item
))
348 template<typename S
, typename T
>
350 check_constant (const std::pair
<S
, T
> &item
)
352 return check_constant (item
.first
) && check_constant (item
.second
);
355 /* Base class for concrete operations. This class supplies an
356 implementation of 'constant_p' that works by checking the
358 template<typename
... Arg
>
359 class maybe_constant_operation
360 : public tuple_holding_operation
<Arg
...>
364 using tuple_holding_operation
<Arg
...>::tuple_holding_operation
;
366 bool constant_p () const override
368 return do_check_constant
<0, Arg
...> (this->m_storage
);
373 template<int I
, typename
... T
>
374 typename
std::enable_if
<I
== sizeof... (T
), bool>::type
375 do_check_constant (const std::tuple
<T
...> &value
) const
380 template<int I
, typename
... T
>
381 typename
std::enable_if
<I
< sizeof... (T
), bool>::type
382 do_check_constant (const std::tuple
<T
...> &value
) const
384 if (!check_constant (std::get
<I
> (value
)))
386 return do_check_constant
<I
+ 1, T
...> (value
);
390 /* A floating-point constant. The constant is encoded in the target
393 typedef std::array
<gdb_byte
, 16> float_data
;
395 /* An operation that holds a floating-point constant of a given
398 This does not need the facilities provided by
399 tuple_holding_operation, so it does not use it. */
400 class float_const_operation
405 float_const_operation (struct type
*type
, float_data data
)
411 value
*evaluate (struct type
*expect_type
,
412 struct expression
*exp
,
413 enum noside noside
) override
415 return value_from_contents (m_type
, m_data
.data ());
418 enum exp_opcode
opcode () const override
421 bool constant_p () const override
424 void dump (struct ui_file
*stream
, int depth
) const override
;
432 class scope_operation
433 : public maybe_constant_operation
<struct type
*, std::string
>
437 using maybe_constant_operation::maybe_constant_operation
;
439 value
*evaluate (struct type
*expect_type
,
440 struct expression
*exp
,
441 enum noside noside
) override
443 return eval_op_scope (expect_type
, exp
, noside
,
444 std::get
<0> (m_storage
),
445 std::get
<1> (m_storage
).c_str ());
448 value
*evaluate_for_address (struct expression
*exp
,
449 enum noside noside
) override
;
451 enum exp_opcode
opcode () const override
456 void do_generate_ax (struct expression
*exp
,
457 struct agent_expr
*ax
,
458 struct axs_value
*value
,
459 struct type
*cast_type
)
463 class long_const_operation
464 : public tuple_holding_operation
<struct type
*, LONGEST
>
468 using tuple_holding_operation::tuple_holding_operation
;
470 value
*evaluate (struct type
*expect_type
,
471 struct expression
*exp
,
472 enum noside noside
) override
474 return value_from_longest (std::get
<0> (m_storage
),
475 std::get
<1> (m_storage
));
478 enum exp_opcode
opcode () const override
481 bool constant_p () const override
486 void do_generate_ax (struct expression
*exp
,
487 struct agent_expr
*ax
,
488 struct axs_value
*value
,
489 struct type
*cast_type
)
493 class var_msym_value_operation
494 : public maybe_constant_operation
<minimal_symbol
*, struct objfile
*>
498 using maybe_constant_operation::maybe_constant_operation
;
500 value
*evaluate (struct type
*expect_type
,
501 struct expression
*exp
,
502 enum noside noside
) override
504 return eval_op_var_msym_value (expect_type
, exp
, noside
, m_outermost
,
505 std::get
<0> (m_storage
),
506 std::get
<1> (m_storage
));
509 value
*evaluate_for_sizeof (struct expression
*exp
, enum noside noside
)
512 value
*evaluate_for_address (struct expression
*exp
, enum noside noside
)
515 value
*evaluate_for_cast (struct type
*expect_type
,
516 struct expression
*exp
,
517 enum noside noside
) override
;
519 enum exp_opcode
opcode () const override
520 { return OP_VAR_MSYM_VALUE
; }
522 void set_outermost () override
529 /* True if this is the outermost operation in the expression. */
530 bool m_outermost
= false;
532 void do_generate_ax (struct expression
*exp
,
533 struct agent_expr
*ax
,
534 struct axs_value
*value
,
535 struct type
*cast_type
)
539 class var_entry_value_operation
540 : public tuple_holding_operation
<symbol
*>
544 using tuple_holding_operation::tuple_holding_operation
;
546 value
*evaluate (struct type
*expect_type
,
547 struct expression
*exp
,
548 enum noside noside
) override
550 return eval_op_var_entry_value (expect_type
, exp
, noside
,
551 std::get
<0> (m_storage
));
554 enum exp_opcode
opcode () const override
555 { return OP_VAR_ENTRY_VALUE
; }
558 } /* namespace expr */