source: src/AST/Type.hpp@ 4073b16

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 4073b16 was 746ae82, checked in by Aaron Moss <a3moss@…>, 6 years ago

Finish conversion visitors for Type

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