source: src/AST/Type.hpp @ e0e9a0b

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

Somewhat deeper clone for types with forall qualifiers.

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