source: src/AST/Type.hpp @ 3648d98

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

Clean up warnings/errors from ast::Type merge

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