source: src/AST/Type.hpp@ f90d10f

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 f90d10f was 07de76b, checked in by Peter A. Buhr <pabuhr@…>, 6 years ago

remove file TypeVar.h* and put TypeVar::Kind into TypeDecl, move LinkageSpec.* from directory Parse to SynTree

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