source: src/AST/Decl.hpp@ 46c4dea

Last change on this file since 46c4dea was 90be0cf, checked in by Andrew Beach <ajbeach@…>, 12 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
RevLine 
[2bb4a01]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
[7edd5c1]11// Last Modified By : Andrew Beach
[3e94a23]12// Last Modified On : Wed Apr 5 10:42:00 2023
13// Update Count : 35
[2bb4a01]14//
15
16#pragma once
17
[d76c588]18#include <iosfwd>
[a300e4a]19#include <string> // for string, to_string
20#include <unordered_map>
[2bb4a01]21#include <vector>
[07de76b]22#include <algorithm>
[2bb4a01]23
[a300e4a]24#include "FunctionSpec.hpp"
[2bb4a01]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
[f3cc5b6]32// Must be included in *all* AST classes; should be #undef'd at the end of the file
[99da267]33#define MUTATE_FRIEND \
[91a72ef]34 template<typename node_t> friend node_t * mutate(const node_t * node); \
[99da267]35 template<typename node_t> friend node_t * shallowCopy(const node_t * node);
[f3cc5b6]36
[2bb4a01]37namespace ast {
[a300e4a]38
[2bb4a01]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
[14cebb7a]48 Decl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
[2bb4a01]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
[23f99e1]55 const Decl * accept( Visitor & v ) const override = 0;
[2bb4a01]56private:
[23f99e1]57 Decl * clone() const override = 0;
[f3cc5b6]58 MUTATE_FRIEND
[2bb4a01]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;
[14cebb7a]66 /// Stores the scope level at which the variable was declared.
[2bb4a01]67 /// Used to access shadowed identifiers.
68 int scopeLevel = 0;
69
70 std::vector<ptr<Attribute>> attributes;
[a300e4a]71 Function::Specs funcSpec;
[2bb4a01]72 ptr<Expr> asmName;
73 bool isDeleted = false;
[16ba4a6f]74 bool isTypeFixed = false;
[85855b0]75 bool isHidden = false;
[2bb4a01]76
[14cebb7a]77 DeclWithType( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
[2bb4a01]78 Linkage::Spec linkage, std::vector<ptr<Attribute>>&& attrs, Function::Specs fs )
[14cebb7a]79 : Decl( loc, name, storage, linkage ), mangleName(), attributes( std::move(attrs) ),
[a300e4a]80 funcSpec(fs), asmName() {}
[14cebb7a]81
[a300e4a]82 std::string scopedMangleName() const { return mangleName + "_" + std::to_string(scopeLevel); }
83
84 /// Get type of this declaration. May be generated by subclass
[6d51bd7]85 virtual const Type * get_type() const = 0;
[a300e4a]86 /// Set type of this declaration. May be verified by subclass
[e0e9a0b]87 virtual void set_type( const Type * ) = 0;
[a300e4a]88
[23f99e1]89 const DeclWithType * accept( Visitor & v ) const override = 0;
[a300e4a]90private:
[23f99e1]91 DeclWithType * clone() const override = 0;
[f3cc5b6]92 MUTATE_FRIEND
[a300e4a]93};
94
[77a3f41]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
[e67991f]102 ObjectDecl( const CodeLocation & loc, const std::string & name, const Type * type,
103 const Init * init = nullptr, Storage::Classes storage = {},
[e8616b6]104 Linkage::Spec linkage = Linkage::Cforall, const Expr * bitWd = nullptr,
[2a8f0c1]105 std::vector< ptr<Attribute> > && attrs = {}, Function::Specs fs = {} )
[14cebb7a]106 : DeclWithType( loc, name, storage, linkage, std::move(attrs), fs ), type( type ),
[77a3f41]107 init( init ), bitfieldWidth( bitWd ) {}
[14cebb7a]108
[77a3f41]109 const Type* get_type() const override { return type; }
[e0e9a0b]110 void set_type( const Type * ty ) override { type = ty; }
[77a3f41]111
[23f99e1]112 const DeclWithType * accept( Visitor& v ) const override { return v.visit( this ); }
[77a3f41]113private:
[23f99e1]114 ObjectDecl * clone() const override { return new ObjectDecl{ *this }; }
[f3cc5b6]115 MUTATE_FRIEND
[23f99e1]116};
117
[3e94a23]118/// Function variable arguments flag
119enum ArgumentFlag { FixedArgs, VariableArgs };
120
[2d6add4]121/// Function declaration `int foo()`
[a1da039]122class FunctionDecl final : public DeclWithType {
[23f99e1]123public:
[a00a2c1]124 std::vector<ptr<TypeDecl>> type_params;
125 std::vector<ptr<DeclWithType>> assertions;
[b859f59]126 std::vector<ptr<DeclWithType>> params;
127 std::vector<ptr<DeclWithType>> returns;
[954c954]128 // declared type, derived from parameter declarations
[23f99e1]129 ptr<FunctionType> type;
[b8ab91a]130 /// Null for the forward declaration of a function.
[23f99e1]131 ptr<CompoundStmt> stmts;
[d76c588]132 std::vector< ptr<Expr> > withExprs;
[23f99e1]133
[37273c8]134 /// Monomorphic Function Constructor:
135 FunctionDecl( const CodeLocation & locaction, const std::string & name,
[954c954]136 std::vector<ptr<DeclWithType>>&& params, std::vector<ptr<DeclWithType>>&& returns,
[3992098]137 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
[3e94a23]138 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
[7edd5c1]139
[37273c8]140 /// Polymorphic Function Constructor:
[7edd5c1]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,
[3992098]144 CompoundStmt * stmts, Storage::Classes storage = {}, Linkage::Spec linkage = Linkage::Cforall,
[3e94a23]145 std::vector<ptr<Attribute>>&& attrs = {}, Function::Specs fs = {}, ArgumentFlag isVarArgs = FixedArgs );
[23f99e1]146
[8a5530c]147 const Type * get_type() const override;
[e0e9a0b]148 void set_type( const Type * t ) override;
[23f99e1]149
150 bool has_body() const { return stmts; }
151
[07de76b]152 const DeclWithType * accept( Visitor & v ) const override { return v.visit( this ); }
[23f99e1]153private:
154 FunctionDecl * clone() const override { return new FunctionDecl( *this ); }
[f3cc5b6]155 MUTATE_FRIEND
[77a3f41]156};
157
[360b2e13]158/// Base class for named type aliases
159class NamedTypeDecl : public Decl {
160public:
161 ptr<Type> base;
162 std::vector<ptr<DeclWithType>> assertions;
163
[7030dab]164 NamedTypeDecl(
[e0e9a0b]165 const CodeLocation & loc, const std::string & name, Storage::Classes storage,
166 const Type * b, Linkage::Spec spec = Linkage::Cforall )
[6a45bd78]167 : Decl( loc, name, storage, spec ), base( b ), assertions() {}
[360b2e13]168
169 /// Produces a name for the kind of alias
[312029a]170 virtual const char * typeString() const = 0;
[360b2e13]171
172private:
173 NamedTypeDecl* clone() const override = 0;
[f3cc5b6]174 MUTATE_FRIEND
[360b2e13]175};
176
177/// Cforall type variable: `dtype T`
178class TypeDecl final : public NamedTypeDecl {
[07de76b]179 public:
[6e50a6b]180 enum Kind { Dtype, DStype, Otype, Ftype, Ttype, Dimension, NUMBER_OF_KINDS };
[07de76b]181
182 Kind kind;
[360b2e13]183 bool sized;
184 ptr<Type> init;
185
[7030dab]186 TypeDecl(
187 const CodeLocation & loc, const std::string & name, Storage::Classes storage,
[e3bc51c]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 ),
[9e1d485]190 init( i ) {}
[360b2e13]191
[312029a]192 const char * typeString() const override;
[360b2e13]193 /// Produces a name for generated code
[312029a]194 const char * genTypeString() const;
[360b2e13]195
[9e1d485]196 /// convenience accessor to match Type::isComplete()
[3606fe4]197 bool isComplete() const { return sized; }
[9e1d485]198
[23f99e1]199 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
[07de76b]200 private:
[23f99e1]201 TypeDecl * clone() const override { return new TypeDecl{ *this }; }
[f3cc5b6]202 MUTATE_FRIEND
[360b2e13]203};
204
[93c10de]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 & );
[d76c588]221
[360b2e13]222/// C-style typedef `typedef Foo Bar`
223class TypedefDecl final : public NamedTypeDecl {
224public:
[e0115286]225 TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
[360b2e13]226 Type* b, Linkage::Spec spec = Linkage::Cforall )
227 : NamedTypeDecl( loc, name, storage, b, spec ) {}
228
[312029a]229 const char * typeString() const override { return "typedef"; }
[360b2e13]230
[23f99e1]231 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
[360b2e13]232private:
[23f99e1]233 TypedefDecl * clone() const override { return new TypedefDecl{ *this }; }
[f3cc5b6]234 MUTATE_FRIEND
[360b2e13]235};
236
[a300e4a]237/// Aggregate type declaration base class
238class AggregateDecl : public Decl {
239public:
[312029a]240 enum Aggregate { Struct, Union, Enum, Exception, Trait, Generator, Coroutine, Monitor, Thread, NoAggregate };
241 static const char * aggrString( Aggregate aggr );
242
[a300e4a]243 std::vector<ptr<Decl>> members;
[54e41b3]244 std::vector<ptr<TypeDecl>> params;
[a300e4a]245 std::vector<ptr<Attribute>> attributes;
246 bool body = false;
247 readonly<AggregateDecl> parent = {};
248
[14cebb7a]249 AggregateDecl( const CodeLocation& loc, const std::string& name,
[a300e4a]250 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
[54e41b3]251 : Decl( loc, name, Storage::Classes{}, linkage ), members(), params(),
[a300e4a]252 attributes( std::move(attrs) ) {}
[14cebb7a]253
[a300e4a]254 AggregateDecl* set_body( bool b ) { body = b; return this; }
255
[ed3935da]256 /// Produces a name for the kind of aggregate
[312029a]257 virtual const char * typeString() const = 0;
[ed3935da]258
[f3cc5b6]259private:
260 AggregateDecl * clone() const override = 0;
261 MUTATE_FRIEND
[a300e4a]262};
263
264/// struct declaration `struct Foo { ... };`
265class StructDecl final : public AggregateDecl {
266public:
[312029a]267 Aggregate kind;
[a300e4a]268
[14cebb7a]269 StructDecl( const CodeLocation& loc, const std::string& name,
[312029a]270 Aggregate kind = Struct,
[a300e4a]271 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
272 : AggregateDecl( loc, name, std::move(attrs), linkage ), kind( kind ) {}
273
[3cc1111]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 ; }
[a300e4a]278
[23f99e1]279 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
[ed3935da]280
[312029a]281 const char * typeString() const override { return aggrString( kind ); }
[ed3935da]282
[a300e4a]283private:
[23f99e1]284 StructDecl * clone() const override { return new StructDecl{ *this }; }
[f3cc5b6]285 MUTATE_FRIEND
[a300e4a]286};
287
288/// union declaration `union Foo { ... };`
289class UnionDecl final : public AggregateDecl {
290public:
[14cebb7a]291 UnionDecl( const CodeLocation& loc, const std::string& name,
[a300e4a]292 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
293 : AggregateDecl( loc, name, std::move(attrs), linkage ) {}
294
[23f99e1]295 const Decl * accept( Visitor& v ) const override { return v.visit( this ); }
[ed3935da]296
[312029a]297 const char * typeString() const override { return aggrString( Union ); }
[ed3935da]298
[a300e4a]299private:
[23f99e1]300 UnionDecl * clone() const override { return new UnionDecl{ *this }; }
[f3cc5b6]301 MUTATE_FRIEND
[a300e4a]302};
303
[90be0cf]304/// Enumeration attribute kind.
[af746cc]305enum class EnumAttribute{ Value, Posn, Label };
[90be0cf]306
[a300e4a]307/// enum declaration `enum Foo { ... };`
308class EnumDecl final : public AggregateDecl {
309public:
[5ccc733]310 // isCfa indicated if the enum has a declaration like:
[94c98f0e]311 // enum (type_optional) Name {...}
[5ccc733]312 bool isCfa;
[8c55d34]313 // if isCfa == true && base.get() == nullptr, it is a "opaque" enum
[a1da039]314 ptr<Type> base;
[e4d7c1c]315 enum class EnumHiding { Visible, Hide } hide;
[85855b0]316 std::vector< ast::ptr<ast::EnumInstType>> inlinedDecl; // child enums
317
[5ccc733]318 EnumDecl( const CodeLocation& loc, const std::string& name, bool isCfa = false,
[b0d9ff7]319 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall,
[e4d7c1c]320 Type const * base = nullptr, EnumHiding hide = EnumHiding::Hide,
[7b71402]321 std::unordered_map< std::string, long long > enumValues = std::unordered_map< std::string, long long >() )
[5ccc733]322 : AggregateDecl( loc, name, std::move(attrs), linkage ), isCfa(isCfa), base(base), hide(hide), enumValues(enumValues) {}
[a300e4a]323
324 /// gets the integer value for this enumerator, returning true iff value found
[f135b50]325 // Maybe it is not used in producing the enum value
[9d6e7fa9]326 bool valueOf( const Decl * enumerator, long long& value ) const;
[a300e4a]327
[23f99e1]328 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
[ed3935da]329
[312029a]330 const char * typeString() const override { return aggrString( Enum ); }
[ed3935da]331
[5ccc733]332 bool isTyped() const;
[8c55d34]333 bool isOpaque() const;
[a300e4a]334private:
[23f99e1]335 EnumDecl * clone() const override { return new EnumDecl{ *this }; }
[f3cc5b6]336 MUTATE_FRIEND
[a300e4a]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:
[14cebb7a]345 TraitDecl( const CodeLocation& loc, const std::string& name,
[a300e4a]346 std::vector<ptr<Attribute>>&& attrs = {}, Linkage::Spec linkage = Linkage::Cforall )
347 : AggregateDecl( loc, name, std::move(attrs), linkage ) {}
348
[23f99e1]349 const Decl * accept( Visitor & v ) const override { return v.visit( this ); }
[ed3935da]350
[312029a]351 const char * typeString() const override { return "trait"; }
[ed3935da]352
[a300e4a]353private:
[23f99e1]354 TraitDecl * clone() const override { return new TraitDecl{ *this }; }
[f3cc5b6]355 MUTATE_FRIEND
[2bb4a01]356};
357
[e67991f]358/// With statement `with (...) ...`
[6a0b043]359/// This is a statement lexically, but a Decl is needed for the SymbolTable.
[e67991f]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
[94c98f0e]374/// Assembly declaration: `asm ... ( "..." : ... )`
[a1da039]375class AsmDecl final : public Decl {
[23f99e1]376public:
377 ptr<AsmStmt> stmt;
378
[07de76b]379 AsmDecl( const CodeLocation & loc, AsmStmt * stmt )
[a1da039]380 : Decl( loc, "", {}, Linkage::C ), stmt(stmt) {}
[23f99e1]381
[07de76b]382 const AsmDecl * accept( Visitor & v ) const override { return v.visit( this ); }
[23f99e1]383private:
[07de76b]384 AsmDecl * clone() const override { return new AsmDecl( *this ); }
[f3cc5b6]385 MUTATE_FRIEND
[23f99e1]386};
387
[2d019af]388/// C-preprocessor directive `#...`
[a1da039]389class DirectiveDecl final : public Decl {
[2d019af]390public:
391 ptr<DirectiveStmt> stmt;
392
393 DirectiveDecl( const CodeLocation & loc, DirectiveStmt * stmt )
[a1da039]394 : Decl( loc, "", {}, Linkage::C ), stmt(stmt) {}
[2d019af]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
[19a8c40]402/// Static Assertion `_Static_assert( ... , ... );`
[a1da039]403class StaticAssertDecl final : public Decl {
[23f99e1]404public:
[112fe04]405 ptr<Expr> cond;
[23f99e1]406 ptr<ConstantExpr> msg; // string literal
407
408 StaticAssertDecl( const CodeLocation & loc, const Expr * condition, const ConstantExpr * msg )
[a1da039]409 : Decl( loc, "", {}, Linkage::C ), cond( condition ), msg( msg ) {}
[23f99e1]410
[07de76b]411 const StaticAssertDecl * accept( Visitor & v ) const override { return v.visit( this ); }
[23f99e1]412private:
413 StaticAssertDecl * clone() const override { return new StaticAssertDecl( *this ); }
[f3cc5b6]414 MUTATE_FRIEND
[23f99e1]415};
[e0115286]416
[19a8c40]417/// Inline Member Declaration `inline TypeName;`
[71806e0]418class InlineMemberDecl final : public DeclWithType {
[e874605]419public:
420 ptr<Type> type;
421
[71806e0]422 InlineMemberDecl( const CodeLocation & loc, const std::string & name, const Type * type,
[e874605]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:
[71806e0]432 InlineMemberDecl * clone() const override { return new InlineMemberDecl{ *this }; }
[e874605]433 MUTATE_FRIEND
434};
[19a8c40]435
[2bb4a01]436}
437
[f3cc5b6]438#undef MUTATE_FRIEND
439
[2bb4a01]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.