source: src/AST/Type.hpp@ f2e482cb

ADT arm-eh ast-experimental cleanup-dtors enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since f2e482cb was 3648d98, checked in by Aaron Moss <a3moss@…>, 7 years ago

Clean up warnings/errors from ast::Type merge

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