source: src/AST/Type.hpp @ 99da267

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 99da267 was 99da267, checked in by Michael Brooks <mlbrooks@…>, 5 years ago

Running a deep-copy on FunctionType? at RenameVars? time. This manual action addresses the currently-problematic occurrence of 'the transitivity problem.' Resolution of bootloader (and thus builtins) is now completing. The change on RenameVars?.cc makes this happen. Changes on AST/*.hpp finish making the deep-copy framework compile.

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