source: src/AST/Expr.hpp@ 79c907b

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 79c907b was aebf5b0, checked in by Andrew Beach <ajbeach@…>, 5 years ago

Made a few changes that should have no effect but will silence some warnings.

  • Property mode set to 100644
File size: 26.6 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// Expr.hpp --
8//
9// Author : Aaron B. Moss
10// Created On : Fri May 10 10:30:00 2019
11// Last Modified By : Peter A. Buhr
12// Created On : Fri May 10 10:30:00 2019
13// Update Count : 7
14//
15
16#pragma once
17
18#include <cassert>
19#include <deque>
20#include <map>
21#include <string>
22#include <utility> // for move
23#include <vector>
24#include <optional>
25
26#include "Fwd.hpp" // for UniqueId
27#include "Label.hpp"
28#include "Decl.hpp"
29#include "ParseNode.hpp"
30#include "Visitor.hpp"
31
32// Must be included in *all* AST classes; should be #undef'd at the end of the file
33#define MUTATE_FRIEND \
34 template<typename node_t> friend node_t * mutate(const node_t * node); \
35 template<typename node_t> friend node_t * shallowCopy(const node_t * node);
36
37
38class ConverterOldToNew;
39class ConverterNewToOld;
40
41namespace ast {
42
43/// Contains the ID of a declaration and a type that is derived from that declaration,
44/// but subject to decay-to-pointer and type parameter renaming
45struct ParamEntry {
46 UniqueId decl;
47 ptr<Decl> declptr;
48 ptr<Type> actualType;
49 ptr<Type> formalType;
50 ptr<Expr> expr;
51
52 ParamEntry() : decl( 0 ), declptr( nullptr ), actualType( nullptr ), formalType( nullptr ), expr( nullptr ) {}
53 ParamEntry(
54 UniqueId id, const Decl * declptr, const Type * actual, const Type * formal,
55 const Expr * e )
56 : decl( id ), declptr( declptr ), actualType( actual ), formalType( formal ), expr( e ) {}
57};
58
59/// Pre-resolution list of parameters to infer
60using ResnSlots = std::vector<UniqueId>;
61/// Post-resolution map of inferred parameters
62using InferredParams = std::map< UniqueId, ParamEntry >;
63
64/// Base node for expressions
65class Expr : public ParseNode {
66public:
67 /// Saves space (~16 bytes) by combining ResnSlots and InferredParams
68 struct InferUnion {
69 enum { Empty, Slots, Params } mode;
70 union data_t {
71 char def;
72 ResnSlots resnSlots;
73 InferredParams inferParams;
74
75 data_t() : def('\0') {}
76 ~data_t() {}
77 } data;
78
79 /// initializes from other InferUnion
80 void init_from( const InferUnion& o ) {
81 switch ( o.mode ) {
82 case Empty: return;
83 case Slots: new(&data.resnSlots) ResnSlots{ o.data.resnSlots }; return;
84 case Params: new(&data.inferParams) InferredParams{ o.data.inferParams }; return;
85 }
86 }
87
88 /// initializes from other InferUnion (move semantics)
89 void init_from( InferUnion&& o ) {
90 switch ( o.mode ) {
91 case Empty: return;
92 case Slots: new(&data.resnSlots) ResnSlots{ std::move(o.data.resnSlots) }; return;
93 case Params:
94 new(&data.inferParams) InferredParams{ std::move(o.data.inferParams) }; return;
95 }
96 }
97
98 /// clears variant fields
99 void reset() {
100 switch( mode ) {
101 case Empty: return;
102 case Slots: data.resnSlots.~ResnSlots(); return;
103 case Params: data.inferParams.~InferredParams(); return;
104 }
105 }
106
107 InferUnion() : mode(Empty), data() {}
108 InferUnion( const InferUnion& o ) : mode( o.mode ), data() { init_from( o ); }
109 InferUnion( InferUnion&& o ) : mode( o.mode ), data() { init_from( std::move(o) ); }
110 InferUnion& operator= ( const InferUnion& ) = delete;
111 InferUnion& operator= ( InferUnion&& ) = delete;
112 ~InferUnion() { reset(); }
113
114 ResnSlots& resnSlots() {
115 switch (mode) {
116 case Empty: new(&data.resnSlots) ResnSlots{}; mode = Slots; [[fallthrough]];
117 case Slots: return data.resnSlots;
118 case Params: assertf(false, "Cannot return to resnSlots from Params"); abort();
119 }
120 assertf(false, "unreachable");
121 }
122
123 const ResnSlots& resnSlots() const {
124 if (mode == Slots) {
125 return data.resnSlots;
126 }
127 assertf(false, "Mode was not already resnSlots");
128 abort();
129 }
130
131 InferredParams& inferParams() {
132 switch (mode) {
133 case Slots: data.resnSlots.~ResnSlots(); [[fallthrough]];
134 case Empty: new(&data.inferParams) InferredParams{}; mode = Params; [[fallthrough]];
135 case Params: return data.inferParams;
136 }
137 assertf(false, "unreachable");
138 }
139
140 const InferredParams& inferParams() const {
141 if (mode == Params) {
142 return data.inferParams;
143 }
144 assertf(false, "Mode was not already Params");
145 abort();
146 }
147
148 void set_inferParams( InferredParams && ps ) {
149 switch(mode) {
150 case Slots:
151 data.resnSlots.~ResnSlots();
152 [[fallthrough]];
153 case Empty:
154 new(&data.inferParams) InferredParams{ std::move( ps ) };
155 mode = Params;
156 break;
157 case Params:
158 data.inferParams = std::move( ps );
159 break;
160 }
161 }
162
163 /// splices other InferUnion into this one. Will fail if one union is in `Slots` mode
164 /// and the other is in `Params`.
165 void splice( InferUnion && o ) {
166 if ( o.mode == Empty ) return;
167 if ( mode == Empty ) { init_from( o ); return; }
168 assert( mode == o.mode && "attempt to splice incompatible InferUnion" );
169
170 if ( mode == Slots ){
171 data.resnSlots.insert(
172 data.resnSlots.end(), o.data.resnSlots.begin(), o.data.resnSlots.end() );
173 } else if ( mode == Params ) {
174 for ( const auto & p : o.data.inferParams ) {
175 data.inferParams[p.first] = std::move(p.second);
176 }
177 } else assertf(false, "invalid mode");
178 }
179 };
180
181 ptr<Type> result;
182 ptr<TypeSubstitution> env;
183 InferUnion inferred;
184 bool extension = false;
185
186 Expr( const CodeLocation & loc, const Type * res = nullptr )
187 : ParseNode( loc ), result( res ), env(), inferred() {}
188
189 Expr * set_extension( bool ex ) { extension = ex; return this; }
190 virtual bool get_lvalue() const;
191
192 virtual const Expr * accept( Visitor & v ) const override = 0;
193private:
194 Expr * clone() const override = 0;
195 MUTATE_FRIEND
196};
197
198/// The application of a function to a set of parameters.
199/// Post-resolver form of `UntypedExpr`
200class ApplicationExpr final : public Expr {
201public:
202 ptr<Expr> func;
203 std::vector<ptr<Expr>> args;
204
205 ApplicationExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} );
206
207 bool get_lvalue() const final;
208
209 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
210private:
211 ApplicationExpr * clone() const override { return new ApplicationExpr{ *this }; }
212 MUTATE_FRIEND
213};
214
215/// The application of a function to a set of parameters, pre-overload resolution.
216class UntypedExpr final : public Expr {
217public:
218 ptr<Expr> func;
219 std::vector<ptr<Expr>> args;
220
221 UntypedExpr( const CodeLocation & loc, const Expr * f, std::vector<ptr<Expr>> && as = {} )
222 : Expr( loc ), func( f ), args( std::move(as) ) {}
223
224 bool get_lvalue() const final;
225
226 /// Creates a new dereference expression
227 static UntypedExpr * createDeref( const CodeLocation & loc, Expr * arg );
228 /// Creates a new assignment expression
229 static UntypedExpr * createAssign( const CodeLocation & loc, Expr * lhs, Expr * rhs );
230
231 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
232private:
233 UntypedExpr * clone() const override { return new UntypedExpr{ *this }; }
234 MUTATE_FRIEND
235};
236
237/// A name whose name is as-yet undetermined.
238/// May also be used to avoid name mangling in codegen phase.
239class NameExpr final : public Expr {
240public:
241 std::string name;
242
243 NameExpr( const CodeLocation & loc, const std::string & n ) : Expr( loc ), name( n ) {}
244
245 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
246private:
247 NameExpr * clone() const override { return new NameExpr{ *this }; }
248 MUTATE_FRIEND
249};
250
251/// Address-of expression `&e`
252class AddressExpr final : public Expr {
253public:
254 ptr<Expr> arg;
255
256 AddressExpr( const CodeLocation & loc, const Expr * a );
257
258 /// Generate AddressExpr wrapping given expression at same location
259 AddressExpr( const Expr * a ) : AddressExpr( a->location, a ) {}
260
261 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
262private:
263 AddressExpr * clone() const override { return new AddressExpr{ *this }; }
264 MUTATE_FRIEND
265};
266
267/// GCC &&label
268/// https://gcc.gnu.org/onlinedocs/gcc-3.4.2/gcc/Labels-as-Values.html
269class LabelAddressExpr final : public Expr {
270public:
271 Label arg;
272
273 LabelAddressExpr( const CodeLocation & loc, Label && a );
274
275 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
276private:
277 LabelAddressExpr * clone() const override { return new LabelAddressExpr{ *this }; }
278 MUTATE_FRIEND
279};
280
281/// Whether a cast existed in the program source or not
282enum GeneratedFlag { ExplicitCast, GeneratedCast };
283
284/// A type cast, e.g. `(int)e`
285class CastExpr final : public Expr {
286public:
287 ptr<Expr> arg;
288 GeneratedFlag isGenerated;
289
290 CastExpr( const CodeLocation & loc, const Expr * a, const Type * to,
291 GeneratedFlag g = GeneratedCast ) : Expr( loc, to ), arg( a ), isGenerated( g ) {}
292 /// Cast-to-void
293 CastExpr( const CodeLocation & loc, const Expr * a, GeneratedFlag g = GeneratedCast );
294
295 /// Wrap a cast expression around an existing expression (always generated)
296 CastExpr( const Expr * a, const Type * to ) : CastExpr( a->location, a, to, GeneratedCast ) {}
297
298 /// Wrap a cast-to-void expression around an existing expression (always generated)
299 CastExpr( const Expr * a ) : CastExpr( a->location, a, GeneratedCast ) {}
300
301 bool get_lvalue() const final;
302
303 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
304private:
305 CastExpr * clone() const override { return new CastExpr{ *this }; }
306 MUTATE_FRIEND
307};
308
309/// A cast to "keyword types", e.g. `(thread &)t`
310class KeywordCastExpr final : public Expr {
311public:
312 ptr<Expr> arg;
313 ast::AggregateDecl::Aggregate target;
314
315 KeywordCastExpr( const CodeLocation & loc, const Expr * a, ast::AggregateDecl::Aggregate t )
316 : Expr( loc ), arg( a ), target( t ) {}
317
318 /// Get a name for the target type
319 const char * targetString() const;
320
321 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
322private:
323 KeywordCastExpr * clone() const override { return new KeywordCastExpr{ *this }; }
324 MUTATE_FRIEND
325};
326
327/// A virtual dynamic cast, e.g. `(virtual exception)e`
328class VirtualCastExpr final : public Expr {
329public:
330 ptr<Expr> arg;
331
332 VirtualCastExpr( const CodeLocation & loc, const Expr * a, const Type * to )
333 : Expr( loc, to ), arg( a ) {}
334
335 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
336private:
337 VirtualCastExpr * clone() const override { return new VirtualCastExpr{ *this }; }
338 MUTATE_FRIEND
339};
340
341/// A member selection operation before expression resolution, e.g. `q.p`
342class UntypedMemberExpr final : public Expr {
343public:
344 ptr<Expr> member;
345 ptr<Expr> aggregate;
346
347 UntypedMemberExpr( const CodeLocation & loc, const Expr * mem, const Expr * agg )
348 : Expr( loc ), member( mem ), aggregate( agg ) { assert( aggregate ); }
349
350 bool get_lvalue() const final;
351
352 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
353private:
354 UntypedMemberExpr * clone() const override { return new UntypedMemberExpr{ *this }; }
355 MUTATE_FRIEND
356};
357
358/// A member selection operation after expression resolution, e.g. `q.p`
359class MemberExpr final : public Expr {
360public:
361 readonly<DeclWithType> member;
362 ptr<Expr> aggregate;
363
364 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg );
365
366 bool get_lvalue() const final;
367
368 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
369private:
370 MemberExpr * clone() const override { return new MemberExpr{ *this }; }
371 MUTATE_FRIEND
372
373 // Custructor overload meant only for AST conversion
374 enum NoOpConstruction { NoOpConstructionChosen };
375 MemberExpr( const CodeLocation & loc, const DeclWithType * mem, const Expr * agg,
376 NoOpConstruction overloadSelector );
377 friend class ::ConverterOldToNew;
378 friend class ::ConverterNewToOld;
379};
380
381/// A reference to a named variable.
382class VariableExpr final : public Expr {
383public:
384 readonly<DeclWithType> var;
385
386 VariableExpr( const CodeLocation & loc );
387 VariableExpr( const CodeLocation & loc, const DeclWithType * v );
388
389 bool get_lvalue() const final;
390
391 /// generates a function pointer for a given function
392 static VariableExpr * functionPointer( const CodeLocation & loc, const FunctionDecl * decl );
393
394 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
395private:
396 VariableExpr * clone() const override { return new VariableExpr{ *this }; }
397 MUTATE_FRIEND
398};
399
400/// A compile-time constant.
401/// Mostly carries C-source text from parse to code-gen, without interpretation. E.g. strings keep their outer quotes and never have backslashes interpreted.
402/// Integer constants get special treatment, e.g. for verifying array operations, when an integer constant occurs as the length of an array.
403class ConstantExpr final : public Expr {
404public:
405 // Representation of this constant, as it occurs in .cfa source and .cfa.cc result.
406 std::string rep;
407
408 ConstantExpr(
409 const CodeLocation & loc, const Type * ty, const std::string & r,
410 std::optional<unsigned long long> i )
411 : Expr( loc, ty ), rep( r ), ival( i ) {}
412
413 /// Gets the integer value of this constant, if one is appropriate to its type.
414 /// Throws a SemanticError if the type is not appropriate for value-as-integer.
415 /// Suffers an assertion failure the type is appropriate but no integer value was supplied to the constructor.
416 long long int intValue() const;
417
418 /// generates a boolean constant of the given bool
419 static ConstantExpr * from_bool( const CodeLocation & loc, bool b );
420 /// generates an integer constant of the given int
421 static ConstantExpr * from_int( const CodeLocation & loc, int i );
422 /// generates an integer constant of the given unsigned long int
423 static ConstantExpr * from_ulong( const CodeLocation & loc, unsigned long i );
424 /// generates a null pointer value for the given type. void * if omitted.
425 static ConstantExpr * null( const CodeLocation & loc, const Type * ptrType = nullptr );
426
427 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
428private:
429 ConstantExpr * clone() const override { return new ConstantExpr{ *this }; }
430 MUTATE_FRIEND
431
432 std::optional<unsigned long long> ival;
433
434 // Intended only for legacy support of roundtripping the old AST.
435 // Captures the very-locally inferred type, before the resolver modifies the type of this ConstantExpression.
436 // In the old AST it's constExpr->constant.type
437 ptr<Type> underlyer;
438 friend class ::ConverterOldToNew;
439 friend class ::ConverterNewToOld;
440};
441
442/// sizeof expression, e.g. `sizeof(int)`, `sizeof 3+4`
443class SizeofExpr final : public Expr {
444public:
445 ptr<Expr> expr;
446 ptr<Type> type;
447
448 SizeofExpr( const CodeLocation & loc, const Expr * e );
449 SizeofExpr( const CodeLocation & loc, const Type * t );
450 // deliberately no disambiguating overload for nullptr_t
451
452 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
453private:
454 SizeofExpr * clone() const override { return new SizeofExpr{ *this }; }
455 MUTATE_FRIEND
456};
457
458/// alignof expression, e.g. `alignof(int)`, `alignof 3+4`
459class AlignofExpr final : public Expr {
460public:
461 ptr<Expr> expr;
462 ptr<Type> type;
463
464 AlignofExpr( const CodeLocation & loc, const Expr * e );
465 AlignofExpr( const CodeLocation & loc, const Type * t );
466 // deliberately no disambiguating overload for nullptr_t
467
468 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
469private:
470 AlignofExpr * clone() const override { return new AlignofExpr{ *this }; }
471 MUTATE_FRIEND
472};
473
474/// offsetof expression before resolver determines field, e.g. `offsetof(MyStruct, myfield)`
475class UntypedOffsetofExpr final : public Expr {
476public:
477 ptr<Type> type;
478 std::string member;
479
480 UntypedOffsetofExpr( const CodeLocation & loc, const Type * ty, const std::string & mem )
481 : Expr( loc ), type( ty ), member( mem ) {}
482
483 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
484private:
485 UntypedOffsetofExpr * clone() const override { return new UntypedOffsetofExpr{ *this }; }
486 MUTATE_FRIEND
487};
488
489/// offsetof expression after resolver determines field, e.g. `offsetof(MyStruct, myfield)`
490class OffsetofExpr final : public Expr {
491public:
492 ptr<Type> type;
493 readonly<DeclWithType> member;
494
495 OffsetofExpr( const CodeLocation & loc, const Type * ty, const DeclWithType * mem );
496
497 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
498private:
499 OffsetofExpr * clone() const override { return new OffsetofExpr{ *this }; }
500 MUTATE_FRIEND
501};
502
503/// a pack of field-offsets for a generic type
504class OffsetPackExpr final : public Expr {
505public:
506 ptr<StructInstType> type;
507
508 OffsetPackExpr( const CodeLocation & loc, const StructInstType * ty );
509
510 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
511private:
512 OffsetPackExpr * clone() const override { return new OffsetPackExpr{ *this }; }
513 MUTATE_FRIEND
514};
515
516/// Variants of short-circuiting logical expression
517enum LogicalFlag { OrExpr, AndExpr };
518
519/// Short-circuiting boolean expression (`&&` or `||`)
520class LogicalExpr final : public Expr {
521public:
522 ptr<Expr> arg1;
523 ptr<Expr> arg2;
524 LogicalFlag isAnd;
525
526 LogicalExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia );
527
528 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
529private:
530 LogicalExpr * clone() const override { return new LogicalExpr{ *this }; }
531 MUTATE_FRIEND
532};
533
534/// Three-argument conditional e.g. `p ? a : b`
535class ConditionalExpr final : public Expr {
536public:
537 ptr<Expr> arg1;
538 ptr<Expr> arg2;
539 ptr<Expr> arg3;
540
541 ConditionalExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2, const Expr * a3 )
542 : Expr( loc ), arg1( a1 ), arg2( a2 ), arg3( a3 ) {}
543
544 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
545private:
546 ConditionalExpr * clone() const override { return new ConditionalExpr{ *this }; }
547 MUTATE_FRIEND
548};
549
550/// Comma expression e.g. `( a , b )`
551class CommaExpr final : public Expr {
552public:
553 ptr<Expr> arg1;
554 ptr<Expr> arg2;
555
556 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
557 : Expr( loc ), arg1( a1 ), arg2( a2 ) {
558 this->result = a2->result;
559 }
560
561 bool get_lvalue() const final;
562
563 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
564private:
565 CommaExpr * clone() const override { return new CommaExpr{ *this }; }
566 MUTATE_FRIEND
567};
568
569/// A type used as an expression (e.g. a type generator parameter)
570class TypeExpr final : public Expr {
571public:
572 ptr<Type> type;
573
574 TypeExpr( const CodeLocation & loc, const Type * t ) : Expr(loc), type(t) {}
575
576 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
577private:
578 TypeExpr * clone() const override { return new TypeExpr{ *this }; }
579 MUTATE_FRIEND
580};
581
582/// A GCC "asm constraint operand" used in an asm statement, e.g. `[output] "=f" (result)`.
583/// https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
584class AsmExpr final : public Expr {
585public:
586 std::string inout;
587 ptr<Expr> constraint;
588 ptr<Expr> operand;
589
590 AsmExpr( const CodeLocation & loc, const std::string & io, const Expr * con, const Expr * op )
591 : Expr( loc ), inout( io ), constraint( con ), operand( op ) {}
592
593 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
594private:
595 AsmExpr * clone() const override { return new AsmExpr{ *this }; }
596 MUTATE_FRIEND
597};
598
599/// The application of a function to a set of parameters, along with a set of copy constructor
600/// calls, one for each argument
601class ImplicitCopyCtorExpr final : public Expr {
602public:
603 ptr<ApplicationExpr> callExpr;
604
605 ImplicitCopyCtorExpr( const CodeLocation& loc, const ApplicationExpr * call )
606 : Expr( loc, call->result ) { assert( call ); }
607
608 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
609private:
610 ImplicitCopyCtorExpr * clone() const override { return new ImplicitCopyCtorExpr{ *this }; }
611 MUTATE_FRIEND
612};
613
614/// Constructor in expression context, e.g. `int * x = alloc() { 42 };`
615class ConstructorExpr final : public Expr {
616public:
617 ptr<Expr> callExpr;
618
619 ConstructorExpr( const CodeLocation & loc, const Expr * call );
620
621 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
622private:
623 ConstructorExpr * clone() const override { return new ConstructorExpr{ *this }; }
624 MUTATE_FRIEND
625};
626
627/// A C99 compound literal, e.g. `(MyType){ a, b, c }`
628class CompoundLiteralExpr final : public Expr {
629public:
630 ptr<Init> init;
631
632 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
633
634 bool get_lvalue() const final;
635
636 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
637private:
638 CompoundLiteralExpr * clone() const override { return new CompoundLiteralExpr{ *this }; }
639 MUTATE_FRIEND
640};
641
642/// A range, e.g. `3 ... 5` or `1~10`
643class RangeExpr final : public Expr {
644public:
645 ptr<Expr> low;
646 ptr<Expr> high;
647
648 RangeExpr( const CodeLocation & loc, const Expr * l, const Expr * h )
649 : Expr( loc ), low( l ), high( h ) {}
650
651 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
652private:
653 RangeExpr * clone() const override { return new RangeExpr{ *this }; }
654 MUTATE_FRIEND
655};
656
657/// A tuple expression before resolution, e.g. `[a, b, c]`
658class UntypedTupleExpr final : public Expr {
659public:
660 std::vector<ptr<Expr>> exprs;
661
662 UntypedTupleExpr( const CodeLocation & loc, std::vector<ptr<Expr>> && xs )
663 : Expr( loc ), exprs( std::move(xs) ) {}
664
665 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
666private:
667 UntypedTupleExpr * clone() const override { return new UntypedTupleExpr{ *this }; }
668 MUTATE_FRIEND
669};
670
671/// A tuple expression after resolution, e.g. `[a, b, c]`
672class TupleExpr final : public Expr {
673public:
674 std::vector<ptr<Expr>> exprs;
675
676 TupleExpr( const CodeLocation & loc, std::vector<ptr<Expr>> && xs );
677
678 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
679private:
680 TupleExpr * clone() const override { return new TupleExpr{ *this }; }
681 MUTATE_FRIEND
682};
683
684/// An element selection operation on a tuple value, e.g. `t.3` after analysis
685class TupleIndexExpr final : public Expr {
686public:
687 ptr<Expr> tuple;
688 unsigned index;
689
690 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
691
692 bool get_lvalue() const final;
693
694 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
695private:
696 TupleIndexExpr * clone() const override { return new TupleIndexExpr{ *this }; }
697 MUTATE_FRIEND
698};
699
700/// A multiple- or mass-assignment operation, or a tuple ctor/dtor expression.
701/// multiple-assignment: both sides of the assignment have tuple type,
702/// e.g. `[a, b, c] = [d, e, f];`
703/// mass-assignment: left-hand side has tuple type and right-hand side does not:
704/// e.g. `[a, b, c] = 42;`
705class TupleAssignExpr final : public Expr {
706public:
707 ptr<StmtExpr> stmtExpr;
708
709 TupleAssignExpr(
710 const CodeLocation & loc, std::vector<ptr<Expr>> && assigns,
711 std::vector<ptr<ObjectDecl>> && tempDecls );
712
713 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
714
715 friend class ::ConverterOldToNew;
716
717private:
718 TupleAssignExpr * clone() const override { return new TupleAssignExpr{ *this }; }
719 TupleAssignExpr( const CodeLocation & loc, const Type * result, const StmtExpr * s );
720
721 MUTATE_FRIEND
722};
723
724/// A GCC "statement expression", e.g. `({ int x = 5; x })`
725class StmtExpr final : public Expr {
726public:
727 ptr<CompoundStmt> stmts;
728 std::vector<ptr<ObjectDecl>> returnDecls; ///< return variable(s) for statement expression
729 std::vector<ptr<Expr>> dtors; ///< destructor(s) for return variable(s)
730
731 StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
732
733 /// Set the result type of this StmtExpr based on its body
734 void computeResult();
735
736 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
737private:
738 StmtExpr * clone() const override { return new StmtExpr{ *this }; }
739 MUTATE_FRIEND
740};
741
742/// An expression which must only be evaluated once
743class UniqueExpr final : public Expr {
744 static unsigned long long nextId;
745public:
746 ptr<Expr> expr;
747 ptr<ObjectDecl> object;
748 ptr<VariableExpr> var;
749 unsigned long long id;
750
751 UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i = -1ull );
752
753 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
754private:
755 UniqueExpr * clone() const override { return new UniqueExpr{ *this }; }
756 MUTATE_FRIEND
757};
758
759/// One option for resolving an initializer expression
760struct InitAlternative {
761 ptr<Type> type;
762 ptr<Designation> designation;
763
764 InitAlternative() = default;
765 InitAlternative( const Type * ty, const Designation * des ) : type( ty ), designation( des ) {}
766};
767
768/// Pre-resolution initializer expression
769class UntypedInitExpr final : public Expr {
770public:
771 ptr<Expr> expr;
772 std::deque<InitAlternative> initAlts;
773
774 UntypedInitExpr( const CodeLocation & loc, const Expr * e, std::deque<InitAlternative> && as )
775 : Expr( loc ), expr( e ), initAlts( std::move(as) ) {}
776
777 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
778private:
779 UntypedInitExpr * clone() const override { return new UntypedInitExpr{ *this }; }
780 MUTATE_FRIEND
781};
782
783/// Post-resolution initializer expression
784class InitExpr final : public Expr {
785public:
786 ptr<Expr> expr;
787 ptr<Designation> designation;
788
789 InitExpr( const CodeLocation & loc, const Expr * e, const Designation * des )
790 : Expr( loc, e->result ), expr( e ), designation( des ) {}
791
792 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
793private:
794 InitExpr * clone() const override { return new InitExpr{ *this }; }
795 MUTATE_FRIEND
796};
797
798/// Expression containing a deleted identifier.
799/// Internal to resolver.
800class DeletedExpr final : public Expr {
801public:
802 ptr<Expr> expr;
803 readonly<Decl> deleteStmt;
804
805 DeletedExpr( const CodeLocation & loc, const Expr * e, const Decl * del )
806 : Expr( loc, e->result ), expr( e ), deleteStmt( del ) { assert( expr->result ); }
807
808 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
809private:
810 DeletedExpr * clone() const override { return new DeletedExpr{ *this }; }
811 MUTATE_FRIEND
812};
813
814/// Use of a default argument.
815/// Internal to resolver.
816class DefaultArgExpr final : public Expr {
817public:
818 ptr<Expr> expr;
819
820 DefaultArgExpr( const CodeLocation & loc, const Expr * e )
821 : Expr( loc, e->result ), expr( e ) { assert( e->result ); }
822
823 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
824private:
825 DefaultArgExpr * clone() const override { return new DefaultArgExpr{ *this }; }
826 MUTATE_FRIEND
827};
828
829/// C11 _Generic expression
830class GenericExpr final : public Expr {
831public:
832 /// One arm of the _Generic expr
833 struct Association {
834 ptr<Type> type;
835 ptr<Expr> expr;
836
837 Association() = default;
838 // default case
839 Association( const Expr * e ) : type(), expr( e ) {}
840 // non-default case
841 Association( const Type * t, const Expr * e ) : type( t ), expr( e ) {}
842 };
843
844 ptr<Expr> control;
845 std::vector<Association> associations;
846
847 GenericExpr( const CodeLocation & loc, const Expr * ctrl, std::vector<Association> && assns )
848 : Expr( loc ), control( ctrl ), associations( std::move(assns) ) {}
849
850 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
851private:
852 GenericExpr * clone() const override { return new GenericExpr{ *this }; }
853 MUTATE_FRIEND
854};
855
856
857}
858
859#undef MUTATE_FRIEND
860
861// Local Variables: //
862// tab-width: 4 //
863// mode: c++ //
864// compile-command: "make install" //
865// End: //
Note: See TracBrowser for help on using the repository browser.