Merge branch 'master' into verilog-ams
[sverilog.git] / PExpr.h
blob0d0b66f339cf633cb2b631d2ffcc0db934bfd0f8
1 #ifndef __PExpr_H
2 #define __PExpr_H
3 /*
4 * Copyright (c) 1998-2008 Stephen Williams <steve@icarus.com>
6 * This source code is free software; you can redistribute it
7 * and/or modify it in source code form under the terms of the GNU
8 * General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
10 * 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, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
22 # include <string>
23 # include <vector>
24 # include "netlist.h"
25 # include "verinum.h"
26 # include "LineInfo.h"
27 # include "pform_types.h"
29 class Design;
30 class Module;
31 class NetNet;
32 class NetExpr;
33 class NetScope;
36 * The PExpr class hierarchy supports the description of
37 * expressions. The parser can generate expression objects from the
38 * source, possibly reducing things that it knows how to reduce.
40 * The elaborate_net method is used by structural elaboration to build
41 * up a netlist interpretation of the expression.
44 class PExpr : public LineInfo {
46 public:
47 PExpr();
48 virtual ~PExpr();
50 virtual void dump(ostream&) const;
52 // This method tests the width that the expression wants to
53 // be. It is used by elaboration of assignments to figure out
54 // the width of the expression.
56 // The "min" is the width of the local context, so it the
57 // minimum width that this function should return. Initially
58 // this is the same as the lval width.
60 // The "lval" is the width of the destination where this
61 // result is going to go. This can be used to constrain the
62 // amount that an expression can reasonably expand. For
63 // example, there is no point expanding an addition to beyond
64 // the lval. This extra bit of information allows the
65 // expression to optimize itself a bit. If the lval==0, then
66 // the subexpression should not make l-value related
67 // optimizations.
69 // The unsigned_flag is set to true if the expression is
70 // unsized and therefore expandable. This happens if a
71 // sub-expression is an unsized literal. Some expressions make
72 // special use of that.
73 virtual unsigned test_width(Design*des, NetScope*scope,
74 unsigned min, unsigned lval,
75 bool&unsized_flag) const;
77 // During the elaborate_sig phase, we may need to scan
78 // expressions to find implicit net declarations.
79 virtual bool elaborate_sig(Design*des, NetScope*scope) const;
81 // Procedural elaboration of the expression. The expr_width is
82 // the width of the context of the expression (i.e. the
83 // l-value width of an assignment),
85 // ... or -1 if the expression is self-determined. or
86 // ... or -2 if the expression is losslessly
87 // self-determined. This can happen in situations where the
88 // result is going to a pseudo-infinitely wide context.
90 // The sys_task_arg flag is true if expressions are allowed to
91 // be incomplete.
92 virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
93 int expr_width, bool sys_task_arg) const;
95 // Elaborate expressions that are the r-value of parameter
96 // assignments. This elaboration follows the restrictions of
97 // constant expressions and supports later overriding and
98 // evaluation of parameters.
99 virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
101 // This method elaborate the expression as gates, for use in a
102 // continuous assign or other wholly structural context.
103 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
104 unsigned lwidth,
105 const NetExpr* rise,
106 const NetExpr* fall,
107 const NetExpr* decay,
108 Link::strength_t drive0 =Link::STRONG,
109 Link::strength_t drive1 =Link::STRONG)
110 const;
112 // This method elaborates the expression as gates, but
113 // restricted for use as l-values of continuous assignments.
114 virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
116 // This is similar to elaborate_lnet, except that the
117 // expression is evaluated to be bi-directional. This is
118 // useful for arguments to inout ports of module instances and
119 // ports of tran primitives.
120 virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
122 // Expressions that can be in the l-value of procedural
123 // assignments can be elaborated with this method. If the
124 // is_force flag is true, then the set of valid l-value types
125 // is slightly modified to accommodate the Verilog force
126 // statement
127 virtual NetAssign_* elaborate_lval(Design*des,
128 NetScope*scope,
129 bool is_force) const;
131 // This attempts to evaluate a constant expression, and return
132 // a verinum as a result. If the expression cannot be
133 // evaluated, return 0.
134 virtual verinum* eval_const(Design*des, NetScope*sc) const;
136 // This method returns true if that expression is the same as
137 // this expression. This method is used for comparing
138 // expressions that must be structurally "identical".
139 virtual bool is_the_same(const PExpr*that) const;
141 // Return true if this expression is a valid constant
142 // expression. the Module pointer is needed to find parameter
143 // identifiers and any other module specific interpretations
144 // of expressions.
145 virtual bool is_constant(Module*) const;
147 private: // not implemented
148 PExpr(const PExpr&);
149 PExpr& operator= (const PExpr&);
152 ostream& operator << (ostream&, const PExpr&);
154 class PEConcat : public PExpr {
156 public:
157 PEConcat(const svector<PExpr*>&p, PExpr*r =0);
158 ~PEConcat();
160 virtual verinum* eval_const(Design*des, NetScope*sc) const;
161 virtual void dump(ostream&) const;
163 virtual bool elaborate_sig(Design*des, NetScope*scope) const;
164 virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
165 virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
166 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
167 unsigned width,
168 const NetExpr* rise,
169 const NetExpr* fall,
170 const NetExpr* decay,
171 Link::strength_t drive0,
172 Link::strength_t drive1) const;
173 virtual NetExpr*elaborate_expr(Design*des, NetScope*,
174 int expr_width, bool sys_task_arg) const;
175 virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
176 virtual NetAssign_* elaborate_lval(Design*des,
177 NetScope*scope,
178 bool is_force) const;
179 virtual bool is_constant(Module*) const;
181 private:
182 NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
183 bool bidirectional_flag) const;
184 private:
185 svector<PExpr*>parms_;
186 PExpr*repeat_;
190 * Event expressions are expressions that can be combined with the
191 * event "or" operator. These include "posedge foo" and similar, and
192 * also include named events. "edge" events are associated with an
193 * expression, whereas named events simply have a name, which
194 * represents an event variable.
196 class PEEvent : public PExpr {
198 public:
199 enum edge_t {ANYEDGE, POSEDGE, NEGEDGE, POSITIVE};
201 // Use this constructor to create events based on edges or levels.
202 PEEvent(edge_t t, PExpr*e);
204 ~PEEvent();
206 edge_t type() const;
207 PExpr* expr() const;
209 virtual void dump(ostream&) const;
211 private:
212 edge_t type_;
213 PExpr *expr_;
217 * This holds a floating point constant in the source.
219 class PEFNumber : public PExpr {
221 public:
222 explicit PEFNumber(verireal*vp);
223 ~PEFNumber();
225 const verireal& value() const;
227 /* The eval_const method as applied to a floating point number
228 gets the *integer* value of the number. This accounts for
229 any rounding that is needed to get the value. */
230 virtual verinum* eval_const(Design*des, NetScope*sc) const;
232 /* A PEFNumber is a constant, so this returns true. */
233 virtual bool is_constant(Module*) const;
235 virtual NetExpr*elaborate_expr(Design*des, NetScope*,
236 int expr_width, bool sys_task_arg) const;
237 virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
239 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
240 unsigned lwidth,
241 const NetExpr* rise,
242 const NetExpr* fall,
243 const NetExpr* decay,
244 Link::strength_t drive0,
245 Link::strength_t drive1) const;
247 virtual void dump(ostream&) const;
249 private:
250 verireal*value_;
253 class PEIdent : public PExpr {
255 public:
256 explicit PEIdent(perm_string);
257 explicit PEIdent(const pform_name_t&);
258 ~PEIdent();
260 // Add another name to the string of hierarchy that is the
261 // current identifier.
262 void append_name(perm_string);
264 virtual void dump(ostream&) const;
265 virtual unsigned test_width(Design*des, NetScope*scope,
266 unsigned min, unsigned lval,
267 bool&unsized_flag) const;
269 virtual bool elaborate_sig(Design*des, NetScope*scope) const;
271 // Identifiers are allowed (with restrictions) is assign l-values.
272 virtual NetNet* elaborate_lnet(Design*des, NetScope*scope) const;
274 virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
276 // Identifiers are also allowed as procedural assignment l-values.
277 virtual NetAssign_* elaborate_lval(Design*des,
278 NetScope*scope,
279 bool is_force) const;
281 // Structural r-values are OK.
282 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
283 unsigned lwidth,
284 const NetExpr* rise,
285 const NetExpr* fall,
286 const NetExpr* decay,
287 Link::strength_t drive0,
288 Link::strength_t drive1) const;
290 virtual NetExpr*elaborate_expr(Design*des, NetScope*,
291 int expr_width, bool sys_task_arg) const;
292 virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
294 // Elaborate the PEIdent as a port to a module. This method
295 // only applies to Ident expressions.
296 NetNet* elaborate_port(Design*des, NetScope*sc) const;
298 virtual bool is_constant(Module*) const;
299 verinum* eval_const(Design*des, NetScope*sc) const;
301 const pform_name_t& path() const { return path_; }
303 private:
304 pform_name_t path_;
306 private:
307 // Common functions to calculate parts of part/bit selects.
308 bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb) const;
309 bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
311 private:
312 NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
313 bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
314 bool elaborate_lval_net_idx_(Design*, NetScope*, NetAssign_*,
315 index_component_t::ctype_t) const;
317 private:
318 NetExpr*elaborate_expr_param(Design*des,
319 NetScope*scope,
320 const NetExpr*par,
321 NetScope*found,
322 const NetExpr*par_msb,
323 const NetExpr*par_lsb) const;
324 NetExpr*elaborate_expr_net(Design*des,
325 NetScope*scope,
326 NetNet*net,
327 NetScope*found,
328 bool sys_task_arg) const;
329 NetExpr*elaborate_expr_net_word_(Design*des,
330 NetScope*scope,
331 NetNet*net,
332 NetScope*found,
333 bool sys_task_arg) const;
334 NetExpr*elaborate_expr_net_part_(Design*des,
335 NetScope*scope,
336 NetESignal*net,
337 NetScope*found) const;
338 NetExpr*elaborate_expr_net_idx_up_(Design*des,
339 NetScope*scope,
340 NetESignal*net,
341 NetScope*found) const;
342 NetExpr*elaborate_expr_net_idx_do_(Design*des,
343 NetScope*scope,
344 NetESignal*net,
345 NetScope*found) const;
346 NetExpr*elaborate_expr_net_bit_(Design*des,
347 NetScope*scope,
348 NetESignal*net,
349 NetScope*found) const;
351 public:
353 NetNet* elaborate_net_array_(Design*des, NetScope*scope,
354 NetNet*sig, unsigned lwidth,
355 const NetExpr* rise,
356 const NetExpr* fall,
357 const NetExpr* decay,
358 Link::strength_t drive0,
359 Link::strength_t drive1) const;
361 NetNet* elaborate_net_net_(Design*des, NetScope*scope,
362 NetNet*sig, unsigned lwidth,
363 const NetExpr* rise,
364 const NetExpr* fall,
365 const NetExpr* decay,
366 Link::strength_t drive0,
367 Link::strength_t drive1) const;
368 NetNet* elaborate_net_net_idx_up_(Design*des, NetScope*scope,
369 NetNet*sig, unsigned lwidth,
370 const NetExpr* rise,
371 const NetExpr* fall,
372 const NetExpr* decay,
373 Link::strength_t drive0,
374 Link::strength_t drive1) const;
375 NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
376 NetNet*sig,
377 const NetExpr* rise,
378 const NetExpr* fall,
379 const NetExpr* decay,
380 Link::strength_t drive0,
381 Link::strength_t drive1) const;
383 private:
384 NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
385 bool bidirectional_flag) const;
387 NetNet*make_implicit_net_(Design*des, NetScope*scope) const;
389 bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
390 long&midx, long&lidx) const;
391 NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
395 class PENumber : public PExpr {
397 public:
398 explicit PENumber(verinum*vp);
399 ~PENumber();
401 const verinum& value() const;
403 virtual void dump(ostream&) const;
404 virtual unsigned test_width(Design*des, NetScope*scope,
405 unsigned min, unsigned lval,
406 bool&unsized_flag) const;
408 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
409 unsigned lwidth,
410 const NetExpr* rise,
411 const NetExpr* fall,
412 const NetExpr* decay,
413 Link::strength_t drive0,
414 Link::strength_t drive1) const;
415 virtual NetEConst*elaborate_expr(Design*des, NetScope*,
416 int expr_width, bool) const;
417 virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
418 virtual NetAssign_* elaborate_lval(Design*des,
419 NetScope*scope,
420 bool is_force) const;
422 virtual verinum* eval_const(Design*des, NetScope*sc) const;
424 virtual bool is_the_same(const PExpr*that) const;
425 virtual bool is_constant(Module*) const;
427 private:
428 verinum*const value_;
432 * This represents a string constant in an expression.
434 * The s parameter to the PEString constructor is a C string that this
435 * class instance will take for its own. The caller should not delete
436 * the string, the destructor will do it.
438 class PEString : public PExpr {
440 public:
441 explicit PEString(char*s);
442 ~PEString();
444 string value() const;
445 virtual void dump(ostream&) const;
447 virtual unsigned test_width(Design*des, NetScope*scope,
448 unsigned min, unsigned lval,
449 bool&unsized_flag) const;
451 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
452 unsigned width,
453 const NetExpr* rise,
454 const NetExpr* fall,
455 const NetExpr* decay,
456 Link::strength_t drive0,
457 Link::strength_t drive1) const;
458 virtual NetEConst*elaborate_expr(Design*des, NetScope*,
459 int expr_width, bool) const;
460 virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
461 verinum* eval_const(Design*, NetScope*) const;
463 virtual bool is_constant(Module*) const;
465 private:
466 char*text_;
469 class PEUnary : public PExpr {
471 public:
472 explicit PEUnary(char op, PExpr*ex);
473 ~PEUnary();
475 virtual void dump(ostream&out) const;
477 virtual bool elaborate_sig(Design*des, NetScope*scope) const;
479 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
480 unsigned width,
481 const NetExpr* rise,
482 const NetExpr* fall,
483 const NetExpr* decay,
484 Link::strength_t drive0,
485 Link::strength_t drive1) const;
486 virtual NetExpr*elaborate_expr(Design*des, NetScope*,
487 int expr_width, bool sys_task_arg) const;
488 virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
489 virtual verinum* eval_const(Design*des, NetScope*sc) const;
491 virtual bool is_constant(Module*) const;
493 private:
494 NetNet* elab_net_uminus_const_logic_(Design*des, NetScope*scope,
495 NetEConst*expr,
496 unsigned width,
497 const NetExpr* rise,
498 const NetExpr* fall,
499 const NetExpr* decay,
500 Link::strength_t drive0,
501 Link::strength_t drive1) const;
502 NetNet* elab_net_uminus_const_real_(Design*des, NetScope*scope,
503 NetECReal*expr,
504 unsigned width,
505 const NetExpr* rise,
506 const NetExpr* fall,
507 const NetExpr* decay,
508 Link::strength_t drive0,
509 Link::strength_t drive1) const;
510 NetNet* elab_net_unary_real_(Design*des, NetScope*scope,
511 NetExpr*expr,
512 unsigned width,
513 const NetExpr* rise,
514 const NetExpr* fall,
515 const NetExpr* decay,
516 Link::strength_t drive0,
517 Link::strength_t drive1) const;
519 private:
520 char op_;
521 PExpr*expr_;
524 class PEBinary : public PExpr {
526 public:
527 explicit PEBinary(char op, PExpr*l, PExpr*r);
528 ~PEBinary();
530 virtual bool is_constant(Module*) const;
532 virtual void dump(ostream&out) const;
534 virtual unsigned test_width(Design*des, NetScope*scope,
535 unsigned min, unsigned lval,
536 bool&unsized_flag) const;
538 virtual bool elaborate_sig(Design*des, NetScope*scope) const;
540 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
541 unsigned width,
542 const NetExpr* rise,
543 const NetExpr* fall,
544 const NetExpr* decay,
545 Link::strength_t drive0,
546 Link::strength_t drive1) const;
547 virtual NetExpr*elaborate_expr(Design*des, NetScope*,
548 int expr_width, bool sys_task_arg) const;
549 virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
550 virtual verinum* eval_const(Design*des, NetScope*sc) const;
552 protected:
553 char op_;
554 PExpr*left_;
555 PExpr*right_;
557 NetExpr*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
558 NetExpr*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
560 static void suppress_operand_sign_if_needed_(NetExpr*lp, NetExpr*rp);
562 private:
563 NetNet* elaborate_net_add_(Design*des, NetScope*scope,
564 unsigned lwidth,
565 const NetExpr* rise,
566 const NetExpr* fall,
567 const NetExpr* decay) const;
568 NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
569 unsigned lwidth,
570 const NetExpr* rise,
571 const NetExpr* fall,
572 const NetExpr* decay) const;
573 NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
574 unsigned lwidth,
575 const NetExpr* rise,
576 const NetExpr* fall,
577 const NetExpr* decay) const;
578 NetNet* elaborate_net_div_(Design*des, NetScope*scope,
579 unsigned lwidth,
580 const NetExpr* rise,
581 const NetExpr* fall,
582 const NetExpr* decay) const;
583 NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
584 unsigned lwidth,
585 const NetExpr* rise,
586 const NetExpr* fall,
587 const NetExpr* decay) const;
588 NetNet* elaborate_net_log_(Design*des, NetScope*scope,
589 unsigned lwidth,
590 const NetExpr* rise,
591 const NetExpr* fall,
592 const NetExpr* decay) const;
593 NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
594 unsigned lwidth,
595 const NetExpr* rise,
596 const NetExpr* fall,
597 const NetExpr* decay) const;
598 NetNet* elaborate_net_pow_(Design*des, NetScope*scope,
599 unsigned lwidth,
600 const NetExpr* rise,
601 const NetExpr* fall,
602 const NetExpr* decay) const;
603 NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
604 unsigned lwidth,
605 const NetExpr* rise,
606 const NetExpr* fall,
607 const NetExpr* decay) const;
611 * Here are a few specialized classes for handling specific binary
612 * operators.
614 class PEBComp : public PEBinary {
616 public:
617 explicit PEBComp(char op, PExpr*l, PExpr*r);
618 ~PEBComp();
620 virtual unsigned test_width(Design*des, NetScope*scope,
621 unsigned min, unsigned lval,
622 bool&flag) const;
624 NetExpr* elaborate_expr(Design*des, NetScope*scope,
625 int expr_width, bool sys_task_arg) const;
628 class PEBShift : public PEBinary {
630 public:
631 explicit PEBShift(char op, PExpr*l, PExpr*r);
632 ~PEBShift();
634 virtual unsigned test_width(Design*des, NetScope*scope,
635 unsigned min, unsigned lval, bool&flag) const;
639 * This class supports the ternary (?:) operator. The operator takes
640 * three expressions, the test, the true result and the false result.
642 class PETernary : public PExpr {
644 public:
645 explicit PETernary(PExpr*e, PExpr*t, PExpr*f);
646 ~PETernary();
648 virtual bool is_constant(Module*) const;
650 virtual void dump(ostream&out) const;
651 virtual unsigned test_width(Design*des, NetScope*scope,
652 unsigned min, unsigned lval,
653 bool&unsized_flag) const;
655 virtual bool elaborate_sig(Design*des, NetScope*scope) const;
657 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
658 unsigned width,
659 const NetExpr* rise,
660 const NetExpr* fall,
661 const NetExpr* decay,
662 Link::strength_t drive0,
663 Link::strength_t drive1) const;
664 virtual NetETernary*elaborate_expr(Design*des, NetScope*,
665 int expr_width, bool sys_task_arg) const;
666 virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
667 virtual verinum* eval_const(Design*des, NetScope*sc) const;
669 private:
670 PExpr*expr_;
671 PExpr*tru_;
672 PExpr*fal_;
676 * This class represents a parsed call to a function, including calls
677 * to system functions. The parameters in the parms list are the
678 * expressions that are passed as input to the ports of the function.
680 class PECallFunction : public PExpr {
681 public:
682 explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
683 // Call of system function (name is not hierarchical)
684 explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
685 explicit PECallFunction(perm_string n);
686 ~PECallFunction();
688 virtual void dump(ostream &) const;
690 virtual NetNet* elaborate_net(Design*des, NetScope*scope,
691 unsigned width,
692 const NetExpr* rise,
693 const NetExpr* fall,
694 const NetExpr* decay,
695 Link::strength_t drive0,
696 Link::strength_t drive1) const;
697 virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
698 int expr_wid, bool sys_task_arg) const;
700 virtual unsigned test_width(Design*des, NetScope*scope,
701 unsigned min, unsigned lval,
702 bool&unsized_flag) const;
704 private:
705 pform_name_t path_;
706 svector<PExpr *> parms_;
708 bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
710 NetExpr* elaborate_sfunc_(Design*des, NetScope*scope, int expr_wid) const;
711 NetNet* elaborate_net_sfunc_(Design*des, NetScope*scope,
712 unsigned width,
713 const NetExpr* rise,
714 const NetExpr* fall,
715 const NetExpr* decay,
716 Link::strength_t drive0,
717 Link::strength_t drive1) const;
718 unsigned test_width_sfunc_(Design*des, NetScope*scope,
719 unsigned min, unsigned lval,
720 bool&unsized_flag) const;
723 #endif