source: src/AST/Expr.hpp @ f5dbc8d

Last change on this file since f5dbc8d was b6f2e7ab, checked in by Andrew Beach <ajbeach@…>, 39 hours 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.