source: src/AST/Type.hpp@ bc4bea8

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since bc4bea8 was dafe9e1, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Fixed broken destructor cycles. Cleaned up strict_dynamic_cast.

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