source: src/AST/Type.hpp @ c829320

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

Hoist attributes back up to Type in new AST

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