source: src/AST/Type.hpp @ dafe9e1

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since dafe9e1 was dafe9e1, checked in by Andrew Beach <ajbeach@…>, 5 years ago

Fixed broken destructor cycles. Cleaned up strict_dynamic_cast.

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