source: src/AST/Type.hpp @ f2d1335

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since f2d1335 was 3f3bfe5a, checked in by Andrew Beach <ajbeach@…>, 5 years ago

Merge from master to new-ast. Removing old lvalue support.

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