1/* Definitions for Ada expressions
2
3   Copyright (C) 2020-2023 Free Software Foundation, Inc.
4
5   This file is part of GDB.
6
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.
11
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.
16
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/>.  */
19
20#ifndef ADA_EXP_H
21#define ADA_EXP_H
22
23#include "expop.h"
24
25extern struct value *ada_unop_neg (struct type *expect_type,
26				   struct expression *exp,
27				   enum noside noside, enum exp_opcode op,
28				   struct value *arg1);
29extern struct value *ada_atr_tag (struct type *expect_type,
30				  struct expression *exp,
31				  enum noside noside, enum exp_opcode op,
32				  struct value *arg1);
33extern struct value *ada_atr_size (struct type *expect_type,
34				   struct expression *exp,
35				   enum noside noside, enum exp_opcode op,
36				   struct value *arg1);
37extern struct value *ada_abs (struct type *expect_type,
38			      struct expression *exp,
39			      enum noside noside, enum exp_opcode op,
40			      struct value *arg1);
41extern struct value *ada_unop_in_range (struct type *expect_type,
42					struct expression *exp,
43					enum noside noside, enum exp_opcode op,
44					struct value *arg1, struct type *type);
45extern struct value *ada_mult_binop (struct type *expect_type,
46				     struct expression *exp,
47				     enum noside noside, enum exp_opcode op,
48				     struct value *arg1, struct value *arg2);
49extern struct value *ada_equal_binop (struct type *expect_type,
50				      struct expression *exp,
51				      enum noside noside, enum exp_opcode op,
52				      struct value *arg1, struct value *arg2);
53extern struct value *ada_ternop_slice (struct expression *exp,
54				       enum noside noside,
55				       struct value *array,
56				       struct value *low_bound_val,
57				       struct value *high_bound_val);
58extern struct value *ada_binop_in_bounds (struct expression *exp,
59					  enum noside noside,
60					  struct value *arg1,
61					  struct value *arg2,
62					  int n);
63extern struct value *ada_binop_minmax (struct type *expect_type,
64				       struct expression *exp,
65				       enum noside noside, enum exp_opcode op,
66				       struct value *arg1,
67				       struct value *arg2);
68extern struct value *ada_pos_atr (struct type *expect_type,
69				  struct expression *exp,
70				  enum noside noside, enum exp_opcode op,
71				  struct value *arg);
72extern struct value *ada_val_atr (enum noside noside, struct type *type,
73				  struct value *arg);
74extern struct value *ada_binop_exp (struct type *expect_type,
75				    struct expression *exp,
76				    enum noside noside, enum exp_opcode op,
77				    struct value *arg1, struct value *arg2);
78
79namespace expr
80{
81
82/* The base class for Ada type resolution.  Ada operations that want
83   to participate in resolution implement this interface.  */
84struct ada_resolvable
85{
86  /* Resolve this object.  EXP is the expression being resolved.
87     DEPROCEDURE_P is true if a symbol that refers to a zero-argument
88     function may be turned into a function call.  PARSE_COMPLETION
89     and TRACKER are passed in from the parser context.  CONTEXT_TYPE
90     is the expected type of the expression, or nullptr if none is
91     known.  This method should return true if the operation should be
92     replaced by a function call with this object as the callee.  */
93  virtual bool resolve (struct expression *exp,
94			bool deprocedure_p,
95			bool parse_completion,
96			innermost_block_tracker *tracker,
97			struct type *context_type) = 0;
98
99  /* Possibly replace this object with some other expression object.
100     This is like 'resolve', but can return a replacement.
101
102     The default implementation calls 'resolve' and wraps this object
103     in a function call if that call returns true.  OWNER is a
104     reference to the unique pointer that owns the 'this'; it can be
105     'move'd from to construct the replacement.
106
107     This should either return a new object, or OWNER -- never
108     nullptr.  */
109
110  virtual operation_up replace (operation_up &&owner,
111				struct expression *exp,
112				bool deprocedure_p,
113				bool parse_completion,
114				innermost_block_tracker *tracker,
115				struct type *context_type);
116};
117
118/* In Ada, some generic operations must be wrapped with a handler that
119   handles some Ada-specific type conversions.  */
120class ada_wrapped_operation
121  : public tuple_holding_operation<operation_up>
122{
123public:
124
125  using tuple_holding_operation::tuple_holding_operation;
126
127  value *evaluate (struct type *expect_type,
128		   struct expression *exp,
129		   enum noside noside) override;
130
131  enum exp_opcode opcode () const override
132  { return std::get<0> (m_storage)->opcode (); }
133};
134
135/* An Ada string constant.  */
136class ada_string_operation
137  : public string_operation
138{
139public:
140
141  using string_operation::string_operation;
142
143  /* Return the underlying string.  */
144  const char *get_name () const
145  {
146    return std::get<0> (m_storage).c_str ();
147  }
148
149  value *evaluate (struct type *expect_type,
150		   struct expression *exp,
151		   enum noside noside) override;
152};
153
154/* The Ada TYPE'(EXP) construct.  */
155class ada_qual_operation
156  : public tuple_holding_operation<operation_up, struct type *>
157{
158public:
159
160  using tuple_holding_operation::tuple_holding_operation;
161
162  value *evaluate (struct type *expect_type,
163		   struct expression *exp,
164		   enum noside noside) override;
165
166  enum exp_opcode opcode () const override
167  { return UNOP_QUAL; }
168};
169
170/* Ternary in-range operator.  */
171class ada_ternop_range_operation
172  : public tuple_holding_operation<operation_up, operation_up, operation_up>
173{
174public:
175
176  using tuple_holding_operation::tuple_holding_operation;
177
178  value *evaluate (struct type *expect_type,
179		   struct expression *exp,
180		   enum noside noside) override;
181
182  enum exp_opcode opcode () const override
183  { return TERNOP_IN_RANGE; }
184};
185
186using ada_neg_operation = unop_operation<UNOP_NEG, ada_unop_neg>;
187using ada_atr_tag_operation = unop_operation<OP_ATR_TAG, ada_atr_tag>;
188using ada_atr_size_operation = unop_operation<OP_ATR_SIZE, ada_atr_size>;
189using ada_abs_operation = unop_operation<UNOP_ABS, ada_abs>;
190using ada_pos_operation = unop_operation<OP_ATR_POS, ada_pos_atr>;
191
192/* The in-range operation, given a type.  */
193class ada_unop_range_operation
194  : public tuple_holding_operation<operation_up, struct type *>
195{
196public:
197
198  using tuple_holding_operation::tuple_holding_operation;
199
200  value *evaluate (struct type *expect_type,
201		   struct expression *exp,
202		   enum noside noside) override
203  {
204    value *val = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
205    return ada_unop_in_range (expect_type, exp, noside, UNOP_IN_RANGE,
206			      val, std::get<1> (m_storage));
207  }
208
209  enum exp_opcode opcode () const override
210  { return UNOP_IN_RANGE; }
211};
212
213/* The Ada + and - operators.  */
214class ada_binop_addsub_operation
215  : public tuple_holding_operation<enum exp_opcode, operation_up, operation_up>
216{
217public:
218
219  using tuple_holding_operation::tuple_holding_operation;
220
221  value *evaluate (struct type *expect_type,
222		   struct expression *exp,
223		   enum noside noside) override;
224
225  enum exp_opcode opcode () const override
226  { return std::get<0> (m_storage); }
227};
228
229using ada_binop_mul_operation = binop_operation<BINOP_MUL, ada_mult_binop>;
230using ada_binop_div_operation = binop_operation<BINOP_DIV, ada_mult_binop>;
231using ada_binop_rem_operation = binop_operation<BINOP_REM, ada_mult_binop>;
232using ada_binop_mod_operation = binop_operation<BINOP_MOD, ada_mult_binop>;
233
234using ada_binop_min_operation = binop_operation<BINOP_MIN, ada_binop_minmax>;
235using ada_binop_max_operation = binop_operation<BINOP_MAX, ada_binop_minmax>;
236
237using ada_binop_exp_operation = binop_operation<BINOP_EXP, ada_binop_exp>;
238
239/* Implement the equal and not-equal operations for Ada.  */
240class ada_binop_equal_operation
241  : public tuple_holding_operation<enum exp_opcode, operation_up, operation_up>
242{
243public:
244
245  using tuple_holding_operation::tuple_holding_operation;
246
247  value *evaluate (struct type *expect_type,
248		   struct expression *exp,
249		   enum noside noside) override
250  {
251    value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
252    value *arg2 = std::get<2> (m_storage)->evaluate (value_type (arg1),
253						     exp, noside);
254    return ada_equal_binop (expect_type, exp, noside, std::get<0> (m_storage),
255			    arg1, arg2);
256  }
257
258  enum exp_opcode opcode () const override
259  { return std::get<0> (m_storage); }
260};
261
262/* Bitwise operators for Ada.  */
263template<enum exp_opcode OP>
264class ada_bitwise_operation
265  : public maybe_constant_operation<operation_up, operation_up>
266{
267public:
268
269  using maybe_constant_operation::maybe_constant_operation;
270
271  value *evaluate (struct type *expect_type,
272		   struct expression *exp,
273		   enum noside noside) override
274  {
275    value *lhs = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
276    value *rhs = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
277    value *result = eval_op_binary (expect_type, exp, noside, OP, lhs, rhs);
278    return value_cast (value_type (lhs), result);
279  }
280
281  enum exp_opcode opcode () const override
282  { return OP; }
283};
284
285using ada_bitwise_and_operation = ada_bitwise_operation<BINOP_BITWISE_AND>;
286using ada_bitwise_ior_operation = ada_bitwise_operation<BINOP_BITWISE_IOR>;
287using ada_bitwise_xor_operation = ada_bitwise_operation<BINOP_BITWISE_XOR>;
288
289/* Ada array- or string-slice operation.  */
290class ada_ternop_slice_operation
291  : public maybe_constant_operation<operation_up, operation_up, operation_up>,
292    public ada_resolvable
293{
294public:
295
296  using maybe_constant_operation::maybe_constant_operation;
297
298  value *evaluate (struct type *expect_type,
299		   struct expression *exp,
300		   enum noside noside) override
301  {
302    value *array = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
303    value *low = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
304    value *high = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
305    return ada_ternop_slice (exp, noside, array, low, high);
306  }
307
308  enum exp_opcode opcode () const override
309  { return TERNOP_SLICE; }
310
311  bool resolve (struct expression *exp,
312		bool deprocedure_p,
313		bool parse_completion,
314		innermost_block_tracker *tracker,
315		struct type *context_type) override;
316};
317
318/* Implement BINOP_IN_BOUNDS for Ada.  */
319class ada_binop_in_bounds_operation
320  : public maybe_constant_operation<operation_up, operation_up, int>
321{
322public:
323
324  using maybe_constant_operation::maybe_constant_operation;
325
326  value *evaluate (struct type *expect_type,
327		   struct expression *exp,
328		   enum noside noside) override
329  {
330    value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
331    value *arg2 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
332    return ada_binop_in_bounds (exp, noside, arg1, arg2,
333				std::get<2> (m_storage));
334  }
335
336  enum exp_opcode opcode () const override
337  { return BINOP_IN_BOUNDS; }
338};
339
340/* Implement several unary Ada OP_ATR_* operations.  */
341class ada_unop_atr_operation
342  : public maybe_constant_operation<operation_up, enum exp_opcode, int>
343{
344public:
345
346  using maybe_constant_operation::maybe_constant_operation;
347
348  value *evaluate (struct type *expect_type,
349		   struct expression *exp,
350		   enum noside noside) override;
351
352  enum exp_opcode opcode () const override
353  { return std::get<1> (m_storage); }
354};
355
356/* Variant of var_value_operation for Ada.  */
357class ada_var_value_operation
358  : public var_value_operation, public ada_resolvable
359{
360public:
361
362  using var_value_operation::var_value_operation;
363
364  value *evaluate (struct type *expect_type,
365		   struct expression *exp,
366		   enum noside noside) override;
367
368  value *evaluate_for_cast (struct type *expect_type,
369			    struct expression *exp,
370			    enum noside noside) override;
371
372  const block *get_block () const
373  { return std::get<0> (m_storage).block; }
374
375  bool resolve (struct expression *exp,
376		bool deprocedure_p,
377		bool parse_completion,
378		innermost_block_tracker *tracker,
379		struct type *context_type) override;
380
381protected:
382
383  using operation::do_generate_ax;
384};
385
386/* Variant of var_msym_value_operation for Ada.  */
387class ada_var_msym_value_operation
388  : public var_msym_value_operation
389{
390public:
391
392  using var_msym_value_operation::var_msym_value_operation;
393
394  value *evaluate_for_cast (struct type *expect_type,
395			    struct expression *exp,
396			    enum noside noside) override;
397
398protected:
399
400  using operation::do_generate_ax;
401};
402
403/* Implement the Ada 'val attribute.  */
404class ada_atr_val_operation
405  : public tuple_holding_operation<struct type *, operation_up>
406{
407public:
408
409  using tuple_holding_operation::tuple_holding_operation;
410
411  value *evaluate (struct type *expect_type,
412		   struct expression *exp,
413		   enum noside noside) override;
414
415  enum exp_opcode opcode () const override
416  { return OP_ATR_VAL; }
417};
418
419/* The indirection operator for Ada.  */
420class ada_unop_ind_operation
421  : public unop_ind_base_operation
422{
423public:
424
425  using unop_ind_base_operation::unop_ind_base_operation;
426
427  value *evaluate (struct type *expect_type,
428		   struct expression *exp,
429		   enum noside noside) override;
430};
431
432/* Implement STRUCTOP_STRUCT for Ada.  */
433class ada_structop_operation
434  : public structop_base_operation
435{
436public:
437
438  using structop_base_operation::structop_base_operation;
439
440  value *evaluate (struct type *expect_type,
441		   struct expression *exp,
442		   enum noside noside) override;
443
444  enum exp_opcode opcode () const override
445  { return STRUCTOP_STRUCT; }
446
447  /* Set the completion prefix.  */
448  void set_prefix (std::string &&prefix)
449  {
450    m_prefix = std::move (prefix);
451  }
452
453  bool complete (struct expression *exp, completion_tracker &tracker) override
454  {
455    return structop_base_operation::complete (exp, tracker, m_prefix.c_str ());
456  }
457
458  void dump (struct ui_file *stream, int depth) const override
459  {
460    structop_base_operation::dump (stream, depth);
461    dump_for_expression (stream, depth + 1, m_prefix);
462  }
463
464private:
465
466  /* We may need to provide a prefix to field name completion.  See
467     ada-exp.y:find_completion_bounds for details.  */
468  std::string m_prefix;
469};
470
471/* Function calls for Ada.  */
472class ada_funcall_operation
473  : public tuple_holding_operation<operation_up, std::vector<operation_up>>,
474    public ada_resolvable
475{
476public:
477
478  using tuple_holding_operation::tuple_holding_operation;
479
480  value *evaluate (struct type *expect_type,
481		   struct expression *exp,
482		   enum noside noside) override;
483
484  bool resolve (struct expression *exp,
485		bool deprocedure_p,
486		bool parse_completion,
487		innermost_block_tracker *tracker,
488		struct type *context_type) override;
489
490  enum exp_opcode opcode () const override
491  { return OP_FUNCALL; }
492};
493
494/* An Ada assignment operation.  */
495class ada_assign_operation
496  : public assign_operation
497{
498public:
499
500  using assign_operation::assign_operation;
501
502  value *evaluate (struct type *expect_type,
503		   struct expression *exp,
504		   enum noside noside) override;
505
506  enum exp_opcode opcode () const override
507  { return BINOP_ASSIGN; }
508};
509
510/* This abstract class represents a single component in an Ada
511   aggregate assignment.  */
512class ada_component
513{
514public:
515
516  /* Assign to LHS, which is part of CONTAINER.  EXP is the expression
517     being evaluated.  INDICES, LOW, and HIGH indicate which
518     sub-components have already been assigned; INDICES should be
519     updated by this call.  */
520  virtual void assign (struct value *container,
521		       struct value *lhs, struct expression *exp,
522		       std::vector<LONGEST> &indices,
523		       LONGEST low, LONGEST high) = 0;
524
525  /* Same as operation::uses_objfile.  */
526  virtual bool uses_objfile (struct objfile *objfile) = 0;
527
528  /* Same as operation::dump.  */
529  virtual void dump (ui_file *stream, int depth) = 0;
530
531  virtual ~ada_component () = default;
532
533protected:
534
535  ada_component () = default;
536  DISABLE_COPY_AND_ASSIGN (ada_component);
537};
538
539/* Unique pointer specialization for Ada assignment components.  */
540typedef std::unique_ptr<ada_component> ada_component_up;
541
542/* An operation that holds a single component.  */
543class ada_aggregate_operation
544  : public tuple_holding_operation<ada_component_up>
545{
546public:
547
548  using tuple_holding_operation::tuple_holding_operation;
549
550  /* Assuming that LHS represents an lvalue having a record or array
551     type, evaluate an assignment of this aggregate's value to LHS.
552     CONTAINER is an lvalue containing LHS (possibly LHS itself).
553     Does not modify the inferior's memory, nor does it modify the
554     contents of LHS (unless == CONTAINER).  Returns the modified
555     CONTAINER.  */
556
557  value *assign_aggregate (struct value *container,
558			   struct value *lhs,
559			   struct expression *exp);
560
561  value *evaluate (struct type *expect_type,
562		   struct expression *exp,
563		   enum noside noside) override
564  {
565    error (_("Aggregates only allowed on the right of an assignment"));
566  }
567
568  enum exp_opcode opcode () const override
569  { return OP_AGGREGATE; }
570};
571
572/* A component holding a vector of other components to assign.  */
573class ada_aggregate_component : public ada_component
574{
575public:
576
577  explicit ada_aggregate_component (std::vector<ada_component_up> &&components)
578    : m_components (std::move (components))
579  {
580  }
581
582  void assign (struct value *container,
583	       struct value *lhs, struct expression *exp,
584	       std::vector<LONGEST> &indices,
585	       LONGEST low, LONGEST high) override;
586
587  bool uses_objfile (struct objfile *objfile) override;
588
589  void dump (ui_file *stream, int depth) override;
590
591private:
592
593  std::vector<ada_component_up> m_components;
594};
595
596/* A component that assigns according to a provided index (which is
597   relative to the "low" value).  */
598class ada_positional_component : public ada_component
599{
600public:
601
602  ada_positional_component (int index, operation_up &&op)
603    : m_index (index),
604      m_op (std::move (op))
605  {
606  }
607
608  void assign (struct value *container,
609	       struct value *lhs, struct expression *exp,
610	       std::vector<LONGEST> &indices,
611	       LONGEST low, LONGEST high) override;
612
613  bool uses_objfile (struct objfile *objfile) override;
614
615  void dump (ui_file *stream, int depth) override;
616
617private:
618
619  int m_index;
620  operation_up m_op;
621};
622
623/* A component which handles an "others" clause.  */
624class ada_others_component : public ada_component
625{
626public:
627
628  explicit ada_others_component (operation_up &&op)
629    : m_op (std::move (op))
630  {
631  }
632
633  void assign (struct value *container,
634	       struct value *lhs, struct expression *exp,
635	       std::vector<LONGEST> &indices,
636	       LONGEST low, LONGEST high) override;
637
638  bool uses_objfile (struct objfile *objfile) override;
639
640  void dump (ui_file *stream, int depth) override;
641
642private:
643
644  operation_up m_op;
645};
646
647/* An interface that represents an association that is used in
648   aggregate assignment.  */
649class ada_association
650{
651public:
652
653  /* Like ada_component::assign, but takes an operation as a
654     parameter.  The operation is evaluated and then assigned into LHS
655     according to the rules of the concrete implementation.  */
656  virtual void assign (struct value *container,
657		       struct value *lhs,
658		       struct expression *exp,
659		       std::vector<LONGEST> &indices,
660		       LONGEST low, LONGEST high,
661		       operation_up &op) = 0;
662
663  /* Same as operation::uses_objfile.  */
664  virtual bool uses_objfile (struct objfile *objfile) = 0;
665
666  /* Same as operation::dump.  */
667  virtual void dump (ui_file *stream, int depth) = 0;
668
669  virtual ~ada_association () = default;
670
671protected:
672
673  ada_association () = default;
674  DISABLE_COPY_AND_ASSIGN (ada_association);
675};
676
677/* Unique pointer specialization for Ada assignment associations.  */
678typedef std::unique_ptr<ada_association> ada_association_up;
679
680/* A component that holds a vector of associations and an operation.
681   The operation is re-evaluated for each choice.  */
682class ada_choices_component : public ada_component
683{
684public:
685
686  explicit ada_choices_component (operation_up &&op)
687    : m_op (std::move (op))
688  {
689  }
690
691  /* Set the vector of associations.  This is done separately from the
692     constructor because it was simpler for the implementation of the
693     parser.  */
694  void set_associations (std::vector<ada_association_up> &&assoc)
695  {
696    m_assocs = std::move (assoc);
697  }
698
699  void assign (struct value *container,
700	       struct value *lhs, struct expression *exp,
701	       std::vector<LONGEST> &indices,
702	       LONGEST low, LONGEST high) override;
703
704  bool uses_objfile (struct objfile *objfile) override;
705
706  void dump (ui_file *stream, int depth) override;
707
708private:
709
710  std::vector<ada_association_up> m_assocs;
711  operation_up m_op;
712};
713
714/* An association that uses a discrete range.  */
715class ada_discrete_range_association : public ada_association
716{
717public:
718
719  ada_discrete_range_association (operation_up &&low, operation_up &&high)
720    : m_low (std::move (low)),
721      m_high (std::move (high))
722  {
723  }
724
725  void assign (struct value *container,
726	       struct value *lhs, struct expression *exp,
727	       std::vector<LONGEST> &indices,
728	       LONGEST low, LONGEST high,
729	       operation_up &op) override;
730
731  bool uses_objfile (struct objfile *objfile) override;
732
733  void dump (ui_file *stream, int depth) override;
734
735private:
736
737  operation_up m_low;
738  operation_up m_high;
739};
740
741/* An association that uses a name.  The name may be an expression
742   that evaluates to an integer (for arrays), or an Ada string or
743   variable value operation.  */
744class ada_name_association : public ada_association
745{
746public:
747
748  explicit ada_name_association (operation_up val)
749    : m_val (std::move (val))
750  {
751  }
752
753  void assign (struct value *container,
754	       struct value *lhs, struct expression *exp,
755	       std::vector<LONGEST> &indices,
756	       LONGEST low, LONGEST high,
757	       operation_up &op) override;
758
759  bool uses_objfile (struct objfile *objfile) override;
760
761  void dump (ui_file *stream, int depth) override;
762
763private:
764
765  operation_up m_val;
766};
767
768/* A character constant expression.  This is a separate operation so
769   that it can participate in resolution, so that TYPE'(CST) can
770   work correctly for enums with character enumerators.  */
771class ada_char_operation : public long_const_operation,
772			   public ada_resolvable
773{
774public:
775
776  using long_const_operation::long_const_operation;
777
778  bool resolve (struct expression *exp,
779		bool deprocedure_p,
780		bool parse_completion,
781		innermost_block_tracker *tracker,
782		struct type *context_type) override
783  {
784    /* This should never be called, because this class also implements
785       'replace'.  */
786    gdb_assert_not_reached ("unexpected call");
787  }
788
789  operation_up replace (operation_up &&owner,
790			struct expression *exp,
791			bool deprocedure_p,
792			bool parse_completion,
793			innermost_block_tracker *tracker,
794			struct type *context_type) override;
795
796  value *evaluate (struct type *expect_type,
797		   struct expression *exp,
798		   enum noside noside) override;
799};
800
801class ada_concat_operation : public concat_operation
802{
803public:
804
805  using concat_operation::concat_operation;
806
807  value *evaluate (struct type *expect_type,
808		   struct expression *exp,
809		   enum noside noside) override;
810};
811
812} /* namespace expr */
813
814#endif /* ADA_EXP_H */
815