source: src/AST/Type.hpp @ 6be3b7d6

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

Deeper clone on forall-lists on types to fix weak-ref error

  • Property mode set to 100644
File size: 17.0 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 = {}, std::vector<ptr<Attribute>> && as = {} ) 
167        : Type(q, std::move(as)), kind(k) {}
168
169        /// Check if this type represents an integer type
170        bool isInteger() const { return (unsigned)kind <= (unsigned)MAX_INTEGER_TYPE; }
171
172        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
173private:
174        BasicType * clone() const override { return new BasicType{ *this }; }
175        MUTATE_FRIEND
176};
177
178/// Pointer/array variable length?
179enum LengthFlag { FixedLen, VariableLen };
180
181/// Pointer/array static dimension?
182enum DimensionFlag { DynamicDim, StaticDim };
183
184/// Pointer type `T*`
185class PointerType final : public Type {
186public:
187        ptr<Type> base;
188
189        // In C99, pointer types can be qualified in many ways, e.g. `int a[ static 3 ]`
190        ptr<Expr> dimension;
191        LengthFlag isVarLen = FixedLen;
192        DimensionFlag isStatic = DynamicDim;
193
194        PointerType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b), dimension() {}
195        PointerType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
196                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
197
198        // true if this pointer is actually an array
199        bool isArray() const { return isVarLen || isStatic || dimension; }
200
201        bool isComplete() const override { return ! isVarLen; }
202
203        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
204private:
205        PointerType * clone() const override { return new PointerType{ *this }; }
206        MUTATE_FRIEND
207};
208
209/// Array type `T[]`
210class ArrayType final : public Type {
211public:
212        ptr<Type> base;
213        ptr<Expr> dimension;
214        LengthFlag isVarLen;
215        DimensionFlag isStatic;
216
217        ArrayType( const Type * b, const Expr * d, LengthFlag vl, DimensionFlag s,
218                CV::Qualifiers q = {} ) : Type(q), base(b), dimension(d), isVarLen(vl), isStatic(s) {}
219
220        // array types are complete if they have a dimension expression or are
221        // VLAs ('*' in parameter declaration), and incomplete otherwise.
222        // See 6.7.6.2
223        bool isComplete() const override { return dimension || isVarLen; }
224
225        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
226private:
227        ArrayType * clone() const override { return new ArrayType{ *this }; }
228        MUTATE_FRIEND
229};
230
231/// Reference type `T&`
232class ReferenceType final : public Type {
233public:
234        ptr<Type> base;
235
236        ReferenceType( const Type * b, CV::Qualifiers q = {} ) : Type(q), base(b) {}
237
238        unsigned referenceDepth() const override { return base->referenceDepth() + 1; }
239
240        // Since reference types act like value types, their size is the size of the base.
241        // This makes it simple to cast the empty tuple to a reference type, since casts that increase
242        // the number of values are disallowed.
243        unsigned size() const override { return base->size(); }
244
245        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
246private:
247        ReferenceType * clone() const override { return new ReferenceType{ *this }; }
248        MUTATE_FRIEND
249};
250
251/// Qualified type `P.C`
252class QualifiedType final : public Type {
253public:
254        ptr<Type> parent;
255        ptr<Type> child;
256
257        QualifiedType( const Type * p, const Type * c, CV::Qualifiers q = {} )
258        : Type(q), parent(p), child(c) {}
259
260        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
261private:
262        QualifiedType * clone() const override { return new QualifiedType{ *this }; }
263        MUTATE_FRIEND
264};
265
266/// Base type for potentially forall-qualified types
267class ParameterizedType : public Type {
268public:
269        using ForallList = std::vector<ptr<TypeDecl>>;
270       
271        ForallList forall;
272
273        ParameterizedType( ForallList&& fs = {}, CV::Qualifiers q = {},
274                std::vector<ptr<Attribute>> && as = {} )
275        : Type(q, std::move(as)), forall(std::move(fs)) {}
276
277        ParameterizedType( CV::Qualifiers q, std::vector<ptr<Attribute>> && as = {} )
278        : Type(q, std::move(as)), forall() {}
279
280        ParameterizedType( const ParameterizedType & o ) : Type( o ), forall() {
281                // one-level deep clone to avoid weak-reference errors
282                forall.reserve( o.forall.size() );
283                for ( const TypeDecl * d : o.forall ) { forall.emplace_back( d->clone() ); }
284        }
285
286        ParameterizedType( ParameterizedType && ) = default;
287
288        // no need to change destructor, and operator= deleted in Node
289
290private:
291        virtual ParameterizedType * clone() const override = 0;
292        MUTATE_FRIEND
293};
294
295/// Function variable arguments flag
296enum ArgumentFlag { FixedArgs, VariableArgs };
297
298/// Type of a function `[R1, R2](*)(P1, P2, P3)`
299class FunctionType final : public ParameterizedType {
300public:
301        std::vector<ptr<DeclWithType>> returns;
302        std::vector<ptr<DeclWithType>> params;
303
304        /// Does the function accept a variable number of arguments following the arguments specified
305        /// in the parameters list.
306        /// This could be because of
307        /// - an ellipsis in a prototype declaration
308        /// - an unprototyped declaration
309        ArgumentFlag isVarArgs;
310
311        FunctionType( ArgumentFlag va = FixedArgs, CV::Qualifiers q = {} )
312        : ParameterizedType(q), returns(), params(), isVarArgs(va) {}
313
314        /// true if either the parameters or return values contain a tttype
315        bool isTtype() const;
316        /// true if function parameters are unconstrained by prototype
317        bool isUnprototyped() const { return isVarArgs && params.size() == 0; }
318
319        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
320private:
321        FunctionType * clone() const override { return new FunctionType{ *this }; }
322        MUTATE_FRIEND
323};
324
325/// base class for types that refer to types declared elsewhere (aggregates and typedefs)
326class ReferenceToType : public ParameterizedType {
327public:
328        std::vector<ptr<Expr>> params;
329        std::string name;
330        bool hoistType = false;
331
332        ReferenceToType( const std::string& n, CV::Qualifiers q = {},
333                std::vector<ptr<Attribute>> && as = {} )
334        : ParameterizedType(q, std::move(as)), params(), name(n) {}
335
336        /// Gets aggregate declaration this type refers to
337        virtual const AggregateDecl * aggr() const = 0;
338        /// Looks up member declarations with given name
339        std::vector<readonly<Decl>> lookup( const std::string & name ) const;
340
341private:
342        virtual ReferenceToType * clone() const override = 0;
343        MUTATE_FRIEND
344};
345
346/// instance of struct type
347class StructInstType final : public ReferenceToType {
348public:
349        readonly<StructDecl> base;
350
351        StructInstType( const std::string& n, CV::Qualifiers q = {},
352                std::vector<ptr<Attribute>> && as = {} )
353        : ReferenceToType( n, q, std::move(as) ), base() {}
354        StructInstType( const StructDecl * b, CV::Qualifiers q = {},
355                std::vector<ptr<Attribute>> && as = {} );
356
357        bool isComplete() const override;
358
359        const StructDecl * aggr() const override { return base; }
360
361        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
362private:
363        StructInstType * clone() const override { return new StructInstType{ *this }; }
364        MUTATE_FRIEND
365};
366
367/// instance of union type
368class UnionInstType final : public ReferenceToType {
369public:
370        readonly<UnionDecl> base;
371
372        UnionInstType( const std::string& n, CV::Qualifiers q = {},
373                std::vector<ptr<Attribute>> && as = {} )
374        : ReferenceToType( n, q, std::move(as) ), base() {}
375        UnionInstType( const UnionDecl * b, CV::Qualifiers q = {},
376                std::vector<ptr<Attribute>> && as = {} );
377
378        bool isComplete() const override;
379
380        const UnionDecl * aggr() const override { return base; }
381
382        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
383private:
384        UnionInstType * clone() const override { return new UnionInstType{ *this }; }
385        MUTATE_FRIEND
386};
387
388/// instance of enum type
389class EnumInstType final : public ReferenceToType {
390public:
391        readonly<EnumDecl> base;
392
393        EnumInstType( const std::string& n, CV::Qualifiers q = {},
394                std::vector<ptr<Attribute>> && as = {} )
395        : ReferenceToType( n, q, std::move(as) ), base() {}
396        EnumInstType( const EnumDecl * b, CV::Qualifiers q = {},
397                std::vector<ptr<Attribute>> && as = {} );
398
399        bool isComplete() const override;
400
401        const EnumDecl * aggr() const override { return base; }
402
403        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
404private:
405        EnumInstType * clone() const override { return new EnumInstType{ *this }; }
406        MUTATE_FRIEND
407};
408
409/// instance of trait type
410class TraitInstType final : public ReferenceToType {
411public:
412        readonly<TraitDecl> base;
413
414        TraitInstType( const std::string& n, CV::Qualifiers q = {},
415                std::vector<ptr<Attribute>> && as = {} )
416        : ReferenceToType( n, q, std::move(as) ), base() {}
417        TraitInstType( const TraitDecl * b, CV::Qualifiers q = {},
418                std::vector<ptr<Attribute>> && as = {} );
419
420        // not meaningful for TraitInstType
421        bool isComplete() const override { assert(false); }
422
423        const TraitDecl * aggr() const override { return base; }
424
425        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
426private:
427        TraitInstType * clone() const override { return new TraitInstType{ *this }; }
428        MUTATE_FRIEND
429};
430
431/// instance of named type alias (typedef or variable)
432class TypeInstType final : public ReferenceToType {
433public:
434        readonly<TypeDecl> base;
435        TypeVar::Kind kind;
436
437        TypeInstType( const std::string& n, const TypeDecl * b, CV::Qualifiers q = {},
438                std::vector<ptr<Attribute>> && as = {} )
439        : ReferenceToType( n, q, std::move(as) ), base( b ), kind( b->kind ) {}
440        TypeInstType( const std::string& n, TypeVar::Kind k, CV::Qualifiers q = {},
441                std::vector<ptr<Attribute>> && as = {} )
442        : ReferenceToType( n, q, std::move(as) ), base(), kind( k ) {}
443
444        /// sets `base`, updating `kind` correctly
445        void set_base( const TypeDecl * );
446
447        bool isComplete() const override;
448
449        // not meaningful for TypeInstType
450        const AggregateDecl * aggr() const override { assert(false); }
451
452        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
453private:
454        TypeInstType * clone() const override { return new TypeInstType{ *this }; }
455        MUTATE_FRIEND
456};
457
458/// tuple type e.g. `[int, char]`
459class TupleType final : public Type {
460public:
461        std::vector<ptr<Type>> types;
462        std::vector<ptr<Decl>> members;
463
464        TupleType( std::vector<ptr<Type>> && ts, CV::Qualifiers q = {} );
465
466        // collection simulation
467        using iterator = std::vector<ptr<Type>>::const_iterator;
468        iterator begin() const { return types.begin(); }
469        iterator end() const { return types.end(); }
470
471        unsigned size() const override { return types.size(); }
472
473        const Type * getComponent( unsigned i ) const override {
474                assertf( i < size(), "TupleType::getComponent: index %d must be less than size %d",
475                        i, size() );
476                return *(begin()+i);
477        }
478
479        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
480private:
481        TupleType * clone() const override { return new TupleType{ *this }; }
482        MUTATE_FRIEND
483};
484
485/// Type of unresolved `typeof()` expression
486class TypeofType : public Type {
487public:
488        ptr<Expr> expr;
489        enum Kind { Typeof, Basetypeof } kind;
490
491        TypeofType( const Expr * e, Kind k = Typeof, CV::Qualifiers q = {} )
492        : Type(q), expr(e), kind(k) {}
493
494        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
495private:
496        TypeofType * clone() const override { return new TypeofType{ *this }; }
497        MUTATE_FRIEND
498};
499
500/// GCC built-in varargs type
501class VarArgsType final : public Type {
502public:
503        VarArgsType( CV::Qualifiers q = {} ) : Type( q ) {}
504
505        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
506private:
507        VarArgsType * clone() const override { return new VarArgsType{ *this }; }
508        MUTATE_FRIEND
509};
510
511/// Type of zero constant `0`
512class ZeroType final : public Type {
513public:
514        ZeroType( CV::Qualifiers q = {} ) : Type( q ) {}
515
516        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
517private:
518        ZeroType * clone() const override { return new ZeroType{ *this }; }
519        MUTATE_FRIEND
520};
521
522/// Type of one constant `1`
523class OneType final : public Type {
524public:
525        OneType( CV::Qualifiers q = {} ) : Type( q ) {}
526
527        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
528private:
529        OneType * clone() const override { return new OneType{ *this }; }
530        MUTATE_FRIEND
531};
532
533/// Parent type for scope-qualified types at global scope
534class GlobalScopeType final : public Type {
535public:
536        GlobalScopeType() : Type() {}
537
538        const Type * accept( Visitor & v ) const override { return v.visit( this ); }
539private:
540        GlobalScopeType * clone() const override { return new GlobalScopeType{ *this }; }
541        MUTATE_FRIEND
542};
543
544}
545
546#undef MUTATE_FRIEND
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.