source: src/AST/Type.hpp@ 92f5279

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 92f5279 was 92f5279, checked in by Aaron Moss <a3moss@…>, 6 years ago

Deeper clone on forall-lists on types to fix weak-ref error

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