source: src/AST/Expr.hpp@ 14c31eb

Last change on this file since 14c31eb was b6f2e7ab, checked in by Andrew Beach <ajbeach@…>, 13 months ago

Removed SizeofExpr::expr and AlignofExpr::expr, expressions that would be stored there are wrapped in TypeofType and stored in the type field. Some special cases to hide the typeof in code generation were added. In addition, initializer length is calculated in more cases so that the full type of more arrays is known sooner. Other than that, most of the code changes were just stripping out the conditional code and checks no longer needed. Some tests had to be updated, because the typeof is not hidden in dumps and the resolver replaces known typeof expressions with the type. The extension case caused some concern but it appears that just hides warnings in the expression which no longer exists.

  • Property mode set to 100644
File size: 28.2 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/// A type cast, e.g. `(int)e`
333class CastExpr final : public Expr {
334public:
335 ptr<Expr> arg;
336 GeneratedFlag isGenerated;
337
338 enum CastKind {
339 Default, // C
340 Coerce, // reinterpret cast
341 Return // overload selection
342 };
343
344 CastKind kind = Default;
345
346 CastExpr( const CodeLocation & loc, const Expr * a, const Type * to,
347 GeneratedFlag g = GeneratedCast, CastKind kind = Default ) : 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 = Default );
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
486 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
487private:
488 SizeofExpr * clone() const override { return new SizeofExpr{ *this }; }
489 MUTATE_FRIEND
490};
491
492class CountExpr final : public Expr {
493public:
494 ptr<Expr> expr;
495 ptr<Type> type;
496
497 CountExpr( const CodeLocation & loc, const Expr * t );
498 CountExpr( const CodeLocation & loc, const Type * t );
499
500 const Expr * accept( Visitor & v )const override { return v.visit( this ); }
501private:
502 CountExpr * clone() const override { return new CountExpr( *this ); }
503 MUTATE_FRIEND
504};
505
506/// alignof expression, e.g. `alignof(int)`, `alignof 3+4`
507class AlignofExpr final : public Expr {
508public:
509 ptr<Type> type;
510
511 AlignofExpr( const CodeLocation & loc, const Type * t );
512
513 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
514private:
515 AlignofExpr * clone() const override { return new AlignofExpr{ *this }; }
516 MUTATE_FRIEND
517};
518
519/// offsetof expression before resolver determines field, e.g. `offsetof(MyStruct, myfield)`
520class UntypedOffsetofExpr final : public Expr {
521public:
522 ptr<Type> type;
523 std::string member;
524
525 UntypedOffsetofExpr( const CodeLocation & loc, const Type * ty, const std::string & mem )
526 : Expr( loc ), type( ty ), member( mem ) {}
527
528 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
529private:
530 UntypedOffsetofExpr * clone() const override { return new UntypedOffsetofExpr{ *this }; }
531 MUTATE_FRIEND
532};
533
534/// offsetof expression after resolver determines field, e.g. `offsetof(MyStruct, myfield)`
535class OffsetofExpr final : public Expr {
536public:
537 ptr<Type> type;
538 readonly<DeclWithType> member;
539
540 OffsetofExpr( const CodeLocation & loc, const Type * ty, const DeclWithType * mem );
541
542 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
543private:
544 OffsetofExpr * clone() const override { return new OffsetofExpr{ *this }; }
545 MUTATE_FRIEND
546};
547
548/// a pack of field-offsets for a generic type
549class OffsetPackExpr final : public Expr {
550public:
551 ptr<StructInstType> type;
552
553 OffsetPackExpr( const CodeLocation & loc, const StructInstType * ty );
554
555 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
556private:
557 OffsetPackExpr * clone() const override { return new OffsetPackExpr{ *this }; }
558 MUTATE_FRIEND
559};
560
561/// Variants of short-circuiting logical expression
562enum LogicalFlag { OrExpr, AndExpr };
563
564/// Short-circuiting boolean expression (`&&` or `||`)
565class LogicalExpr final : public Expr {
566public:
567 ptr<Expr> arg1;
568 ptr<Expr> arg2;
569 LogicalFlag isAnd;
570
571 LogicalExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2, LogicalFlag ia );
572
573 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
574private:
575 LogicalExpr * clone() const override { return new LogicalExpr{ *this }; }
576 MUTATE_FRIEND
577};
578
579/// Three-argument conditional e.g. `p ? a : b`
580class ConditionalExpr final : public Expr {
581public:
582 ptr<Expr> arg1;
583 ptr<Expr> arg2;
584 ptr<Expr> arg3;
585
586 ConditionalExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2, const Expr * a3 )
587 : Expr( loc ), arg1( a1 ), arg2( a2 ), arg3( a3 ) {}
588
589 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
590private:
591 ConditionalExpr * clone() const override { return new ConditionalExpr{ *this }; }
592 MUTATE_FRIEND
593};
594
595/// Comma expression e.g. `( a , b )`
596class CommaExpr final : public Expr {
597public:
598 ptr<Expr> arg1;
599 ptr<Expr> arg2;
600
601 CommaExpr( const CodeLocation & loc, const Expr * a1, const Expr * a2 )
602 : Expr( loc ), arg1( a1 ), arg2( a2 ) {
603 this->result = a2->result;
604 }
605
606 bool get_lvalue() const final;
607
608 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
609private:
610 CommaExpr * clone() const override { return new CommaExpr{ *this }; }
611 MUTATE_FRIEND
612};
613
614/// A type used as an expression (e.g. a type generator parameter)
615class TypeExpr final : public Expr {
616public:
617 ptr<Type> type;
618
619 TypeExpr( const CodeLocation & loc, const Type * t ) : Expr(loc), type(t) {}
620
621 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
622private:
623 TypeExpr * clone() const override { return new TypeExpr{ *this }; }
624 MUTATE_FRIEND
625};
626
627/// A name that refers to a generic dimension parameter.
628class DimensionExpr final : public Expr {
629public:
630 std::string name;
631
632 DimensionExpr( const CodeLocation & loc, std::string name )
633 : Expr( loc ), name( name ) {}
634
635 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
636private:
637 DimensionExpr * clone() const override { return new DimensionExpr{ *this }; }
638 MUTATE_FRIEND
639};
640
641/// A GCC "asm constraint operand" used in an asm statement, e.g. `[output] "=f" (result)`.
642/// https://gcc.gnu.org/onlinedocs/gcc-4.7.1/gcc/Machine-Constraints.html#Machine-Constraints
643class AsmExpr final : public Expr {
644public:
645 std::string inout;
646 ptr<Expr> constraint;
647 ptr<Expr> operand;
648
649 AsmExpr( const CodeLocation & loc, const std::string & io, const Expr * con, const Expr * op )
650 : Expr( loc ), inout( io ), constraint( con ), operand( op ) {}
651
652 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
653private:
654 AsmExpr * clone() const override { return new AsmExpr{ *this }; }
655 MUTATE_FRIEND
656};
657
658/// The application of a function to a set of parameters, along with a set of copy constructor
659/// calls, one for each argument
660class ImplicitCopyCtorExpr final : public Expr {
661public:
662 ptr<ApplicationExpr> callExpr;
663
664 ImplicitCopyCtorExpr( const CodeLocation & loc, const ApplicationExpr * call )
665 : Expr( loc, call->result ), callExpr(call) { assert( call ); assert(call->result); }
666
667 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
668private:
669 ImplicitCopyCtorExpr * clone() const override { return new ImplicitCopyCtorExpr{ *this }; }
670 MUTATE_FRIEND
671};
672
673/// Constructor in expression context, e.g. `int * x = alloc() { 42 };`
674class ConstructorExpr final : public Expr {
675public:
676 ptr<Expr> callExpr;
677
678 ConstructorExpr( const CodeLocation & loc, const Expr * call );
679
680 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
681private:
682 ConstructorExpr * clone() const override { return new ConstructorExpr{ *this }; }
683 MUTATE_FRIEND
684};
685
686/// A C99 compound literal, e.g. `(MyType){ a, b, c }`
687class CompoundLiteralExpr final : public Expr {
688public:
689 ptr<Init> init;
690
691 CompoundLiteralExpr( const CodeLocation & loc, const Type * t, const Init * i );
692
693 bool get_lvalue() const final;
694
695 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
696private:
697 CompoundLiteralExpr * clone() const override { return new CompoundLiteralExpr{ *this }; }
698 MUTATE_FRIEND
699};
700
701/// A range, e.g. `3 ... 5` or `1~10`
702class RangeExpr final : public Expr {
703public:
704 ptr<Expr> low;
705 ptr<Expr> high;
706
707 RangeExpr( const CodeLocation & loc, const Expr * l, const Expr * h )
708 : Expr( loc ), low( l ), high( h ) {}
709
710 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
711private:
712 RangeExpr * clone() const override { return new RangeExpr{ *this }; }
713 MUTATE_FRIEND
714};
715
716/// A tuple expression before resolution, e.g. `[a, b, c]`
717class UntypedTupleExpr final : public Expr {
718public:
719 std::vector<ptr<Expr>> exprs;
720
721 UntypedTupleExpr( const CodeLocation & loc, std::vector<ptr<Expr>> && xs )
722 : Expr( loc ), exprs( std::move(xs) ) {}
723
724 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
725private:
726 UntypedTupleExpr * clone() const override { return new UntypedTupleExpr{ *this }; }
727 MUTATE_FRIEND
728};
729
730/// A tuple expression after resolution, e.g. `[a, b, c]`
731class TupleExpr final : public Expr {
732public:
733 std::vector<ptr<Expr>> exprs;
734
735 TupleExpr( const CodeLocation & loc, std::vector<ptr<Expr>> && xs );
736
737 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
738private:
739 TupleExpr * clone() const override { return new TupleExpr{ *this }; }
740 MUTATE_FRIEND
741};
742
743/// An element selection operation on a tuple value, e.g. `t.3` after analysis
744class TupleIndexExpr final : public Expr {
745public:
746 ptr<Expr> tuple;
747 unsigned index;
748
749 TupleIndexExpr( const CodeLocation & loc, const Expr * t, unsigned i );
750
751 bool get_lvalue() const final;
752
753 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
754private:
755 TupleIndexExpr * clone() const override { return new TupleIndexExpr{ *this }; }
756 MUTATE_FRIEND
757};
758
759/// A multiple- or mass-assignment operation, or a tuple ctor/dtor expression.
760/// multiple-assignment: both sides of the assignment have tuple type,
761/// e.g. `[a, b, c] = [d, e, f];`
762/// mass-assignment: left-hand side has tuple type and right-hand side does not:
763/// e.g. `[a, b, c] = 42;`
764class TupleAssignExpr final : public Expr {
765public:
766 ptr<StmtExpr> stmtExpr;
767
768 TupleAssignExpr(
769 const CodeLocation & loc, std::vector<ptr<Expr>> && assigns,
770 std::vector<ptr<ObjectDecl>> && tempDecls );
771
772 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
773
774private:
775 TupleAssignExpr * clone() const override { return new TupleAssignExpr{ *this }; }
776 MUTATE_FRIEND
777};
778
779/// A GCC "statement expression", e.g. `({ int x = 5; x })`
780class StmtExpr final : public Expr {
781public:
782 ptr<CompoundStmt> stmts;
783 std::vector<ptr<ObjectDecl>> returnDecls; ///< return variable(s) for statement expression
784 std::vector<ptr<Expr>> dtors; ///< destructor(s) for return variable(s)
785
786 readonly<ExprStmt> resultExpr;
787
788 StmtExpr( const CodeLocation & loc, const CompoundStmt * ss );
789
790 /// Set the result type of this StmtExpr based on its body
791 void computeResult();
792
793 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
794private:
795 StmtExpr * clone() const override { return new StmtExpr{ *this }; }
796 MUTATE_FRIEND
797};
798
799/// An expression which must only be evaluated once
800class UniqueExpr final : public Expr {
801 static unsigned long long nextId;
802public:
803 ptr<Expr> expr;
804 readonly<ObjectDecl> object;
805 ptr<VariableExpr> var;
806 unsigned long long id;
807
808 UniqueExpr( const CodeLocation & loc, const Expr * e, unsigned long long i = -1ull );
809
810 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
811private:
812 UniqueExpr * clone() const override { return new UniqueExpr{ *this }; }
813 MUTATE_FRIEND
814};
815
816/// One option for resolving an initializer expression
817struct InitAlternative {
818 ptr<Type> type;
819 ptr<Designation> designation;
820
821 InitAlternative() = default;
822 InitAlternative( const Type * ty, const Designation * des ) : type( ty ), designation( des ) {}
823};
824
825/// Pre-resolution initializer expression
826class UntypedInitExpr final : public Expr {
827public:
828 ptr<Expr> expr;
829 std::deque<InitAlternative> initAlts;
830
831 UntypedInitExpr( const CodeLocation & loc, const Expr * e, std::deque<InitAlternative> && as )
832 : Expr( loc ), expr( e ), initAlts( std::move(as) ) {}
833
834 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
835private:
836 UntypedInitExpr * clone() const override { return new UntypedInitExpr{ *this }; }
837 MUTATE_FRIEND
838};
839
840/// Post-resolution initializer expression
841class InitExpr final : public Expr {
842public:
843 ptr<Expr> expr;
844 ptr<Designation> designation;
845
846 InitExpr( const CodeLocation & loc, const Expr * e, const Designation * des )
847 : Expr( loc, e->result ), expr( e ), designation( des ) {}
848
849 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
850private:
851 InitExpr * clone() const override { return new InitExpr{ *this }; }
852 MUTATE_FRIEND
853};
854
855/// Expression containing a deleted identifier.
856/// Internal to resolver.
857class DeletedExpr final : public Expr {
858public:
859 ptr<Expr> expr;
860 readonly<Decl> deleteStmt;
861
862 DeletedExpr( const CodeLocation & loc, const Expr * e, const Decl * del )
863 : Expr( loc, e->result ), expr( e ), deleteStmt( del ) { assert( expr->result ); }
864
865 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
866private:
867 DeletedExpr * clone() const override { return new DeletedExpr{ *this }; }
868 MUTATE_FRIEND
869};
870
871/// Use of a default argument.
872/// Internal to resolver.
873class DefaultArgExpr final : public Expr {
874public:
875 ptr<Expr> expr;
876
877 DefaultArgExpr( const CodeLocation & loc, const Expr * e )
878 : Expr( loc, e->result ), expr( e ) { assert( e->result ); }
879
880 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
881private:
882 DefaultArgExpr * clone() const override { return new DefaultArgExpr{ *this }; }
883 MUTATE_FRIEND
884};
885
886/// C11 _Generic expression
887class GenericExpr final : public Expr {
888public:
889 /// One arm of the _Generic expr
890 struct Association {
891 ptr<Type> type;
892 ptr<Expr> expr;
893
894 Association() = default;
895 // default case
896 Association( const Expr * e ) : type(), expr( e ) {}
897 // non-default case
898 Association( const Type * t, const Expr * e ) : type( t ), expr( e ) {}
899 };
900
901 ptr<Expr> control;
902 std::vector<Association> associations;
903
904 GenericExpr( const CodeLocation & loc, const Expr * ctrl, std::vector<Association> && assns )
905 : Expr( loc ), control( ctrl ), associations( std::move(assns) ) {}
906
907 const Expr * accept( Visitor & v ) const override { return v.visit( this ); }
908private:
909 GenericExpr * clone() const override { return new GenericExpr{ *this }; }
910 MUTATE_FRIEND
911};
912
913}
914
915#undef MUTATE_FRIEND
916
917// Local Variables: //
918// tab-width: 4 //
919// mode: c++ //
920// compile-command: "make install" //
921// End: //
Note: See TracBrowser for help on using the repository browser.