source: src/AST/Type.hpp @ c570806

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since c570806 was 4eb43fa, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Merge branch 'new-ast' of plg.uwaterloo.ca:software/cfa/cfa-cc into new-ast

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