source: src/AST/Type.hpp @ d76c588

arm-ehjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since d76c588 was d76c588, checked in by Aaron Moss <a3moss@…>, 3 years ago

Stubs for new resolver, implementation of new indexer, type environment

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