source: src/AST/Expr.hpp@ 5e8d75bb

stuck-waitfor-destruct
Last change on this file since 5e8d75bb was 17fa94f, checked in by Andrew Beach <ajbeach@…>, 13 months ago

Reworked some nodes so they can be typed or untyped. This allowed me to remove TranslationDeps as the type information is only needed in the candidate finder, which can easily insert it.

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