source: src/AST/Decl.hpp@ 14c31eb

Last change on this file since 14c31eb was 90be0cf, checked in by Andrew Beach <ajbeach@…>, 11 months ago

Moved some methods out of EnumDecl. These were calculations and the ast types are supposed to be data focused so they should either go with utility functions or to their use site. I tried the use site.

  • Property mode set to 100644
File size: 15.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// Decl.hpp --
8//
9// Author : Aaron B. Moss
10// Created On : Thu May 9 10:00:00 2019
11// Last Modified By : Andrew Beach
12// Last Modified On : Wed Apr 5 10:42:00 2023
13// Update Count : 35
14//
15
16#pragma once
17
18#include <iosfwd>
19#include <string> // for string, to_string
20#include <unordered_map>
21#include <vector>
22#include <algorithm>
23
24#include "FunctionSpec.hpp"
25#include "Fwd.hpp" // for UniqueId
26#include "LinkageSpec.hpp"
27#include "Node.hpp" // for ptr, readonly
28#include "ParseNode.hpp"
29#include "StorageClasses.hpp"
30#include "Visitor.hpp"
31
32// Must be included in *all* AST classes; should be #undef'd at the end of the file
33#define MUTATE_FRIEND \
34 template<typename node_t> friend node_t * mutate(const node_t * node); \
35 template<typename node_t> friend node_t * shallowCopy(const node_t * node);
36
37namespace ast {
38
39/// Base declaration class
40class Decl : public ParseNode {
41public:
42 std::string name;
43 Storage::Classes storage;
44 Linkage::Spec linkage;
45 UniqueId uniqueId = 0;
46 bool extension = false;
47
48 Decl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
49 Linkage::Spec linkage )
50 : ParseNode( loc ), name( name ), storage( storage ), linkage( linkage ) {}
51
52 /// Ensures this node has a unique ID
53 void fixUniqueId();
54
55 const Decl * accept( Visitor & v ) const override = 0;
56private:
57 Decl * clone() const override = 0;
58 MUTATE_FRIEND
59};
60
61/// Typed declaration base class
62class DeclWithType : public Decl {
63public:
64 /// Represents the type with all types and typedefs expanded.
65 std::string mangleName;
66 /// Stores the scope level at which the variable was declared.
67 /// Used to access shadowed identifiers.
68 int scopeLevel = 0;
69
70 std::vector<ptr<Attribute>> attributes;
71 Function::Specs funcSpec;
72 ptr<Expr> asmName;
73 bool isDeleted = false;
74 bool isTypeFixed = false;
75 bool isHidden = false;
76
77 DeclWithType( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
78 Linkage::Spec linkage, std::vector<ptr<Attribute>>&& attrs, Function::Specs fs )
79 : Decl( loc, name, storage, linkage ), mangleName(), attributes( std::move(attrs) ),
80 funcSpec(fs), asmName() {}
81
82 std::string scopedMangleName() const { return mangleName + "_" + std::to_string(scopeLevel); }
83
84 /// Get type of this declaration. May be generated by subclass
85 virtual const Type * get_type() const = 0;
86 /// Set type of this declaration. May be verified by subclass
87 virtual void set_type( const Type * ) = 0;
88
89 const DeclWithType * accept( Visitor & v ) const override = 0;
90private:
91 DeclWithType * clone() const override = 0;
92 MUTATE_FRIEND
93};
94
95/// Object declaration `Foo foo = 42;`
96class ObjectDecl final : public DeclWithType {
97public:
98 ptr<Type> type;
99 ptr<Init> init;
100 ptr<Expr> bitfieldWidth;
101
102 ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type,
103 const Init * init = nullptr, Storage::Classes storage = {},
104 Linkage::Spec linkage = Linkage::Cforall, const Expr * bitWd = nullptr,
105 std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {} )
106 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
107 init( init ), bitfieldWidth( bitWd ) {}
108
109 const Type* get_type() const override { return type; }
110 void set_type( const Type * ty ) override { type = ty; }
111
112 const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
113private:
114 ObjectDecl * clone() const override { return new ObjectDecl{ *this }; }
115 MUTATE_FRIEND
116};
117
118/// Function variable arguments flag
119enum ArgumentFlag { FixedArgs, VariableArgs };
120
121/// Function declaration `int foo()`
122class FunctionDecl final : public DeclWithType {
123public:
124 std::vector<ptr<TypeDecl>> type_params;
125 std::vector<ptr<DeclWithType>> assertions;
126 std::vector<ptr<DeclWithType>> params;
127 std::vector<ptr<DeclWithType>> returns;
128 // declared type, derived from parameter declarations
129 ptr<FunctionType> type;
130 /// Null for the forward declaration of a function.
131 ptr<CompoundStmt> stmts;
132 std::vector< ptr<Expr> > withExprs;
133
134 /// Monomorphic Function Constructor:
135 FunctionDecl( const CodeLocation & locaction, const std::string & name,
136 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
137 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
138 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
139
140 /// Polymorphic Function Constructor:
141 FunctionDecl( const CodeLocation & location, const std::string & name,
142 std::vector<ptr<TypeDecl>>&& forall, std::vector<ptr<DeclWithType>>&& assertions,
143 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
144 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
145 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
146
147 const Type * get_type() const override;
148 void set_type( const Type * t ) override;
149
150 bool has_body() const { return stmts; }
151
152 const DeclWithType * accept( Visitor & v ) const override { return v.visit( this ); }
153private:
154 FunctionDecl * clone() const override { return new FunctionDecl( *this ); }
155 MUTATE_FRIEND
156};
157
158/// Base class for named type aliases
159class NamedTypeDecl : public Decl {
160public:
161 ptr<Type> base;
162 std::vector<ptr<DeclWithType>> assertions;
163
164 NamedTypeDecl(
165 const CodeLocation & loc, const std::string & name, Storage::Classes storage,
166 const Type * b, Linkage::Spec spec = Linkage::Cforall )
167 : Decl( loc, name, storage, spec ), base( b ), assertions() {}
168
169 /// Produces a name for the kind of alias
170 virtual const char * typeString() const = 0;
171
172private:
173 NamedTypeDecl* clone() const override = 0;
174 MUTATE_FRIEND
175};
176
177/// Cforall type variable: `dtype T`
178class TypeDecl final : public NamedTypeDecl {
179 public:
180 enum Kind { Dtype, DStype, Otype, Ftype, Ttype, Dimension, NUMBER_OF_KINDS };
181
182 Kind kind;
183 bool sized;
184 ptr<Type> init;
185
186 TypeDecl(
187 const CodeLocation & loc, const std::string & name, Storage::Classes storage,
188 const Type * b, TypeDecl::Kind k, bool s, const Type * i = nullptr )
189 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == TypeDecl::Ttype || s ),
190 init( i ) {}
191
192 const char * typeString() const override;
193 /// Produces a name for generated code
194 const char * genTypeString() const;
195
196 /// convenience accessor to match Type::isComplete()
197 bool isComplete() const { return sized; }
198
199 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
200 private:
201 TypeDecl * clone() const override { return new TypeDecl{ *this }; }
202 MUTATE_FRIEND
203};
204
205/// Data extracted from a TypeDecl.
206struct TypeData {
207 TypeDecl::Kind kind;
208 bool isComplete;
209
210 TypeData() : kind( TypeDecl::NUMBER_OF_KINDS ), isComplete( false ) {}
211 TypeData( const TypeDecl * d ) : kind( d->kind ), isComplete( d->sized ) {}
212 TypeData( TypeDecl::Kind k, bool c ) : kind( k ), isComplete( c ) {}
213 TypeData( const TypeData & d1, const TypeData & d2 )
214 : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {}
215
216 bool operator==( const TypeData & o ) const { return kind == o.kind && isComplete == o.isComplete; }
217 bool operator!=( const TypeData & o ) const { return !(*this == o); }
218};
219
220std::ostream & operator<< ( std::ostream &, const TypeData & );
221
222/// C-style typedef `typedef Foo Bar`
223class TypedefDecl final : public NamedTypeDecl {
224public:
225 TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
226 Type* b, Linkage::Spec spec = Linkage::Cforall )
227 : NamedTypeDecl( loc, name, storage, b, spec ) {}
228
229 const char * typeString() const override { return "typedef"; }
230
231 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
232private:
233 TypedefDecl * clone() const override { return new TypedefDecl{ *this }; }
234 MUTATE_FRIEND
235};
236
237/// Aggregate type declaration base class
238class AggregateDecl : public Decl {
239public:
240 enum Aggregate { Struct, Union, Enum, Exception, Trait, Generator, Coroutine, Monitor, Thread, NoAggregate };
241 static const char * aggrString( Aggregate aggr );
242
243 std::vector<ptr<Decl>> members;
244 std::vector<ptr<TypeDecl>> params;
245 std::vector<ptr<Attribute>> attributes;
246 bool body = false;
247 readonly<AggregateDecl> parent = {};
248
249 AggregateDecl( const CodeLocation& loc, const std::string& name,
250 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
251 : Decl( loc, name, Storage::Classes{}, linkage ), members(), params(),
252 attributes( std::move(attrs) ) {}
253
254 AggregateDecl* set_body( bool b ) { body = b; return this; }
255
256 /// Produces a name for the kind of aggregate
257 virtual const char * typeString() const = 0;
258
259private:
260 AggregateDecl * clone() const override = 0;
261 MUTATE_FRIEND
262};
263
264/// struct declaration `struct Foo { ... };`
265class StructDecl final : public AggregateDecl {
266public:
267 Aggregate kind;
268
269 StructDecl( const CodeLocation& loc, const std::string& name,
270 Aggregate kind = Struct,
271 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
272 : AggregateDecl( loc, name, std::move(attrs), linkage ), kind( kind ) {}
273
274 bool is_coroutine() const { return kind == Coroutine; }
275 bool is_generator() const { return kind == Generator; }
276 bool is_monitor () const { return kind == Monitor ; }
277 bool is_thread () const { return kind == Thread ; }
278
279 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
280
281 const char * typeString() const override { return aggrString( kind ); }
282
283private:
284 StructDecl * clone() const override { return new StructDecl{ *this }; }
285 MUTATE_FRIEND
286};
287
288/// union declaration `union Foo { ... };`
289class UnionDecl final : public AggregateDecl {
290public:
291 UnionDecl( const CodeLocation& loc, const std::string& name,
292 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
293 : AggregateDecl( loc, name, std::move(attrs), linkage ) {}
294
295 const Decl * accept( Visitor& v ) const override { return v.visit( this ); }
296
297 const char * typeString() const override { return aggrString( Union ); }
298
299private:
300 UnionDecl * clone() const override { return new UnionDecl{ *this }; }
301 MUTATE_FRIEND
302};
303
304/// Enumeration attribute kind.
305enum class EnumAttribute{ Value, Posn, Label };
306
307/// enum declaration `enum Foo { ... };`
308class EnumDecl final : public AggregateDecl {
309public:
310 // isCfa indicated if the enum has a declaration like:
311 // enum (type_optional) Name {...}
312 bool isCfa;
313 // if isCfa == true && base.get() == nullptr, it is a "opaque" enum
314 ptr<Type> base;
315 enum class EnumHiding { Visible, Hide } hide;
316 std::vector< ast::ptr<ast::EnumInstType>> inlinedDecl; // child enums
317
318 EnumDecl( const CodeLocation& loc, const std::string& name, bool isCfa = false,
319 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
320 Type const * base = nullptr, EnumHiding hide = EnumHiding::Hide,
321 std::unordered_map< std::string, long long > enumValues = std::unordered_map< std::string, long long >() )
322 : AggregateDecl( loc, name, std::move(attrs), linkage ), isCfa(isCfa), base(base), hide(hide), enumValues(enumValues) {}
323
324 /// gets the integer value for this enumerator, returning true iff value found
325 // Maybe it is not used in producing the enum value
326 bool valueOf( const Decl * enumerator, long long& value ) const;
327
328 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
329
330 const char * typeString() const override { return aggrString( Enum ); }
331
332 bool isTyped() const;
333 bool isOpaque() const;
334private:
335 EnumDecl * clone() const override { return new EnumDecl{ *this }; }
336 MUTATE_FRIEND
337
338 /// Map from names to enumerator values; kept private for lazy initialization
339 mutable std::unordered_map< std::string, long long > enumValues;
340};
341
342/// trait declaration `trait Foo( ... ) { ... };`
343class TraitDecl final : public AggregateDecl {
344public:
345 TraitDecl( const CodeLocation& loc, const std::string& name,
346 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
347 : AggregateDecl( loc, name, std::move(attrs), linkage ) {}
348
349 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
350
351 const char * typeString() const override { return "trait"; }
352
353private:
354 TraitDecl * clone() const override { return new TraitDecl{ *this }; }
355 MUTATE_FRIEND
356};
357
358/// With statement `with (...) ...`
359/// This is a statement lexically, but a Decl is needed for the SymbolTable.
360class WithStmt final : public Decl {
361public:
362 std::vector<ptr<Expr>> exprs;
363 ptr<Stmt> stmt;
364
365 WithStmt( const CodeLocation & loc, std::vector<ptr<Expr>> && exprs, const Stmt * stmt )
366 : Decl(loc, "", Storage::Auto, Linkage::Cforall), exprs(std::move(exprs)), stmt(stmt) {}
367
368 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
369private:
370 WithStmt * clone() const override { return new WithStmt{ *this }; }
371 MUTATE_FRIEND
372};
373
374/// Assembly declaration: `asm ... ( "..." : ... )`
375class AsmDecl final : public Decl {
376public:
377 ptr<AsmStmt> stmt;
378
379 AsmDecl( const CodeLocation & loc, AsmStmt * stmt )
380 : Decl( loc, "", {}, Linkage::C ), stmt(stmt) {}
381
382 const AsmDecl * accept( Visitor & v ) const override { return v.visit( this ); }
383private:
384 AsmDecl * clone() const override { return new AsmDecl( *this ); }
385 MUTATE_FRIEND
386};
387
388/// C-preprocessor directive `#...`
389class DirectiveDecl final : public Decl {
390public:
391 ptr<DirectiveStmt> stmt;
392
393 DirectiveDecl( const CodeLocation & loc, DirectiveStmt * stmt )
394 : Decl( loc, "", {}, Linkage::C ), stmt(stmt) {}
395
396 const DirectiveDecl * accept( Visitor & v ) const override { return v.visit( this ); }
397private:
398 DirectiveDecl * clone() const override { return new DirectiveDecl( *this ); }
399 MUTATE_FRIEND
400};
401
402/// Static Assertion `_Static_assert( ... , ... );`
403class StaticAssertDecl final : public Decl {
404public:
405 ptr<Expr> cond;
406 ptr<ConstantExpr> msg; // string literal
407
408 StaticAssertDecl( const CodeLocation & loc, const Expr * condition, const ConstantExpr * msg )
409 : Decl( loc, "", {}, Linkage::C ), cond( condition ), msg( msg ) {}
410
411 const StaticAssertDecl * accept( Visitor & v ) const override { return v.visit( this ); }
412private:
413 StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
414 MUTATE_FRIEND
415};
416
417/// Inline Member Declaration `inline TypeName;`
418class InlineMemberDecl final : public DeclWithType {
419public:
420 ptr<Type> type;
421
422 InlineMemberDecl( const CodeLocation & loc, const std::string & name, const Type * type,
423 Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
424 std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {} )
425 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ) {}
426
427 const Type * get_type() const override { return type; }
428 void set_type( const Type * ty ) override { type = ty; }
429
430 const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
431private:
432 InlineMemberDecl * clone() const override { return new InlineMemberDecl{ *this }; }
433 MUTATE_FRIEND
434};
435
436}
437
438#undef MUTATE_FRIEND
439
440// Local Variables: //
441// tab-width: 4 //
442// mode: c++ //
443// compile-command: "make install" //
444// End: //
Note: See TracBrowser for help on using the repository browser.