source: src/AST/Type.hpp @ 9e1d485

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 9e1d485 was 9e1d485, checked in by Aaron Moss <a3moss@…>, 5 years ago

First draft of ast::Type with subclasses

  • Property mode set to 100644
File size: 19.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// Type.hpp --
8//
9// Author           : Aaron B. Moss
10// Created On       : Thu May 9 10:00:00 2019
11// Last Modified By : Aaron B. Moss
12// Last Modified On : Thu May 9 10:00:00 2019
13// Update Count     : 1
14//
15
16#pragma once
17
18#include <cassert>
19#include <cstddef>           // for nullptr_t
20#include <cstdint>           // for uintptr_t
21#include <utility>           // for move
22#include <vector>
23
24#include "CVQualifiers.hpp"
25#include "Fwd.hpp"
26#include "Node.hpp"          // for Node, ptr
27#include "TypeVar.hpp"
28#include "Visitor.hpp"
29
30namespace ast {
31
32class Type : public Node {
33        CV::Qualifiers tq;
34public:
35        Type( CV::Qualifiers q = {} ) : tq(q) {}
36
37        CV::Qualifiers qualifiers() const { return tq; }
38        bool is_const() const { return tq.is_const; }
39        bool is_volatile() const { return tq.is_volatile; }
40        bool is_restrict() const { return tq.is_restrict; }
41        bool is_lvalue() const { return tq.is_lvalue; }
42        bool is_mutex() const { return tq.is_mutex; }
43        bool is_atomic() const { return tq.is_atomic; }
44
45        void set_qualifiers( CV::Qualifiers q ) { tq = q; }
46        void set_const( bool v ) { tq.is_const = v; }
47        void set_restrict( bool v ) { tq.is_restrict = v; }
48        void set_lvalue( bool v ) { tq.is_lvalue = v; }
49        void set_mutex( bool v ) { tq.is_mutex = v; }
50        void set_atomic( bool v ) { tq.is_atomic = v; }
51
52        /// How many elemental types are represented by this type
53        virtual unsigned size() const { return 1; }
54        /// Is this a void type?
55        virtual bool isVoid() const { return size() == 0; }
56        /// Get the i'th component of this type
57        virtual const Type * getComponent( unsigned i );
58
59        /// type without outer pointers and arrays
60        const Type * stripDeclarator();
61        /// type without outer references
62        const Type * stripReferences();
63        /// number of reference occuring consecutively on the outermost layer of this type
64        /// (i.e. do not count references nested within other types)
65        virtual unsigned referenceDepth() const { return 0; }
66        /// true iff type is complete type (i.e. compiler knows the size, alignment, and layout)
67        virtual bool isComplete() const { return true; }
68
69        virtual Type * accept( Visitor & v ) override = 0;
70private:
71        virtual Type * clone() const override = 0;
72};
73
74/// `void`
75class VoidType final : public Type {
76public:
77        VoidType( CV::Qualifiers q = {} ) : Type( q ) {}
78       
79        unsigned size() const override { return 0; }
80        bool isVoid() const override { return true; }
81        bool isComplete() const override { return false; }
82
83        Type * accept( Visitor & v ) override { return v.visit( this ); }
84private:
85        VoidType * clone() const override { return new VoidType{ *this }; }
86};
87
88/// Built-in arithmetic type
89class BasicType final : public Type {
90public:
91        // GENERATED START, DO NOT EDIT
92        // GENERATED BY BasicTypes-gen.cc
93        enum Kind {
94                Bool,
95                Char,
96                SignedChar,
97                UnsignedChar,
98                ShortSignedInt,
99                ShortUnsignedInt,
100                SignedInt,
101                UnsignedInt,
102                LongSignedInt,
103                LongUnsignedInt,
104                LongLongSignedInt,
105                LongLongUnsignedInt,
106                SignedInt128,
107                UnsignedInt128,
108                uFloat16,
109                uFloat16Complex,
110                uFloat32,
111                uFloat32Complex,
112                Float,
113                FloatComplex,
114                uFloat32x,
115                uFloat32xComplex,
116                uFloat64,
117                uFloat64Complex,
118                Double,
119                DoubleComplex,
120                uFloat64x,
121                uFloat64xComplex,
122                uuFloat80,
123                uFloat128,
124                uFloat128Complex,
125                uuFloat128,
126                LongDouble,
127                LongDoubleComplex,
128                uFloat128x,
129                uFloat128xComplex,
130                NUMBER_OF_BASIC_TYPES
131        } kind;
132        // GENERATED END
133
134        /// xxx -- MAX_INTEGER_TYPE should probably be in BasicTypes-gen.cc, rather than hardcoded here
135        enum { MAX_INTEGER_TYPE = UnsignedInt128 };
136
137        /// string names of basic types; generated to match with Kind
138        static const char *typeNames[];
139
140        BasicType( Kind k, CV::Qualifiers q = {} ) : Type(q), kind(k) {}
141
142        /// Check if this type represents an integer type
143        bool isInteger() const { return kind <= MAX_INTEGER_TYPE; }
144
145        Type * accept( Visitor & v ) override { return v.visit( this ); }
146private:
147        BasicType * clone() const override { return new BasicType{ *this }; }
148};
149
150/// Pointer/array variable length?
151enum LengthFlag { FixedLen, VariableLen };
152
153/// Pointer/array static dimension?
154enum DimensionFlag { DynamicDim, StaticDim };
155
156/// Pointer type `T*`
157class PointerType final : public Type {
158public:
159        ptr<Type> base;
160
161        // In C99, pointer types can be qualified in many ways, e.g. `int a[ static 3 ]`
162        ptr<Expr> dimension;
163        LengthFlag isVarLen = FixedLen;
164        DimensionFlag isStatic = DynamicDim;
165
166        PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
167        PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s, 
168                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
169
170        // true if this pointer is actually an array
171        bool isArray() const { return isVarLen || isStatic || dimension; }
172
173        bool isComplete() const override { return ! isVarLen; }
174
175        Type * accept( Visitor & v ) override { return v.visit( this ); }
176private:
177        PointerType * clone() const override { return new PointerType{ *this }; }
178};
179
180/// Array type `T[]`
181class ArrayType final : public Type {
182public:
183        ptr<Type> base;
184        ptr<Expr> dimension;
185        LengthFlag isVarLen;
186        DimensionFlag isStatic;
187
188        ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s, 
189                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
190
191        // array types are complete if they have a dimension expression or are
192        // VLAs ('*' in parameter declaration), and incomplete otherwise.
193        // See 6.7.6.2
194        bool isComplete() const override { return dimension || isVarLen; }
195
196        Type * accept( Visitor & v ) override { return v.visit( this ); }
197private:
198        ArrayType * clone() const override { return new ArrayType{ *this }; }
199};
200
201/// Reference type `T&`
202class ReferenceType final : public Type {
203public:
204        ptr<Type> base;
205
206        ReferenceType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
207
208        unsigned referenceDepth() const override { return base->referenceDepth() + 1; }
209
210        // Since reference types act like value types, their size is the size of the base.
211        // This makes it simple to cast the empty tuple to a reference type, since casts that increase
212        // the number of values are disallowed.
213        unsigned size() const override { return base->size(); }
214
215        Type * accept( Visitor & v ) override { return v.visit( this ); }
216private:
217        ReferenceType * clone() const override { return new ReferenceType{ *this }; }
218};
219
220/// Qualified type `P.C`
221class QualifiedType final : public Type {
222public:
223        ptr<Type> parent;
224        ptr<Type> child;
225
226        QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} ) 
227        : Type(q), parent(p), child(c) {}
228
229        Type * accept( Visitor & v ) override { return v.visit( this ); }
230private:
231        QualifiedType * clone() const override { return new QualifiedType{ *this }; }
232};
233
234/// Base type for potentially forall-qualified types
235class ParameterizedType : public Type {
236public:
237        using ForallList = std::vector<ptr<TypeDecl>>;
238
239        ForallList forall;
240
241        ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {} ) 
242        : Type(q), forall(std::move(fs)) {}
243        ParameterizedType( CV::Qualifiers q ) : Type(q), forall() {}
244
245private:
246        virtual ParameterizedType * clone() const override = 0;
247};
248
249/// Function variable arguments flag
250enum ArgumentFlag { FixedArgs, VariableArgs };
251
252/// Type of a function `[R1, R2](*)(P1, P2, P3)`
253class FunctionType final : public ParameterizedType {
254public:
255        std::vector<ptr<DeclWithType>> returnVals;
256        std::vector<ptr<DeclWithType>> parameters;
257
258        /// Does the function accept a variable number of arguments following the arguments specified
259        /// in the parameters list.
260        /// This could be because of
261        /// - an ellipsis in a prototype declaration
262        /// - an unprototyped declaration
263        ArgumentFlag isVarArgs;
264
265        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
266        : ParameterizedType(q), returnVals(), parameters(), isVarArgs(va) {}
267
268        /// true if either the parameters or return values contain a tttype
269        bool isTtype() const;
270        /// true if function parameters are unconstrained by prototype
271        bool isUnprototyped() const { return isVarArgs && parameters.size() == 0; }
272
273        Type * accept( Visitor & v ) override { return v.visit( this ); }
274private:
275        FunctionType * clone() const override { return new FunctionType{ *this }; }
276};
277
278/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
279class ReferenceToType : public ParameterizedType {
280public:
281        std::vector<ptr<Expr>> parameters;
282        std::vector<ptr<Attribute>> attributes;
283        std::string name;
284        bool hoistType = false;
285
286        ReferenceToType( const std::string& n, CV::Qualifiers q = {}, 
287                std::vector<ptr<Attribute>> && as = {} )
288        : ParameterizedType(q), parameters(), attributes(std::move(as)), name(n) {}
289
290        /// Gets aggregate declaration this type refers to
291        virtual const AggregateDecl * aggr() const = 0;
292        /// Looks up member declarations with given name
293        std::vector<readonly<Decl>> lookup( const std::string & name ) const;
294
295private:
296        virtual ReferenceToType * clone() const override = 0;
297
298protected:
299        /// Name for the kind of type this is
300        virtual std::string typeString() const = 0;
301};
302
303/// instance of struct type
304class StructInstType final : public ReferenceToType {
305public:
306        readonly<StructDecl> base;
307
308        StructInstType( const std::string& n, CV::Qualifiers q = {}, 
309                std::vector<ptr<Attribute>> && as = {} )
310        : ReferenceToType( n, q, std::move(as) ), base() {}
311        StructInstType( const StructDecl * b, CV::Qualifiers q = {}, 
312                std::vector<ptr<Attribute>> && as = {} );
313       
314        bool isComplete() const override;
315
316        const StructDecl * aggr() const override { return base; }
317
318        Type * accept( Visitor & v ) override { return v.visit( this ); }
319private:
320        StructInstType * clone() const override { return new StructInstType{ *this }; }
321
322        std::string typeString() const override { return "struct"; }
323};
324
325/// instance of union type
326class UnionInstType final : public ReferenceToType {
327public:
328        readonly<UnionDecl> base;
329
330        UnionInstType( const std::string& n, CV::Qualifiers q = {}, 
331                std::vector<ptr<Attribute>> && as = {} )
332        : ReferenceToType( n, q, std::move(as) ), base() {}
333        UnionInstType( const UnionDecl * b, CV::Qualifiers q = {}, 
334                std::vector<ptr<Attribute>> && as = {} );
335       
336        bool isComplete() const override;
337
338        const UnionDecl * aggr() const override { return base; }
339
340        Type * accept( Visitor & v ) override { return v.visit( this ); }
341private:
342        UnionInstType * clone() const override { return new UnionInstType{ *this }; }
343
344        std::string typeString() const override { return "union"; }
345};
346
347/// instance of enum type
348class EnumInstType final : public ReferenceToType {
349public:
350        readonly<EnumDecl> base;
351
352        EnumInstType( const std::string& n, CV::Qualifiers q = {}, 
353                std::vector<ptr<Attribute>> && as = {} )
354        : ReferenceToType( n, q, std::move(as) ), base() {}
355        EnumInstType( const EnumDecl * b, CV::Qualifiers q = {}, 
356                std::vector<ptr<Attribute>> && as = {} );
357       
358        bool isComplete() const override;
359
360        const EnumDecl * aggr() const override { return base; }
361
362        Type * accept( Visitor & v ) override { return v.visit( this ); }
363private:
364        EnumInstType * clone() const override { return new EnumInstType{ *this }; }
365
366        std::string typeString() const override { return "enum"; }
367};
368
369/// instance of trait type
370class TraitInstType final : public ReferenceToType {
371public:
372        readonly<TraitDecl> base;
373
374        TraitInstType( const std::string& n, CV::Qualifiers q = {}, 
375                std::vector<ptr<Attribute>> && as = {} )
376        : ReferenceToType( n, q, std::move(as) ), base() {}
377        TraitInstType( const TraitDecl * b, CV::Qualifiers q = {}, 
378                std::vector<ptr<Attribute>> && as = {} );
379       
380        // not meaningful for TraitInstType
381        bool isComplete() const override { assert(false); }
382
383        const TraitDecl * aggr() const override { return base; }
384
385        Type * accept( Visitor & v ) override { return v.visit( this ); }
386private:
387        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
388
389        std::string typeString() const override { return "trait"; }
390};
391
392/// instance of named type alias (typedef or variable)
393class TypeInstType final : public ReferenceToType {
394public:
395        readonly<TypeDecl> base;
396        TypeVar::Kind kind;
397
398        TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {}, 
399                std::vector<ptr<Attribute>> && as = {} )
400        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
401        TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {}, 
402                std::vector<ptr<Attribute>> && as = {} )
403        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
404
405        /// sets `base`, updating `kind` correctly
406        void set_base( const TypeDecl * );
407
408        bool isComplete() const override;
409
410        // not meaningful for TypeInstType
411        const AggregateDecl * aggr() const override { assert(false); }
412
413        Type * accept( Visitor & v ) override { return v.visit( this ); }
414private:
415        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
416
417        std::string typeString() const override { return "type"; }
418};
419
420/// tuple type e.g. `[int, char]`
421class TupleType final : public Type {
422public:
423        std::vector<ptr<Type>> types;
424        std::vector<ptr<Decl>> members;
425
426        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
427
428        // collection simulation
429        using iterator = std::vector<ptr<Type>>::const_iterator;
430        iterator begin() const { return types.begin(); }
431        iterator end() const { return types.end(); }
432       
433        unsigned size() const override { return types.size(); }
434
435        const Type * getComponent( unsigned i ) override {
436                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d", 
437                        i, size() );
438                return *(begin()+i);
439        }
440
441        Type * accept( Visitor & v ) override { return v.visit( this ); }
442private:
443        TupleType * clone() const override { return new TupleType{ *this }; }
444};
445
446/// Type of unresolved `typeof()` expression
447class TypeofType : public Type {
448public:
449        ptr<Expr> expr;
450        enum Kind { Typeof, Basetypeof } kind;
451
452        TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} ) 
453        : Type(q), expr(e), kind(k) {}
454
455        Type * accept( Visitor & v ) override { return v.visit( this ); }
456private:
457        TypeofType * clone() const override { return new TypeofType{ *this }; }
458};
459
460/// GCC built-in varargs type
461class VarArgsType final : public Type {
462public:
463        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
464       
465        Type * accept( Visitor & v ) override { return v.visit( this ); }
466private:
467        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
468};
469
470/// Type of zero constant `0`
471class ZeroType final : public Type {
472public:
473        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
474       
475        Type * accept( Visitor & v ) override { return v.visit( this ); }
476private:
477        ZeroType * clone() const override { return new ZeroType{ *this }; }     
478};
479
480/// Type of one constant `1`
481class OneType final : public Type {
482public:
483        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
484
485        Type * accept( Visitor & v ) override { return v.visit( this ); }
486private:
487        OneType * clone() const override { return new OneType{ *this }; }
488};
489
490/// Parent type for scope-qualified types at global scope
491class GlobalScopeType final : public Type {
492public:
493        GlobalScopeType( CV::Qualifiers q = {} ) : Type( q ) {}
494
495        Type * accept( Visitor & v ) override { return v.visit( this ); }
496private:
497        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
498};
499
500//=================================================================================================
501/// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency
502/// remove only if there is a better solution.
503/// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with
504/// forward declarations
505inline void increment( const class Type * node, Node::ref_type ref ) { node->increment( ref ); }
506inline void decrement( const class Type * node, Node::ref_type ref ) { node->decrement( ref ); }
507inline void increment( const class VoidType * node, Node::ref_type ref ) { node->increment( ref ); }
508inline void decrement( const class VoidType * node, Node::ref_type ref ) { node->decrement( ref ); }
509inline void increment( const class BasicType * node, Node::ref_type ref ) { node->increment( ref ); }
510inline void decrement( const class BasicType * node, Node::ref_type ref ) { node->decrement( ref ); }
511inline void increment( const class PointerType * node, Node::ref_type ref ) { node->increment( ref ); }
512inline void decrement( const class PointerType * node, Node::ref_type ref ) { node->decrement( ref ); }
513inline void increment( const class ArrayType * node, Node::ref_type ref ) { node->increment( ref ); }
514inline void decrement( const class ArrayType * node, Node::ref_type ref ) { node->decrement( ref ); }
515inline void increment( const class ReferenceType * node, Node::ref_type ref ) { node->increment( ref ); }
516inline void decrement( const class ReferenceType * node, Node::ref_type ref ) { node->decrement( ref ); }
517inline void increment( const class QualifiedType * node, Node::ref_type ref ) { node->increment( ref ); }
518inline void decrement( const class QualifiedType * node, Node::ref_type ref ) { node->decrement( ref ); }
519inline void increment( const class FunctionType * node, Node::ref_type ref ) { node->increment( ref ); }
520inline void decrement( const class FunctionType * node, Node::ref_type ref ) { node->decrement( ref ); }
521inline void increment( const class ReferenceToType * node, Node::ref_type ref ) { node->increment( ref ); }
522inline void decrement( const class ReferenceToType * node, Node::ref_type ref ) { node->decrement( ref ); }
523inline void increment( const class StructInstType * node, Node::ref_type ref ) { node->increment( ref ); }
524inline void decrement( const class StructInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
525inline void increment( const class UnionInstType * node, Node::ref_type ref ) { node->increment( ref ); }
526inline void decrement( const class UnionInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
527inline void increment( const class EnumInstType * node, Node::ref_type ref ) { node->increment( ref ); }
528inline void decrement( const class EnumInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
529inline void increment( const class TraitInstType * node, Node::ref_type ref ) { node->increment( ref ); }
530inline void decrement( const class TraitInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
531inline void increment( const class TypeInstType * node, Node::ref_type ref ) { node->increment( ref ); }
532inline void decrement( const class TypeInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
533inline void increment( const class TupleType * node, Node::ref_type ref ) { node->increment( ref ); }
534inline void decrement( const class TupleType * node, Node::ref_type ref ) { node->decrement( ref ); }
535inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); }
536inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); }
537inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); }
538inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); }
539inline void increment( const class ZeroType * node, Node::ref_type ref ) { node->increment( ref ); }
540inline void decrement( const class ZeroType * node, Node::ref_type ref ) { node->decrement( ref ); }
541inline void increment( const class OneType * node, Node::ref_type ref ) { node->increment( ref ); }
542inline void decrement( const class OneType * node, Node::ref_type ref ) { node->decrement( ref ); }
543inline void increment( const class GlobalScopeType * node, Node::ref_type ref ) { node->increment( ref ); }
544inline void decrement( const class GlobalScopeType * node, Node::ref_type ref ) { node->decrement( ref ); }
545
546}
547
548// Local Variables: //
549// tab-width: 4 //
550// mode: c++ //
551// compile-command: "make install" //
552// End: //
Note: See TracBrowser for help on using the repository browser.