source: src/AST/Type.hpp @ ee574a2

arm-ehenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since ee574a2 was ee574a2, checked in by Aaron Moss <a3moss@…>, 4 years ago

Port CommonType? to new AST

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