Changes in / [7e89526:2a5e8a6]
- Location:
- src
- Files:
-
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
src/AST/Bitfield.hpp
r7e89526 r2a5e8a6 22 22 /// does not allow it. Requires type to have `unsigned val` field 23 23 /// @param BFType Name of containing type 24 #define MakeBitfield( BFType ) \ 25 constexpr BFType() : val( 0 ) {} \ 26 constexpr BFType( unsigned int v ) : val( v ) {} \ 27 bool operator[]( unsigned int i ) const { return val & (1 << i); } \ 28 bool any() const { return val != 0; } \ 29 void reset() { val = 0; } \ 30 int ffs() { return ::ffs( val ) - 1; } \ 31 BFType operator&=( BFType other ) { \ 32 val &= other.val; return *this; \ 33 } \ 34 BFType operator&( BFType other ) const { \ 35 BFType q = other; \ 36 q &= *this; \ 37 return q; \ 38 } \ 39 BFType operator|=( BFType other ) { \ 40 val |= other.val; return *this; \ 41 } \ 42 BFType operator|( BFType other ) const { \ 43 BFType q = other; \ 44 q |= *this; \ 45 return q; \ 46 } \ 47 BFType operator-=( BFType other ) { \ 48 val &= ~other.val; return *this; \ 24 template<typename T> 25 struct bitfield : public T { 26 static_assert(sizeof(T) == sizeof(unsigned int), "Type has incorrect size"); 27 using T::val; 28 using val_t = decltype(val); 29 30 constexpr bitfield() : T( 0 ) {} 31 constexpr bitfield( val_t v ) : T( v ) {} 32 33 bool operator[]( val_t i ) const { return val & (1 << i); } 34 bool any() const { return val != 0; } 35 void reset() { val = 0; } 36 int ffs() { return ::ffs( val ) - 1; } 37 38 bitfield operator&=( bitfield other ) { 39 val &= other.val; return *this; 49 40 } 41 bitfield operator&( bitfield other ) const { 42 bitfield q = other; 43 q &= *this; 44 return q; 45 } 46 bitfield operator|=( bitfield other ) { 47 val |= other.val; return *this; 48 } 49 bitfield operator|( bitfield other ) const { 50 bitfield q = other; 51 q |= *this; 52 return q; 53 } 54 bitfield operator-=( bitfield other ) { 55 val &= ~other.val; return *this; 56 } 57 }; 50 58 51 59 /// Adds default printing operator to a bitfield type. 52 60 /// Include in definition to add print function, requires other bitfield operators. 53 61 /// @param N Number of bits in bitfield 54 #define MakeBitfieldPrint( N ) \ 55 static const char* Names[]; \ 56 void print( std::ostream & os ) const { \ 57 if ( (*this).any() ) { \ 58 for ( unsigned int i = 0; i < N; i += 1 ) { \ 59 if ( (*this)[i] ) { \ 60 os << Names[i] << ' '; \ 61 } \ 62 } \ 63 } \ 62 #define MakeBitfieldPrint( N ) \ 63 static const char* Names[]; \ 64 \ 65 void print( std::ostream & os ) const { \ 66 if ( (*this).any() ) { \ 67 for ( unsigned int i = 0; i < N; i += 1 ) { \ 68 if ( (*this)[i] ) { \ 69 os << Names[i] << ' '; \ 70 } \ 71 } \ 72 } \ 64 73 } 65 74 -
src/AST/Decl.hpp
r7e89526 r2a5e8a6 122 122 std::vector<ptr<DeclWithType>> assertions; 123 123 124 NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 124 NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 125 125 Type* b, Linkage::Spec spec = Linkage::Cforall ) 126 126 : Decl( loc, name, storage, spec ), base( b ), parameters(), assertions() {} … … 149 149 Data( TypeDecl* d ) : kind( d->kind ), isComplete( d->sized ) {} 150 150 Data( Kind k, bool c ) : kind( k ), isComplete( c ) {} 151 Data( const Data& d1, const Data& d2 ) 151 Data( const Data& d1, const Data& d2 ) 152 152 : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {} 153 153 … … 158 158 }; 159 159 160 TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b, 160 TypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, Type* b, 161 161 Kind k, bool s, Type* i = nullptr ) 162 162 : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ), init( i ) {} … … 174 174 class TypedefDecl final : public NamedTypeDecl { 175 175 public: 176 TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 176 TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 177 177 Type* b, Linkage::Spec spec = Linkage::Cforall ) 178 178 : NamedTypeDecl( loc, name, storage, b, spec ) {} … … 275 275 }; 276 276 277 278 //================================================================================================= 279 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 280 /// remove only if there is a better solution 281 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 282 /// forward declarations 283 inline void increment( const class Decl * node, Node::ref_type ref ) { node->increment(ref); } 284 inline void decrement( const class Decl * node, Node::ref_type ref ) { node->decrement(ref); } 285 inline void increment( const class DeclWithType * node, Node::ref_type ref ) { node->increment(ref); } 286 inline void decrement( const class DeclWithType * node, Node::ref_type ref ) { node->decrement(ref); } 287 inline void increment( const class ObjectDecl * node, Node::ref_type ref ) { node->increment(ref); } 288 inline void decrement( const class ObjectDecl * node, Node::ref_type ref ) { node->decrement(ref); } 289 inline void increment( const class FunctionDecl * node, Node::ref_type ref ) { node->increment(ref); } 290 inline void decrement( const class FunctionDecl * node, Node::ref_type ref ) { node->decrement(ref); } 291 inline void increment( const class AggregateDecl * node, Node::ref_type ref ) { node->increment(ref); } 292 inline void decrement( const class AggregateDecl * node, Node::ref_type ref ) { node->decrement(ref); } 293 inline void increment( const class StructDecl * node, Node::ref_type ref ) { node->increment(ref); } 294 inline void decrement( const class StructDecl * node, Node::ref_type ref ) { node->decrement(ref); } 295 inline void increment( const class UnionDecl * node, Node::ref_type ref ) { node->increment(ref); } 296 inline void decrement( const class UnionDecl * node, Node::ref_type ref ) { node->decrement(ref); } 297 inline void increment( const class EnumDecl * node, Node::ref_type ref ) { node->increment(ref); } 298 inline void decrement( const class EnumDecl * node, Node::ref_type ref ) { node->decrement(ref); } 299 inline void increment( const class TraitDecl * node, Node::ref_type ref ) { node->increment(ref); } 300 inline void decrement( const class TraitDecl * node, Node::ref_type ref ) { node->decrement(ref); } 301 inline void increment( const class NamedTypeDecl * node, Node::ref_type ref ) { node->increment(ref); } 302 inline void decrement( const class NamedTypeDecl * node, Node::ref_type ref ) { node->decrement(ref); } 303 inline void increment( const class TypeDecl * node, Node::ref_type ref ) { node->increment(ref); } 304 inline void decrement( const class TypeDecl * node, Node::ref_type ref ) { node->decrement(ref); } 305 inline void increment( const class FtypeDecl * node, Node::ref_type ref ) { node->increment(ref); } 306 inline void decrement( const class FtypeDecl * node, Node::ref_type ref ) { node->decrement(ref); } 307 inline void increment( const class DtypeDecl * node, Node::ref_type ref ) { node->increment(ref); } 308 inline void decrement( const class DtypeDecl * node, Node::ref_type ref ) { node->decrement(ref); } 309 inline void increment( const class TypedefDecl * node, Node::ref_type ref ) { node->increment(ref); } 310 inline void decrement( const class TypedefDecl * node, Node::ref_type ref ) { node->decrement(ref); } 311 inline void increment( const class AsmDecl * node, Node::ref_type ref ) { node->increment(ref); } 312 inline void decrement( const class AsmDecl * node, Node::ref_type ref ) { node->decrement(ref); } 313 inline void increment( const class StaticAssertDecl * node, Node::ref_type ref ) { node->increment(ref); } 314 inline void decrement( const class StaticAssertDecl * node, Node::ref_type ref ) { node->decrement(ref); } 315 277 316 } 278 317 -
src/AST/FunctionSpec.hpp
r7e89526 r2a5e8a6 31 31 32 32 /// Bitflag type for storage classes 33 union Specs { 34 unsigned int val; 35 struct { 36 bool is_inline : 1; 37 bool is_noreturn : 1; 38 bool is_fortran : 1; 33 struct spec_flags { 34 union { 35 unsigned int val; 36 struct { 37 bool is_inline : 1; 38 bool is_noreturn : 1; 39 bool is_fortran : 1; 40 }; 41 42 // MakeBitfieldPrint( NumSpecs ) 39 43 }; 40 44 41 MakeBitfield( Specs ) 42 MakeBitfieldPrint( NumSpecs ) 45 constexpr spec_flags( unsigned int val ) : val(val) {} 43 46 }; 44 47 48 using Specs = bitfield<spec_flags>; 45 49 } 46 50 } -
src/AST/Fwd.hpp
r7e89526 r2a5e8a6 16 16 #pragma once 17 17 18 #include "AST/Node.hpp" 19 18 20 namespace ast { 19 21 20 class Node;21 22 class ParseNode; 22 23 … … 137 138 class TypeSubstitution; 138 139 140 //================================================================================================= 141 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 142 /// remove only if there is a better solution 143 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 144 /// forward declarations 145 inline void decrement( const class Node * node, Node::ref_type ref ) { node->decrement(ref); } 146 inline void increment( const class Node * node, Node::ref_type ref ) { node->increment(ref); } 147 inline void increment( const class ParseNode *, Node::ref_type ); 148 inline void decrement( const class ParseNode *, Node::ref_type ); 149 inline void increment( const class Decl *, Node::ref_type ); 150 inline void decrement( const class Decl *, Node::ref_type ); 151 inline void increment( const class DeclWithType *, Node::ref_type ); 152 inline void decrement( const class DeclWithType *, Node::ref_type ); 153 inline void increment( const class ObjectDecl *, Node::ref_type ); 154 inline void decrement( const class ObjectDecl *, Node::ref_type ); 155 inline void increment( const class FunctionDecl *, Node::ref_type ); 156 inline void decrement( const class FunctionDecl *, Node::ref_type ); 157 inline void increment( const class AggregateDecl *, Node::ref_type ); 158 inline void decrement( const class AggregateDecl *, Node::ref_type ); 159 inline void increment( const class StructDecl *, Node::ref_type ); 160 inline void decrement( const class StructDecl *, Node::ref_type ); 161 inline void increment( const class UnionDecl *, Node::ref_type ); 162 inline void decrement( const class UnionDecl *, Node::ref_type ); 163 inline void increment( const class EnumDecl *, Node::ref_type ); 164 inline void decrement( const class EnumDecl *, Node::ref_type ); 165 inline void increment( const class TraitDecl *, Node::ref_type ); 166 inline void decrement( const class TraitDecl *, Node::ref_type ); 167 inline void increment( const class NamedTypeDecl *, Node::ref_type ); 168 inline void decrement( const class NamedTypeDecl *, Node::ref_type ); 169 inline void increment( const class TypeDecl *, Node::ref_type ); 170 inline void decrement( const class TypeDecl *, Node::ref_type ); 171 inline void increment( const class FtypeDecl *, Node::ref_type ); 172 inline void decrement( const class FtypeDecl *, Node::ref_type ); 173 inline void increment( const class DtypeDecl *, Node::ref_type ); 174 inline void decrement( const class DtypeDecl *, Node::ref_type ); 175 inline void increment( const class TypedefDecl *, Node::ref_type ); 176 inline void decrement( const class TypedefDecl *, Node::ref_type ); 177 inline void increment( const class AsmDecl *, Node::ref_type ); 178 inline void decrement( const class AsmDecl *, Node::ref_type ); 179 inline void increment( const class StaticAssertDecl *, Node::ref_type ); 180 inline void decrement( const class StaticAssertDecl *, Node::ref_type ); 181 inline void increment( const class Stmt *, Node::ref_type ); 182 inline void decrement( const class Stmt *, Node::ref_type ); 183 inline void increment( const class CompoundStmt *, Node::ref_type ); 184 inline void decrement( const class CompoundStmt *, Node::ref_type ); 185 inline void increment( const class ExprStmt *, Node::ref_type ); 186 inline void decrement( const class ExprStmt *, Node::ref_type ); 187 inline void increment( const class AsmStmt *, Node::ref_type ); 188 inline void decrement( const class AsmStmt *, Node::ref_type ); 189 inline void increment( const class DirectiveStmt *, Node::ref_type ); 190 inline void decrement( const class DirectiveStmt *, Node::ref_type ); 191 inline void increment( const class IfStmt *, Node::ref_type ); 192 inline void decrement( const class IfStmt *, Node::ref_type ); 193 inline void increment( const class WhileStmt *, Node::ref_type ); 194 inline void decrement( const class WhileStmt *, Node::ref_type ); 195 inline void increment( const class ForStmt *, Node::ref_type ); 196 inline void decrement( const class ForStmt *, Node::ref_type ); 197 inline void increment( const class SwitchStmt *, Node::ref_type ); 198 inline void decrement( const class SwitchStmt *, Node::ref_type ); 199 inline void increment( const class CaseStmt *, Node::ref_type ); 200 inline void decrement( const class CaseStmt *, Node::ref_type ); 201 inline void increment( const class BranchStmt *, Node::ref_type ); 202 inline void decrement( const class BranchStmt *, Node::ref_type ); 203 inline void increment( const class ReturnStmt *, Node::ref_type ); 204 inline void decrement( const class ReturnStmt *, Node::ref_type ); 205 inline void increment( const class ThrowStmt *, Node::ref_type ); 206 inline void decrement( const class ThrowStmt *, Node::ref_type ); 207 inline void increment( const class TryStmt *, Node::ref_type ); 208 inline void decrement( const class TryStmt *, Node::ref_type ); 209 inline void increment( const class CatchStmt *, Node::ref_type ); 210 inline void decrement( const class CatchStmt *, Node::ref_type ); 211 inline void increment( const class FinallyStmt *, Node::ref_type ); 212 inline void decrement( const class FinallyStmt *, Node::ref_type ); 213 inline void increment( const class WaitForStmt *, Node::ref_type ); 214 inline void decrement( const class WaitForStmt *, Node::ref_type ); 215 inline void increment( const class WithStmt *, Node::ref_type ); 216 inline void decrement( const class WithStmt *, Node::ref_type ); 217 inline void increment( const class DeclStmt *, Node::ref_type ); 218 inline void decrement( const class DeclStmt *, Node::ref_type ); 219 inline void increment( const class NullStmt *, Node::ref_type ); 220 inline void decrement( const class NullStmt *, Node::ref_type ); 221 inline void increment( const class ImplicitCtorDtorStmt *, Node::ref_type ); 222 inline void decrement( const class ImplicitCtorDtorStmt *, Node::ref_type ); 223 inline void increment( const class Expr *, Node::ref_type ); 224 inline void decrement( const class Expr *, Node::ref_type ); 225 inline void increment( const class ApplicationExpr *, Node::ref_type ); 226 inline void decrement( const class ApplicationExpr *, Node::ref_type ); 227 inline void increment( const class UntypedExpr *, Node::ref_type ); 228 inline void decrement( const class UntypedExpr *, Node::ref_type ); 229 inline void increment( const class NameExpr *, Node::ref_type ); 230 inline void decrement( const class NameExpr *, Node::ref_type ); 231 inline void increment( const class AddressExpr *, Node::ref_type ); 232 inline void decrement( const class AddressExpr *, Node::ref_type ); 233 inline void increment( const class LabelAddressExpr *, Node::ref_type ); 234 inline void decrement( const class LabelAddressExpr *, Node::ref_type ); 235 inline void increment( const class CastExpr *, Node::ref_type ); 236 inline void decrement( const class CastExpr *, Node::ref_type ); 237 inline void increment( const class KeywordCastExpr *, Node::ref_type ); 238 inline void decrement( const class KeywordCastExpr *, Node::ref_type ); 239 inline void increment( const class VirtualCastExpr *, Node::ref_type ); 240 inline void decrement( const class VirtualCastExpr *, Node::ref_type ); 241 inline void increment( const class MemberExpr *, Node::ref_type ); 242 inline void decrement( const class MemberExpr *, Node::ref_type ); 243 inline void increment( const class UntypedMemberExpr *, Node::ref_type ); 244 inline void decrement( const class UntypedMemberExpr *, Node::ref_type ); 245 inline void increment( const class VariableExpr *, Node::ref_type ); 246 inline void decrement( const class VariableExpr *, Node::ref_type ); 247 inline void increment( const class ConstantExpr *, Node::ref_type ); 248 inline void decrement( const class ConstantExpr *, Node::ref_type ); 249 inline void increment( const class SizeofExpr *, Node::ref_type ); 250 inline void decrement( const class SizeofExpr *, Node::ref_type ); 251 inline void increment( const class AlignofExpr *, Node::ref_type ); 252 inline void decrement( const class AlignofExpr *, Node::ref_type ); 253 inline void increment( const class UntypedOffsetofExpr *, Node::ref_type ); 254 inline void decrement( const class UntypedOffsetofExpr *, Node::ref_type ); 255 inline void increment( const class OffsetofExpr *, Node::ref_type ); 256 inline void decrement( const class OffsetofExpr *, Node::ref_type ); 257 inline void increment( const class OffsetPackExpr *, Node::ref_type ); 258 inline void decrement( const class OffsetPackExpr *, Node::ref_type ); 259 inline void increment( const class AttrExpr *, Node::ref_type ); 260 inline void decrement( const class AttrExpr *, Node::ref_type ); 261 inline void increment( const class LogicalExpr *, Node::ref_type ); 262 inline void decrement( const class LogicalExpr *, Node::ref_type ); 263 inline void increment( const class ConditionalExpr *, Node::ref_type ); 264 inline void decrement( const class ConditionalExpr *, Node::ref_type ); 265 inline void increment( const class CommaExpr *, Node::ref_type ); 266 inline void decrement( const class CommaExpr *, Node::ref_type ); 267 inline void increment( const class TypeExpr *, Node::ref_type ); 268 inline void decrement( const class TypeExpr *, Node::ref_type ); 269 inline void increment( const class AsmExpr *, Node::ref_type ); 270 inline void decrement( const class AsmExpr *, Node::ref_type ); 271 inline void increment( const class ImplicitCopyCtorExpr *, Node::ref_type ); 272 inline void decrement( const class ImplicitCopyCtorExpr *, Node::ref_type ); 273 inline void increment( const class ConstructorExpr *, Node::ref_type ); 274 inline void decrement( const class ConstructorExpr *, Node::ref_type ); 275 inline void increment( const class CompoundLiteralExpr *, Node::ref_type ); 276 inline void decrement( const class CompoundLiteralExpr *, Node::ref_type ); 277 inline void increment( const class UntypedValofExpr *, Node::ref_type ); 278 inline void decrement( const class UntypedValofExpr *, Node::ref_type ); 279 inline void increment( const class RangeExpr *, Node::ref_type ); 280 inline void decrement( const class RangeExpr *, Node::ref_type ); 281 inline void increment( const class UntypedTupleExpr *, Node::ref_type ); 282 inline void decrement( const class UntypedTupleExpr *, Node::ref_type ); 283 inline void increment( const class TupleExpr *, Node::ref_type ); 284 inline void decrement( const class TupleExpr *, Node::ref_type ); 285 inline void increment( const class TupleIndexExpr *, Node::ref_type ); 286 inline void decrement( const class TupleIndexExpr *, Node::ref_type ); 287 inline void increment( const class TupleAssignExpr *, Node::ref_type ); 288 inline void decrement( const class TupleAssignExpr *, Node::ref_type ); 289 inline void increment( const class StmtExpr *, Node::ref_type ); 290 inline void decrement( const class StmtExpr *, Node::ref_type ); 291 inline void increment( const class UniqueExpr *, Node::ref_type ); 292 inline void decrement( const class UniqueExpr *, Node::ref_type ); 293 inline void increment( const class UntypedInitExpr *, Node::ref_type ); 294 inline void decrement( const class UntypedInitExpr *, Node::ref_type ); 295 inline void increment( const class InitExpr *, Node::ref_type ); 296 inline void decrement( const class InitExpr *, Node::ref_type ); 297 inline void increment( const class DeletedExpr *, Node::ref_type ); 298 inline void decrement( const class DeletedExpr *, Node::ref_type ); 299 inline void increment( const class DefaultArgExpr *, Node::ref_type ); 300 inline void decrement( const class DefaultArgExpr *, Node::ref_type ); 301 inline void increment( const class GenericExpr *, Node::ref_type ); 302 inline void decrement( const class GenericExpr *, Node::ref_type ); 303 inline void increment( const class Type *, Node::ref_type ); 304 inline void decrement( const class Type *, Node::ref_type ); 305 inline void increment( const class VoidType *, Node::ref_type ); 306 inline void decrement( const class VoidType *, Node::ref_type ); 307 inline void increment( const class BasicType *, Node::ref_type ); 308 inline void decrement( const class BasicType *, Node::ref_type ); 309 inline void increment( const class PointerType *, Node::ref_type ); 310 inline void decrement( const class PointerType *, Node::ref_type ); 311 inline void increment( const class ArrayType *, Node::ref_type ); 312 inline void decrement( const class ArrayType *, Node::ref_type ); 313 inline void increment( const class ReferenceType *, Node::ref_type ); 314 inline void decrement( const class ReferenceType *, Node::ref_type ); 315 inline void increment( const class QualifiedType *, Node::ref_type ); 316 inline void decrement( const class QualifiedType *, Node::ref_type ); 317 inline void increment( const class FunctionType *, Node::ref_type ); 318 inline void decrement( const class FunctionType *, Node::ref_type ); 319 inline void increment( const class ReferenceToType *, Node::ref_type ); 320 inline void decrement( const class ReferenceToType *, Node::ref_type ); 321 inline void increment( const class StructInstType *, Node::ref_type ); 322 inline void decrement( const class StructInstType *, Node::ref_type ); 323 inline void increment( const class UnionInstType *, Node::ref_type ); 324 inline void decrement( const class UnionInstType *, Node::ref_type ); 325 inline void increment( const class EnumInstType *, Node::ref_type ); 326 inline void decrement( const class EnumInstType *, Node::ref_type ); 327 inline void increment( const class TraitInstType *, Node::ref_type ); 328 inline void decrement( const class TraitInstType *, Node::ref_type ); 329 inline void increment( const class TypeInstType *, Node::ref_type ); 330 inline void decrement( const class TypeInstType *, Node::ref_type ); 331 inline void increment( const class TupleType *, Node::ref_type ); 332 inline void decrement( const class TupleType *, Node::ref_type ); 333 inline void increment( const class TypeofType *, Node::ref_type ); 334 inline void decrement( const class TypeofType *, Node::ref_type ); 335 inline void increment( const class AttrType *, Node::ref_type ); 336 inline void decrement( const class AttrType *, Node::ref_type ); 337 inline void increment( const class VarArgsType *, Node::ref_type ); 338 inline void decrement( const class VarArgsType *, Node::ref_type ); 339 inline void increment( const class ZeroType *, Node::ref_type ); 340 inline void decrement( const class ZeroType *, Node::ref_type ); 341 inline void increment( const class OneType *, Node::ref_type ); 342 inline void decrement( const class OneType *, Node::ref_type ); 343 inline void increment( const class GlobalScopeType *, Node::ref_type ); 344 inline void decrement( const class GlobalScopeType *, Node::ref_type ); 345 inline void increment( const class Designation *, Node::ref_type ); 346 inline void decrement( const class Designation *, Node::ref_type ); 347 inline void increment( const class Init *, Node::ref_type ); 348 inline void decrement( const class Init *, Node::ref_type ); 349 inline void increment( const class SingleInit *, Node::ref_type ); 350 inline void decrement( const class SingleInit *, Node::ref_type ); 351 inline void increment( const class ListInit *, Node::ref_type ); 352 inline void decrement( const class ListInit *, Node::ref_type ); 353 inline void increment( const class ConstructorInit *, Node::ref_type ); 354 inline void decrement( const class ConstructorInit *, Node::ref_type ); 355 inline void increment( const class Constant *, Node::ref_type ); 356 inline void decrement( const class Constant *, Node::ref_type ); 357 inline void increment( const class Label *, Node::ref_type ); 358 inline void decrement( const class Label *, Node::ref_type ); 359 inline void increment( const class Attribute *, Node::ref_type ); 360 inline void decrement( const class Attribute *, Node::ref_type ); 361 inline void increment( const class TypeSubstitution *, Node::ref_type ); 362 inline void decrement( const class TypeSubstitution *, Node::ref_type ); 363 139 364 typedef unsigned int UniqueId; 140 365 -
src/AST/Init.hpp
r7e89526 r2a5e8a6 28 28 class Stmt; 29 29 30 /// List of designator (NameExpr, VariableExpr, and ConstantExpr) expressions that specify an 30 /// List of designator (NameExpr, VariableExpr, and ConstantExpr) expressions that specify an 31 31 /// object being initialized 32 32 class Designation final : public ParseNode { … … 34 34 std::vector<ptr<Expr>> designators; 35 35 36 Designation( const CodeLocation& loc, std::vector<ptr<Expr>>&& ds = {} ) 36 Designation( const CodeLocation& loc, std::vector<ptr<Expr>>&& ds = {} ) 37 37 : ParseNode( loc ), designators( std::move(ds) ) {} 38 38 … … 60 60 ptr<Expr> value; 61 61 62 SingleInit( const CodeLocation& loc, Expr* val, bool mc = false ) 62 SingleInit( const CodeLocation& loc, Expr* val, bool mc = false ) 63 63 : Init( loc, mc ), value( val ) {} 64 64 … … 77 77 std::vector<ptr<Designation>> designations; 78 78 79 ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is, 79 ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is, 80 80 std::vector<ptr<Designation>>&& ds = {}, bool mc = false ); 81 81 82 82 using iterator = std::vector<ptr<Init>>::iterator; 83 83 using const_iterator = std::vector<ptr<Init>>::const_iterator; … … 93 93 94 94 /// Either a constructor expression or a C-style initializer. 95 /// Should not be necessary to create manually; instead set `maybeConstructed` true on `SingleInit` 95 /// Should not be necessary to create manually; instead set `maybeConstructed` true on `SingleInit` 96 96 /// or `ListInit` if the object should be constructed. 97 97 class ConstructorInit final : public Init { … … 99 99 ptr<Stmt> ctor; 100 100 ptr<Stmt> dtor; 101 /// C-style initializer made up of SingleInit/ListInit nodes to use as a fallback if an 101 /// C-style initializer made up of SingleInit/ListInit nodes to use as a fallback if an 102 102 /// appropriate constructor definition is not found by the resolver. 103 103 ptr<Init> init; … … 111 111 }; 112 112 113 114 //================================================================================================= 115 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 116 /// remove only if there is a better solution 117 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 118 /// forward declarations 119 inline void increment( const class Init * node, Node::ref_type ref ) { node->increment( ref ); } 120 inline void decrement( const class Init * node, Node::ref_type ref ) { node->decrement( ref ); } 121 inline void increment( const class SingleInit * node, Node::ref_type ref ) { node->increment( ref ); } 122 inline void decrement( const class SingleInit * node, Node::ref_type ref ) { node->decrement( ref ); } 123 inline void increment( const class ListInit * node, Node::ref_type ref ) { node->increment( ref ); } 124 inline void decrement( const class ListInit * node, Node::ref_type ref ) { node->decrement( ref ); } 125 inline void increment( const class ConstructorInit * node, Node::ref_type ref ) { node->increment( ref ); } 126 inline void decrement( const class ConstructorInit * node, Node::ref_type ref ) { node->decrement( ref ); } 113 127 } 114 128 -
src/AST/Label.hpp
r7e89526 r2a5e8a6 25 25 namespace ast { 26 26 27 27 class Attribute; 28 28 29 30 31 32 33 34 29 /// Named labels for statements 30 class Label { 31 public: 32 CodeLocation location; 33 std::string name; 34 std::vector< ptr<Attribute> > attributes; 35 35 36 37 38 36 Label( CodeLocation loc, const std::string& name = "", 37 const std::vector<ptr<Attribute>>& attrs = std::vector<ptr<Attribute>>{} ) 38 : location( loc ), name( name ), attributes( attrs ) {} 39 39 40 41 42 40 operator std::string () const { return name; } 41 bool empty() { return name.empty(); } 42 }; 43 43 44 45 46 44 inline bool operator== ( const Label& l1, const Label& l2 ) { return l1.name == l2.name; } 45 inline bool operator!= ( const Label& l1, const Label& l2 ) { return !(l1 == l2); } 46 inline bool operator< ( const Label& l1, const Label& l2 ) { return l1.name < l2.name; } 47 47 48 inline std::ostream& operator<< ( std::ostream& out, const Label& l ) { return out << l.name; } 48 inline std::ostream& operator<< ( std::ostream& out, const Label& l ) { return out << l.name; } 49 50 51 //================================================================================================= 52 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 53 /// remove only if there is a better solution 54 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 55 /// forward declarations 56 inline void increment( const class Label * node, Node::ref_type ref ) { node->increment( ref ); } 57 inline void decrement( const class Label * node, Node::ref_type ref ) { node->decrement( ref ); } 49 58 50 59 } -
src/AST/LinkageSpec.hpp
r7e89526 r2a5e8a6 35 35 36 36 /// Bitflag type for storage classes 37 union Spec { 38 unsigned int val; 39 struct { 40 bool is_mangled : 1; 41 bool is_generatable : 1; 42 bool is_overrideable : 1; 43 bool is_builtin : 1; 44 bool is_gcc_builtin : 1; 37 struct spec_flags { 38 union { 39 unsigned int val; 40 struct { 41 bool is_mangled : 1; 42 bool is_generatable : 1; 43 bool is_overrideable : 1; 44 bool is_builtin : 1; 45 bool is_gcc_builtin : 1; 46 }; 45 47 }; 46 48 47 MakeBitfield( Spec )49 constexpr spec_flags( unsigned int val ) : val(val) {} 48 50 }; 51 52 using Spec = bitfield<spec_flags>; 49 53 50 54 /// If `cmd` = "C" returns `spec` with `is_mangled = false`. -
src/AST/ParseNode.hpp
r7e89526 r2a5e8a6 22 22 namespace ast { 23 23 24 25 26 27 24 /// AST node with an included source location 25 class ParseNode : public Node { 26 public: 27 CodeLocation location; 28 28 29 30 31 29 // Default constructor is deliberately omitted, all ParseNodes must have a location. 30 // Escape hatch if needed is to explicitly pass a default-constructed location, but 31 // this should be used sparingly. 32 32 33 33 ParseNode( const CodeLocation& loc ) : Node(), location(loc) {} 34 34 35 36 35 ParseNode( const ParseNode& o ) = default; 36 }; 37 37 38 39 //================================================================================================= 40 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 41 /// remove only if there is a better solution 42 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 43 /// forward declarations 44 inline void increment( const class ParseNode * node, Node::ref_type ref ) { node->increment( ref ); } 45 inline void decrement( const class ParseNode * node, Node::ref_type ref ) { node->decrement( ref ); } 38 46 } 39 47 -
src/AST/Pass.hpp
r7e89526 r2a5e8a6 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2019 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 // Pass.hpp -- 8 // 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 15 1 16 #pragma once 2 // IWYU pragma: private, include " Common/PassVisitor.h"17 // IWYU pragma: private, include "AST/Pass.hpp" 3 18 4 19 #include <functional> … … 6 21 #include <stack> 7 22 8 #include "Fwd.hpp" 9 #include "Node.hpp" 23 #include "AST/Fwd.hpp" 24 #include "AST/Node.hpp" 25 #include "AST/Decl.hpp" 26 #include "AST/Visitor.hpp" 27 28 #include "SymTab/Indexer.h" 10 29 11 30 // Private prelude header, needed for some of the magic tricks this class pulls off 12 #include " Pass.proto.hpp"31 #include "AST/Pass.proto.hpp" 13 32 14 33 namespace ast { … … 20 39 // 21 40 // Several additional features are available through inheritance 22 // | WithTypeSubstitution - provides polymorphic TypeSubstitution * env for the current expression 41 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the 42 // current expression 23 43 // | WithStmtsToAdd - provides the ability to insert statements before or after the current 24 44 // statement by adding new statements into stmtsToAddBefore or 25 45 // stmtsToAddAfter respectively. 46 // | WithDeclsToAdd - provides the ability to insert declarations before or after the current 47 // declarations by adding new DeclStmt into declsToAddBefore or 48 // declsToAddAfter respectively. 26 49 // | WithShortCircuiting - provides the ability to skip visiting child nodes; set visit_children 27 50 // to false in pre{visit,visit} to skip visiting children … … 30 53 // automatically be restored to its previous value after the corresponding 31 54 // postvisit/postmutate teminates. 55 // | WithVisitorRef - provides an pointer to the templated visitor wrapper 56 // | WithIndexer - provides indexer functionality (i.e. up-to-date symbol table) 32 57 //------------------------------------------------------------------------------------------------- 33 58 template< typename pass_t > 34 59 class Pass final : public ast::Visitor { 35 60 public: 61 /// Forward any arguments to the pass constructor 62 /// Propagate 'this' if necessary 36 63 template< typename... Args > 37 64 Pass( Args &&... args) 38 : m_pass( std::forward<Args>( args )... )65 : pass( std::forward<Args>( args )... ) 39 66 { 40 67 // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor 41 68 typedef Pass<pass_t> this_t; 42 this_t * const * visitor = __pass::visitor( m_pass, 0);69 this_t * const * visitor = __pass::visitor(pass, 0); 43 70 if(visitor) { 44 71 *const_cast<this_t **>( visitor ) = this; … … 48 75 virtual ~Pass() = default; 49 76 50 pass_t m_pass; 51 77 /// Storage for the actual pass 78 pass_t pass; 79 80 /// Visit function declarations 52 81 virtual DeclWithType * visit( const ObjectDecl * ) override final; 53 82 virtual DeclWithType * visit( const FunctionDecl * ) override final; … … 145 174 virtual TypeSubstitution * visit( const TypeSubstitution * ) override final; 146 175 176 friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_t>& visitor ); 147 177 private: 148 178 149 bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children( m_pass, 0); return ptr ? *ptr : true; }179 bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(pass, 0); return ptr ? *ptr : true; } 150 180 151 181 private: 182 /// Logic to call the accept and mutate the parent if needed, delegates call to accept 152 183 template<typename parent_t, typename child_t> 153 184 void maybe_accept(parent_t * & , typename parent_t::child_t *); 154 185 155 ast::Statement * call_accept( const ast::Statement* );156 ast::Expression * call_accept( const ast::Expression* );186 Stmt * call_accept( const Stmt * ); 187 Expr * call_accept( const Expr * ); 157 188 158 189 template< template <class> class container_t > 159 container_t< ast::ptr<ast::Statement> > call_accept( const container_t< ast::ptr<ast::Statement> > & );190 container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & ); 160 191 161 192 template< template <class> class container_t, typename node_t > 162 container_t< ast::ptr<node_t> > call_accept( const container_t< ast::ptr<node_t> > & container );193 container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container ); 163 194 164 195 private: 165 struct indexer_guard { 196 /// Internal RAII guard for indexer features 197 struct guard_indexer { 198 guard_indexer( Pass<pass_t> & pass ): pass( pass ) { __pass::indexer::enter(pass, 0); } 199 ~guard_indexer() { __pass::indexer::leave(pass, 0); } 166 200 Pass<pass_t> & pass; 167 168 indexer_guard( Pass<pass_t> & pass ) : pass( pass ) { __pass::indexer::enter(pass, 0); }169 ~indexer_guard() { __pass::indexer::leave(pass, 0); }170 201 }; 171 202 172 indexer_guard make_indexer_guard() { return { *this }; }173 174 private: 175 struct scope_guard {203 /// Internal RAII guard for scope features 204 struct guard_scope { 205 guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); } 206 ~guard_scope() { __pass::scope::leave(pass, 0); } 176 207 Pass<pass_t> & pass; 177 178 scope_guard( Pass<pass_t> & pass ) : pass( pass ) { __pass::scope::enter(pass, 0); }179 ~scope_guard() { __pass::scope::leave(pass, 0); }180 208 }; 181 182 scope_guard make_scope_guard() { return { *this }; } 183 }; 184 185 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 186 // Guard value : RAII type to restore a value when the Pass finishes visiting this node 187 template<typename pass_t, typename T> 188 void GuardValue( pass_t * pass, T& val ) { 189 pass->at_cleanup( [ val ]( void * newVal ) { 190 * static_cast< T * >( newVal ) = val; 191 }, static_cast< void * >( & val ) ); 192 } 193 194 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 209 }; 210 211 template<typename pass_t> 212 void acceptAll( std::list< ptr<Decl> >, Pass<pass_t>& visitor ); 213 214 //------------------------------------------------------------------------------------------------- 195 215 // PASS ACCESSORIES 196 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 197 198 // Keep track of the type substitution 199 struct WithConstTypeSubstitution { 200 const ast::TypeSubstitution * env = nullptr; 201 }; 216 //------------------------------------------------------------------------------------------------- 202 217 203 218 template<typename T> 204 219 using std_list = std::list<T>; 205 220 206 // Used if visitor requires added statements before or after the current node. 207 // The Pass template handles what *before* and *after* means automatically 221 /// Keep track of the polymorphic const TypeSubstitution * env for the current expression 222 struct WithConstTypeSubstitution { 223 const TypeSubstitution * env = nullptr; 224 }; 225 226 /// Used if visitor requires added statements before or after the current node. 227 /// The Pass template handles what *before* and *after* means automatically 208 228 template< template<class> class container_t = std_list > 209 229 struct WithStmtsToAdd { 210 container_t< ast::ptr< ast::Statement> > stmtsToAddBefore;211 container_t< ast::ptr< ast::Statement> > stmtsToAddAfter;212 }; 213 214 // Used if visitor requires added declarations before or after the current node.215 // The Pass template handles what *before* and *after* means automatically230 container_t< ptr<Stmt> > stmtsToAddBefore; 231 container_t< ptr<Stmt> > stmtsToAddAfter; 232 }; 233 234 /// Used if visitor requires added declarations before or after the current node. 235 /// The Pass template handles what *before* and *after* means automatically 216 236 template< template<class> class container_t = std_list > 217 237 struct WithDeclsToAdd { 218 ~WithDeclsToAdd() { 219 assert( declsToAddBefore.empty() ); 220 } 221 222 container_t< ast::ptr< ast::Declaration > > declsToAddBefore; 223 container_t< ast::ptr< ast::Declaration > > declsToAddAfter; 224 }; 225 226 // Use if visitation should stop at certain levels 227 // set visit_children false of all child nodes should be ignored 238 container_t< ptr<Decl> > declsToAddBefore; 239 container_t< ptr<Decl> > declsToAddAfter; 240 }; 241 242 /// Use if visitation should stop at certain levels 243 /// set visit_children false of all child nodes should be ignored 228 244 struct WithShortCircuiting { 229 245 __pass::bool_ref visit_children; 230 246 }; 231 247 232 // class WithGuards { 233 // protected: 234 // WithGuards() = default; 235 // ~WithGuards() = default; 236 237 // public: 238 // at_cleanup_t at_cleanup; 239 240 // template< typename T > 241 // void GuardValue( T& val ) { 242 // at_cleanup( [ val ]( void * newVal ) { 243 // * static_cast< T * >( newVal ) = val; 244 // }, static_cast< void * >( & val ) ); 245 // } 246 247 // template< typename T > 248 // void GuardScope( T& val ) { 249 // val.beginScope(); 250 // at_cleanup( []( void * val ) { 251 // static_cast< T * >( val )->endScope(); 252 // }, static_cast< void * >( & val ) ); 253 // } 254 255 // template< typename Func > 256 // void GuardAction( Func func ) { 257 // at_cleanup( [func](__attribute__((unused)) void *) { func(); }, nullptr ); 258 // } 259 // }; 260 261 // template<typename pass_type> 262 // class WithVisitorRef { 263 // protected: 264 // WithVisitorRef() {} 265 // ~WithVisitorRef() {} 266 267 // public: 268 // PassVisitor<pass_type> * const visitor = nullptr; 269 // }; 270 248 /// Used to restore values/functions/etc. when the Pass finishes visiting this node 249 class WithGuards { 250 __pass::at_cleanup_t at_cleanup; 251 252 public: 253 /// When this node is finished being visited, restore the value of a variable 254 template< typename T > 255 void GuardValue( T& val ) { 256 at_cleanup( [ val ]( void * newVal ) { 257 * static_cast< T * >( newVal ) = val; 258 }, static_cast< void * >( & val ) ); 259 } 260 261 /// On the object, all beginScope now and endScope when the current node is finished being visited 262 template< typename T > 263 void GuardScope( T& val ) { 264 val.beginScope(); 265 at_cleanup( []( void * val ) { 266 static_cast< T * >( val )->endScope(); 267 }, static_cast< void * >( & val ) ); 268 } 269 270 /// When this node is finished being visited, call a function 271 template< typename Func > 272 void GuardAction( Func func ) { 273 at_cleanup( [func](void *) { func(); }, nullptr ); 274 } 275 }; 276 277 /// Used to get a pointer to the pass with its wrapped type 278 template<typename pass_t> 279 struct WithVisitorRef { 280 Pass<pass_t> * const visitor = nullptr; 281 }; 282 283 /// Use when the templated visitor should update the indexer 271 284 struct WithIndexer { 272 285 SymTab::Indexer indexer; -
src/AST/Pass.impl.hpp
r7e89526 r2a5e8a6 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2019 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 // Pass.impl.hpp -- 8 // 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 15 1 16 #pragma once 2 // IWYU pragma: private, include " Pass.hpp"17 // IWYU pragma: private, include "AST/Pass.hpp" 3 18 4 19 #define VISIT_START( node ) \ 20 using namespace ast; \ 5 21 /* back-up the visit children */ \ 6 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children( m_pass, 0) ); \22 __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \ 7 23 /* setup the scope for passes that want to run code at exit */ \ 8 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup ( m_pass, 0) ); \24 __attribute__((unused)) ast::__pass::guard_value guard2( ast::__pass::at_cleanup (pass, 0) ); \ 9 25 /* call the implementation of the previsit of this pass */ \ 10 __pass::previsit( m_pass, node, 0 );26 __pass::previsit( pass, node, 0 ); 11 27 12 28 #define VISIT( code ) \ … … 98 114 99 115 template< typename pass_t > 100 ast::Expr ession * Pass< pass_t >::call_accept( const ast::Expression* expr ) {116 ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) { 101 117 __pedantic_pass_assert( __visit_children() ); 102 118 __pedantic_pass_assert( expr ); 103 119 104 const ast::TypeSubstitution ** env_ptr = __pass::env( m_pass, 0);120 const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0); 105 121 if ( env_ptr && expr->env ) { 106 122 *env_ptr = expr->env; … … 111 127 112 128 template< typename pass_t > 113 ast::Statement * Pass< pass_t >::call_accept( const ast::Statement * stmt ) {129 Stmt * Pass< pass_t >::call_accept( const Stmt * stmt ) { 114 130 __pedantic_pass_assert( __visit_children() ); 115 131 __pedantic_pass_assert( stmt ); 116 117 // add a few useful symbols to the scope118 using __pass::empty;119 using decls_t = typename std::remove_pointer< decltype(__decls_before()) >::type;120 using stmts_t = typename std::remove_pointer< decltype(__stmts_before()) >::type;121 122 // get the stmts/decls that will need to be spliced in123 auto stmts_before = __pass::stmtsToAddBefore( m_pass, 0);124 auto stmts_after = __pass::stmtsToAddAfter ( m_pass, 0);125 auto decls_before = __pass::declsToAddBefore( m_pass, 0);126 auto decls_after = __pass::declsToAddAfter ( m_pass, 0);127 128 // These may be modified by subnode but most be restored once we exit this statemnet.129 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( m_pass, 0); );130 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before );131 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after );132 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > __old_stmts_before( decls_before );133 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after );134 135 // Now is the time to actually visit the node136 ast::Statement * nstmt = stmt->accept( *this );137 138 // If the pass doesn't want to add anything then we are done139 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) {140 return nstmt;141 }142 143 // Make sure that it is either adding statements or declartions but not both144 // this is because otherwise the order would be awkward to predict145 assert(( empty( stmts_before ) && empty( stmts_after ))146 || ( empty( decls_before ) && empty( decls_after )) );147 148 // Create a new Compound Statement to hold the new decls/stmts149 ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location );150 151 // Take all the declarations that go before152 __pass::take_all( std::back_inserter( compound->kids ), decls_before );153 __pass::take_all( std::back_inserter( compound->kids ), stmts_before );154 155 // Insert the original declaration156 compound->kids.push_back( nstmt );157 158 // Insert all the declarations that go before159 __pass::take_all( std::back_inserter( compound->kids ), decls_after );160 __pass::take_all( std::back_inserter( compound->kids ), stmts_after );161 162 return compound;163 }164 165 template< typename pass_t >166 template< template <class> class container_t >167 container_t< ast::ptr<ast::Statement> > Pass< pass_t >::call_accept( const container_t< ast::ptr<ast::Statement> > & statements ) {168 __pedantic_pass_assert( __visit_children() );169 if( statements.empty() ) return {};170 171 // We are going to aggregate errors for all these statements172 SemanticErrorException errors;173 132 174 133 // add a few useful symbols to the scope … … 182 141 183 142 // These may be modified by subnode but most be restored once we exit this statemnet. 143 ValueGuardPtr< const ast::TypeSubstitution * > __old_env ( __pass::env( pass, 0); ); 184 144 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before ); 185 145 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after ); … … 187 147 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after ); 188 148 149 // Now is the time to actually visit the node 150 ast::Statement * nstmt = stmt->accept( *this ); 151 152 // If the pass doesn't want to add anything then we are done 153 if( empty(stmts_before) && empty(stmts_after) && empty(decls_before) && empty(decls_after) ) { 154 return nstmt; 155 } 156 157 // Make sure that it is either adding statements or declartions but not both 158 // this is because otherwise the order would be awkward to predict 159 assert(( empty( stmts_before ) && empty( stmts_after )) 160 || ( empty( decls_before ) && empty( decls_after )) ); 161 162 // Create a new Compound Statement to hold the new decls/stmts 163 ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location ); 164 165 // Take all the declarations that go before 166 __pass::take_all( std::back_inserter( compound->kids ), decls_before ); 167 __pass::take_all( std::back_inserter( compound->kids ), stmts_before ); 168 169 // Insert the original declaration 170 compound->kids.push_back( nstmt ); 171 172 // Insert all the declarations that go before 173 __pass::take_all( std::back_inserter( compound->kids ), decls_after ); 174 __pass::take_all( std::back_inserter( compound->kids ), stmts_after ); 175 176 return compound; 177 } 178 179 template< typename pass_t > 180 template< template <class> class container_t > 181 container_t< ptr<Stmt> > Pass< pass_t >::call_accept( const container_t< ptr<Stmt> > & statements ) { 182 __pedantic_pass_assert( __visit_children() ); 183 if( statements.empty() ) return {}; 184 185 // We are going to aggregate errors for all these statements 186 SemanticErrorException errors; 187 188 // add a few useful symbols to the scope 189 using __pass::empty; 190 191 // get the stmts/decls that will need to be spliced in 192 auto stmts_before = __pass::stmtsToAddBefore( pass, 0); 193 auto stmts_after = __pass::stmtsToAddAfter ( pass, 0); 194 auto decls_before = __pass::declsToAddBefore( pass, 0); 195 auto decls_after = __pass::declsToAddAfter ( pass, 0); 196 197 // These may be modified by subnode but most be restored once we exit this statemnet. 198 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before ); 199 ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after ); 200 ValueGuardPtr< typename std::remove_pointer< decltype(decls_before) > __old_stmts_before( decls_before ); 201 ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after ); 202 189 203 // update pass statitistics 190 204 pass_visitor_stats.depth++; … … 193 207 194 208 bool mutated = false; 195 container_t< ast::ptr< ast::Statement >> new_kids;196 for( const ast::Statement * stmt : statements ) {209 container_t< ptr<Stmt> > new_kids; 210 for( const Stmt * stmt : statements ) { 197 211 try { 198 212 __pedantic_pass_assert( stmt ); … … 269 283 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 270 284 285 template< typename pass_t > 286 inline void ast::acceptAll( std::list< ast::ptr<ast::Decl> > & decls, ast::Pass< pass_t > & visitor ) { 287 // We are going to aggregate errors for all these statements 288 SemanticErrorException errors; 289 290 // add a few useful symbols to the scope 291 using __pass::empty; 292 293 // get the stmts/decls that will need to be spliced in 294 auto decls_before = __pass::declsToAddBefore( pass, 0); 295 auto decls_after = __pass::declsToAddAfter ( pass, 0); 296 297 // update pass statitistics 298 pass_visitor_stats.depth++; 299 pass_visitor_stats.max->push(pass_visitor_stats.depth); 300 pass_visitor_stats.avg->push(pass_visitor_stats.depth); 301 302 for ( std::list< ast::ptr<ast::Decl> >::iterator i = decls.begin(); ; ++i ) { 303 // splice in new declarations after previous decl 304 if ( !empty( decls_after ) ) { decls.splice( i, *decls_after ); } 305 306 if ( i == decls.end() ) break; 307 308 try { 309 // run visitor on declaration 310 ast::ptr<ast::Decl> & node = *i; 311 assert( node ); 312 node = node->accept( visitor ); 313 } 314 catch( SemanticErrorException &e ) { 315 errors.append( e ); 316 } 317 318 // splice in new declarations before current decl 319 if ( !empty( decls_before ) ) { decls.splice( i, *decls_before ); } 320 } 321 pass_visitor_stats.depth--; 322 if ( !errors.isEmpty() ) { throw errors; } 323 } 324 271 325 // A NOTE ON THE ORDER OF TRAVERSAL 272 326 // … … 289 343 // ObjectDecl 290 344 template< typename pass_t > 291 ast::Decl arationWithType * Pass< pass_t >::mutate(ast::ObjectDecl * node ) {345 ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) { 292 346 VISIT_START( node ); 293 347 294 348 VISIT( 295 349 { 296 auto guard = make_indexer_guard();297 maybe_accept( node, ast::ObjectDecl::type );298 } 299 maybe_accept( node, ast::ObjectDecl::init );300 maybe_accept( node, ast::ObjectDecl::bitfieldWidth );301 maybe_accept( node, ast::ObjectDecl::attributes );350 indexer_guard guard { *this }; 351 maybe_accept( node, ObjectDecl::type ); 352 } 353 maybe_accept( node, ObjectDecl::init ); 354 maybe_accept( node, ObjectDecl::bitfieldWidth ); 355 maybe_accept( node, ObjectDecl::attributes ); 302 356 ) 303 357 304 __pass::indexer::AddId( m_pass, 0, node );305 306 VISIT_END( Decl arationWithType, node );358 __pass::indexer::AddId( pass, 0, node ); 359 360 VISIT_END( DeclWithType, node ); 307 361 } 308 362 … … 310 364 // Attribute 311 365 template< typename pass_type > 312 ast::Attribute * ast::Pass< pass_type >::visit( ast::ptr<ast::Attribute> &node ) {366 ast::Attribute * ast::Pass< pass_type >::visit( const ast::Attribute * node ) { 313 367 VISIT_START(node); 314 368 … … 323 377 // TypeSubstitution 324 378 template< typename pass_type > 325 TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {379 TypeSubstitution * PassVisitor< pass_type >::mutate( const TypeSubstitution * node ) { 326 380 MUTATE_START( node ); 327 381 -
src/AST/Pass.proto.hpp
r7e89526 r2a5e8a6 1 // 2 // Cforall Version 1.0.0 Copyright (C) 2019 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 // Pass.impl.hpp -- 8 // 9 // Author : Thierry Delisle 10 // Created On : Thu May 09 15::37::05 2019 11 // Last Modified By : 12 // Last Modified On : 13 // Update Count : 14 // 15 1 16 #pragma once 2 17 // IWYU pragma: private, include "Pass.hpp" 3 18 4 19 namespace ast { 5 template<typename pass_type> 6 class Pass; 7 8 namespace __pass { 9 typedef std::function<void( void * )> cleanup_func_t; 10 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t; 11 12 13 // boolean reference that may be null 14 // either refers to a boolean value or is null and returns true 15 class bool_ref { 16 public: 17 bool_ref() = default; 18 ~bool_ref() = default; 19 20 operator bool() { return m_ref ? *m_ref : true; } 21 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; } 22 23 private: 24 25 friend class visit_children_guard; 26 27 bool * set( bool * val ) { 28 bool * prev = m_ref; 29 m_ref = val; 30 return prev; 20 template<typename pass_type> 21 class Pass; 22 23 namespace __pass { 24 typedef std::function<void( void * )> cleanup_func_t; 25 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t; 26 27 28 // boolean reference that may be null 29 // either refers to a boolean value or is null and returns true 30 class bool_ref { 31 public: 32 bool_ref() = default; 33 ~bool_ref() = default; 34 35 operator bool() { return m_ref ? *m_ref : true; } 36 bool operator=( bool val ) { assert(m_ref); return *m_ref = val; } 37 38 private: 39 40 friend class visit_children_guard; 41 42 bool * set( bool * val ) { 43 bool * prev = m_ref; 44 m_ref = val; 45 return prev; 46 } 47 48 bool * m_ref = nullptr; 49 }; 50 51 // Implementation of the guard value 52 // Created inside the visit scope 53 class guard_value { 54 public: 55 /// Push onto the cleanup 56 guard_value( at_cleanup_t * at_cleanup ) { 57 if( at_cleanup ) { 58 *at_cleanup = [this]( cleanup_func_t && func, void* val ) { 59 push( std::move( func ), val ); 60 }; 31 61 } 32 33 bool * m_ref = nullptr; 62 } 63 64 ~guard_value() { 65 while( !cleanups.empty() ) { 66 auto& cleanup = cleanups.top(); 67 cleanup.func( cleanup.val ); 68 cleanups.pop(); 69 } 70 } 71 72 void push( cleanup_func_t && func, void* val ) { 73 cleanups.emplace( std::move(func), val ); 74 } 75 76 private: 77 struct cleanup_t { 78 cleanup_func_t func; 79 void * val; 80 81 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {} 34 82 }; 35 83 36 // Implementation of the guard value 37 // Created inside the visit scope 38 class guard_value { 39 public: 40 guard_value( at_cleanup_t * at_cleanup ) { 41 if( at_cleanup ) { 42 *at_cleanup = [this]( cleanup_func_t && func, void* val ) { 43 push( std::move( func ), val ); 44 }; 45 } 84 std::stack< cleanup_t > cleanups; 85 }; 86 87 // Guard structure implementation for whether or not children should be visited 88 class visit_children_guard { 89 public: 90 91 visit_children_guard( bool_ref * ref ) 92 : m_val ( true ) 93 , m_prev( ref ? ref->set( &m_val ) : nullptr ) 94 , m_ref ( ref ) 95 {} 96 97 ~visit_children_guard() { 98 if( m_ref ) { 99 m_ref->set( m_prev ); 46 100 } 47 48 ~guard_value() { 49 while( !cleanups.empty() ) { 50 auto& cleanup = cleanups.top(); 51 cleanup.func( cleanup.val ); 52 cleanups.pop(); 53 } 54 } 55 56 void push( cleanup_func_t && func, void* val ) { 57 cleanups.emplace( std::move(func), val ); 58 } 59 60 private: 61 struct cleanup_t { 62 cleanup_func_t func; 63 void * val; 64 65 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {} 66 }; 67 68 std::stack< cleanup_t > cleanups; 69 }; 70 71 // Guard structure implementation for whether or not children should be visited 72 class visit_children_guard { 73 public: 74 75 visit_children_guard( bool_ref * ref ) 76 : m_val ( true ) 77 , m_prev( ref ? ref->set( &m_val ) : nullptr ) 78 , m_ref ( ref ) 79 {} 80 81 ~visit_children_guard() { 82 if( m_ref ) { 83 m_ref->set( m_prev ); 84 } 85 } 86 87 operator bool() { return m_val; } 88 89 private: 90 bool m_val; 91 bool * m_prev; 92 bool_ref * m_ref; 93 }; 94 95 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 96 // Deep magic (a.k.a template meta programming) to make the templated visitor work 97 // Basically the goal is to make 2 previsit 98 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 99 // 'pass.previsit( node )' that compiles will be used for that node for that type 100 // This requires that this option only compile for passes that actually define an appropriate visit. 101 // SFINAE will make sure the compilation errors in this function don't halt the build. 102 // See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE 103 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing. 104 // This is needed only to eliminate the need for passes to specify any kind of handlers. 105 // The second implementation only works because it has a lower priority. This is due to the bogus last parameter. 106 // The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0 107 // the first implementation takes priority in regards to overloading. 108 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 109 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 110 template<typename pass_t, typename node_t> 111 static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) { 112 node = pass.previsit( node ); 113 assert(node); 114 } 115 116 template<typename pass_t, typename node_t> 117 static inline auto previsit( pass_t &, const node_t *, long ) {} 118 119 // PostVisit : never mutates the passed pointer but may return a different node 120 template<typename pass_t, typename node_t> 121 static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> decltype( pass.postvisit( node ), (const node_t *)nullptr ) { 122 return pass.postvisit( node ); 123 } 124 125 template<typename pass_t, typename node_t> 126 static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; } 127 128 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 129 // Deep magic (a.k.a template meta programming) continued 130 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit 131 // from in order to get extra functionallity for example 132 // class ErrorChecker : WithShortCircuiting { ... }; 133 // Pass<ErrorChecker> checker; 134 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting 135 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched 136 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 137 // For several accessories, the feature is enabled by detecting that a specific field is present 138 // Use a macro the encapsulate the logic of detecting a particular field 139 // The type is not strictly enforced but does match the accessory 140 #define FIELD_PTR( name, default_type ) \ 141 template< typename pass_t > \ 142 static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \ 101 } 102 103 operator bool() { return m_val; } 104 105 private: 106 bool m_val; 107 bool * m_prev; 108 bool_ref * m_ref; 109 }; 110 111 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 112 // Deep magic (a.k.a template meta programming) to make the templated visitor work 113 // Basically the goal is to make 2 previsit 114 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of 115 // 'pass.previsit( node )' that compiles will be used for that node for that type 116 // This requires that this option only compile for passes that actually define an appropriate visit. 117 // SFINAE will make sure the compilation errors in this function don't halt the build. 118 // See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE 119 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing. 120 // This is needed only to eliminate the need for passes to specify any kind of handlers. 121 // The second implementation only works because it has a lower priority. This is due to the bogus last parameter. 122 // The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0 123 // the first implementation takes priority in regards to overloading. 124 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 125 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call 126 template<typename pass_t, typename node_t> 127 static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) { 128 node = pass.previsit( node ); 129 assert(node); 130 } 131 132 template<typename pass_t, typename node_t> 133 static inline auto previsit( pass_t &, const node_t *, long ) {} 134 135 // PostVisit : never mutates the passed pointer but may return a different node 136 template<typename pass_t, typename node_t> 137 static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> decltype( pass.postvisit( node ), (const node_t *)nullptr ) { 138 return pass.postvisit( node ); 139 } 140 141 template<typename pass_t, typename node_t> 142 static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; } 143 144 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 145 // Deep magic (a.k.a template meta programming) continued 146 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit 147 // from in order to get extra functionallity for example 148 // class ErrorChecker : WithShortCircuiting { ... }; 149 // Pass<ErrorChecker> checker; 150 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting 151 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched 152 //------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 153 // For several accessories, the feature is enabled by detecting that a specific field is present 154 // Use a macro the encapsulate the logic of detecting a particular field 155 // The type is not strictly enforced but does match the accessory 156 #define FIELD_PTR( name, default_type ) \ 157 template< typename pass_t > \ 158 static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \ 159 \ 160 template< typename pass_t > \ 161 static inline default_type * name( pass_t &, long ) { return nullptr; } 162 163 // List of fields and their expected types 164 FIELD_PTR( env, const ast::TypeSubstitution ) 165 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 166 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) 167 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > ) 168 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > ) 169 FIELD_PTR( visit_children, __pass::bool_ref ) 170 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 171 FIELD_PTR( visitor, ast::Pass<pass_t> * const ) 172 173 // Remove the macro to make sure we don't clash 174 #undef FIELD_PTR 175 176 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. 177 // All passes which have such functions are assumed desire this behaviour 178 // detect it using the same strategy 179 namespace scope { 180 template<typename pass_t> 181 static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) { 182 pass.beginScope(); 183 } 184 185 template<typename pass_t> 186 static inline void enter( pass_t &, long ) {} 187 188 template<typename pass_t> 189 static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) { 190 pass.endScope(); 191 } 192 193 template<typename pass_t> 194 static inline void leave( pass_t &, long ) {} 195 }; 196 197 // Finally certain pass desire an up to date indexer automatically 198 // detect the presence of a member name indexer and call all the members appropriately 199 namespace indexer { 200 // Some simple scoping rules 201 template<typename pass_t> 202 static inline auto enter( pass_t & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) { 203 pass.indexer.enterScope(); 204 } 205 206 template<typename pass_t> 207 static inline auto enter( pass_t &, long ) {} 208 209 template<typename pass_t> 210 static inline auto leave( pass_t & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) { 211 pass.indexer.leaveScope(); 212 } 213 214 template<typename pass_t> 215 static inline auto leave( pass_t &, long ) {} 216 217 // The indexer has 2 kind of functions mostly, 1 argument and 2 arguments 218 // Create macro to condense these common patterns 219 #define INDEXER_FUNC1( func, type ) \ 220 template<typename pass_t> \ 221 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {\ 222 pass.indexer.func( arg ); \ 223 } \ 143 224 \ 144 template< typename pass_t > \ 145 static inline default_type * name( pass_t &, long ) { return nullptr; } 146 147 // List of fields and their expected types 148 FIELD_PTR( env, const ast::TypeSubstitution ) 149 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > ) 150 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > ) 151 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > ) 152 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > ) 153 FIELD_PTR( visit_children, __pass::bool_ref ) 154 FIELD_PTR( at_cleanup, __pass::at_cleanup_t ) 155 FIELD_PTR( visitor, ast::Pass<pass_t> * const ) 156 157 // Remove the macro to make sure we don't clash 158 #undef FIELD_PTR 159 160 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement. 161 // All passes which have such functions are assumed desire this behaviour 162 // detect it using the same strategy 163 namespace scope { 164 template<typename pass_t> 165 static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) { 166 pass.beginScope(); 167 } 168 169 template<typename pass_t> 170 static inline void enter( pass_t &, long ) {} 171 172 template<typename pass_t> 173 static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) { 174 pass.endScope(); 175 } 176 177 template<typename pass_t> 178 static inline void leave( pass_t &, long ) {} 179 }; 180 181 // Finally certain pass desire an up to date indexer automatically 182 // detect the presence of a member name indexer and call all the members appropriately 183 namespace indexer { 184 // Some simple scoping rules 185 template<typename pass_t> 186 static inline auto enter( pass_t & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) { 187 pass.indexer.enterScope(); 188 } 189 190 template<typename pass_t> 191 static inline auto enter( pass_t &, long ) {} 192 193 template<typename pass_t> 194 static inline auto leave( pass_t & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) { 195 pass.indexer.leaveScope(); 196 } 197 198 template<typename pass_t> 199 static inline auto leave( pass_t &, long ) {} 200 201 // The indexer has 2 kind of functions mostly, 1 argument and 2 arguments 202 // Create macro to condense these common patterns 203 #define INDEXER_FUNC1( func, type ) \ 204 template<typename pass_t> \ 205 static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {\ 206 pass.indexer.func( arg ); \ 207 } \ 225 template<typename pass_t> \ 226 static inline void func( pass_t &, long, type ) {} 227 228 #define INDEXER_FUNC2( func, type1, type2 ) \ 229 template<typename pass_t> \ 230 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void () ) {\ 231 pass.indexer.func( arg1, arg2 ); \ 232 } \ 208 233 \ 209 template<typename pass_t> \ 210 static inline void func( pass_t &, long, type ) {} 211 212 #define INDEXER_FUNC2( func, type1, type2 ) \ 213 template<typename pass_t> \ 214 static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void () ) {\ 215 pass.indexer.func( arg1, arg2 ); \ 216 } \ 217 \ 218 template<typename pass_t> \ 219 static inline void func( pass_t &, long, type1, type2 ) {} 220 221 INDEXER_FUNC1( addId , DeclarationWithType * ); 222 INDEXER_FUNC1( addType , NamedTypeDecl * ); 223 INDEXER_FUNC1( addStruct , StructDecl * ); 224 INDEXER_FUNC1( addEnum , EnumDecl * ); 225 INDEXER_FUNC1( addUnion , UnionDecl * ); 226 INDEXER_FUNC1( addTrait , TraitDecl * ); 227 INDEXER_FUNC2( addWith , std::list< Expression * > &, BaseSyntaxNode * ); 228 229 // A few extra functions have more complicated behaviour, they are hand written 230 template<typename pass_t> 231 static inline auto addStructFwd( pass_t & pass, int, ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) { 232 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 233 fwd->parameters = decl->parameters; 234 pass.indexer.addStruct( fwd ); 235 } 236 237 template<typename pass_t> 238 static inline void addStructFwd( pass_t &, long, ast::StructDecl * ) {} 239 240 template<typename pass_t> 241 static inline auto addUnionFwd( pass_t & pass, int, ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) { 242 UnionDecl * fwd = new UnionDecl( decl->name ); 243 fwd->parameters = decl->parameters; 244 pass.indexer.addUnion( fwd ); 245 } 246 247 template<typename pass_t> 248 static inline void addUnionFwd( pass_t &, long, ast::UnionDecl * ) {} 249 250 template<typename pass_t> 251 static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) { 252 if ( ! pass.indexer.lookupStruct( str ) ) { 253 pass.indexer.addStruct( str ); 254 } 255 } 256 257 template<typename pass_t> 258 static inline void addStruct( pass_t &, long, const std::string & ) {} 259 260 template<typename pass_t> 261 static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) { 262 if ( ! pass.indexer.lookupUnion( str ) ) { 263 pass.indexer.addUnion( str ); 264 } 265 } 266 267 template<typename pass_t> 268 static inline void addUnion( pass_t &, long, const std::string & ) {} 269 270 #undef INDEXER_FUNC1 271 #undef INDEXER_FUNC2 272 }; 234 template<typename pass_t> \ 235 static inline void func( pass_t &, long, type1, type2 ) {} 236 237 INDEXER_FUNC1( addId , DeclWithType * ); 238 INDEXER_FUNC1( addType , NamedTypeDecl * ); 239 INDEXER_FUNC1( addStruct , StructDecl * ); 240 INDEXER_FUNC1( addEnum , EnumDecl * ); 241 INDEXER_FUNC1( addUnion , UnionDecl * ); 242 INDEXER_FUNC1( addTrait , TraitDecl * ); 243 INDEXER_FUNC2( addWith , std::list< Expression * > &, Node * ); 244 245 // A few extra functions have more complicated behaviour, they are hand written 246 // template<typename pass_t> 247 // static inline auto addStructFwd( pass_t & pass, int, ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) { 248 // ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name ); 249 // fwd->parameters = decl->parameters; 250 // pass.indexer.addStruct( fwd ); 251 // } 252 253 // template<typename pass_t> 254 // static inline void addStructFwd( pass_t &, long, ast::StructDecl * ) {} 255 256 // template<typename pass_t> 257 // static inline auto addUnionFwd( pass_t & pass, int, ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) { 258 // UnionDecl * fwd = new UnionDecl( decl->name ); 259 // fwd->parameters = decl->parameters; 260 // pass.indexer.addUnion( fwd ); 261 // } 262 263 // template<typename pass_t> 264 // static inline void addUnionFwd( pass_t &, long, ast::UnionDecl * ) {} 265 266 // template<typename pass_t> 267 // static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) { 268 // if ( ! pass.indexer.lookupStruct( str ) ) { 269 // pass.indexer.addStruct( str ); 270 // } 271 // } 272 273 // template<typename pass_t> 274 // static inline void addStruct( pass_t &, long, const std::string & ) {} 275 276 // template<typename pass_t> 277 // static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) { 278 // if ( ! pass.indexer.lookupUnion( str ) ) { 279 // pass.indexer.addUnion( str ); 280 // } 281 // } 282 283 // template<typename pass_t> 284 // static inline void addUnion( pass_t &, long, const std::string & ) {} 285 286 #undef INDEXER_FUNC1 287 #undef INDEXER_FUNC2 273 288 }; 274 289 }; 290 }; -
src/AST/Stmt.hpp
r7e89526 r2a5e8a6 89 89 90 90 91 //================================================================================================= 92 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 93 /// remove only if there is a better solution 94 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 95 /// forward declarations 96 inline void increment( const class Stmt * node, Node::ref_type ref ) { node->increment( ref ); } 97 inline void decrement( const class Stmt * node, Node::ref_type ref ) { node->decrement( ref ); } 98 inline void increment( const class CompoundStmt * node, Node::ref_type ref ) { node->increment( ref ); } 99 inline void decrement( const class CompoundStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 100 inline void increment( const class ExprStmt * node, Node::ref_type ref ) { node->increment( ref ); } 101 inline void decrement( const class ExprStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 102 inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); } 103 inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 104 inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); } 105 inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 106 inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); } 107 inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 108 inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); } 109 inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 110 inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); } 111 inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 112 inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); } 113 inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 114 inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); } 115 inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 116 inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); } 117 inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 118 inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); } 119 inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 120 inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); } 121 inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 122 inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); } 123 inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 124 inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); } 125 inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 126 inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); } 127 inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 128 inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); } 129 inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 130 inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); } 131 inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 132 inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); } 133 inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 134 inline void increment( const class NullStmt * node, Node::ref_type ref ) { node->increment( ref ); } 135 inline void decrement( const class NullStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 136 inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); } 137 inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); } 138 91 139 } 92 140 -
src/AST/StorageClasses.hpp
r7e89526 r2a5e8a6 33 33 34 34 /// Bitflag type for storage classes 35 union Classes { 36 unsigned int val; 37 struct { 38 bool is_extern : 1; 39 bool is_static : 1; 40 bool is_auto : 1; 41 bool is_register : 1; 42 bool is_threadlocal : 1; 35 struct class_flags { 36 union { 37 unsigned int val; 38 struct { 39 bool is_extern : 1; 40 bool is_static : 1; 41 bool is_auto : 1; 42 bool is_register : 1; 43 bool is_threadlocal : 1; 44 }; 45 46 // MakeBitfieldPrint( NumClasses ) 43 47 }; 44 48 45 MakeBitfield( Classes ) 46 MakeBitfieldPrint( NumClasses ) 49 constexpr class_flags( unsigned int val ) : val(val) {} 47 50 }; 48 51 52 using Classes = bitfield<class_flags>; 49 53 } 50 54 } -
src/AST/Type.hpp
r7e89526 r2a5e8a6 24 24 }; 25 25 26 27 28 //================================================================================================= 29 /// This disgusting and giant piece of boiler-plate is here to solve a cyclic dependency 30 /// remove only if there is a better solution 31 /// The problem is that ast::ptr< ... > uses increment/decrement which won't work well with 32 /// forward declarations 33 inline void increment( const class Type * node, Node::ref_type ref ) { node->increment( ref ); } 34 inline void decrement( const class Type * node, Node::ref_type ref ) { node->decrement( ref ); } 35 inline void increment( const class VoidType * node, Node::ref_type ref ) { node->increment( ref ); } 36 inline void decrement( const class VoidType * node, Node::ref_type ref ) { node->decrement( ref ); } 37 inline void increment( const class BasicType * node, Node::ref_type ref ) { node->increment( ref ); } 38 inline void decrement( const class BasicType * node, Node::ref_type ref ) { node->decrement( ref ); } 39 inline void increment( const class PointerType * node, Node::ref_type ref ) { node->increment( ref ); } 40 inline void decrement( const class PointerType * node, Node::ref_type ref ) { node->decrement( ref ); } 41 inline void increment( const class ArrayType * node, Node::ref_type ref ) { node->increment( ref ); } 42 inline void decrement( const class ArrayType * node, Node::ref_type ref ) { node->decrement( ref ); } 43 inline void increment( const class ReferenceType * node, Node::ref_type ref ) { node->increment( ref ); } 44 inline void decrement( const class ReferenceType * node, Node::ref_type ref ) { node->decrement( ref ); } 45 inline void increment( const class QualifiedType * node, Node::ref_type ref ) { node->increment( ref ); } 46 inline void decrement( const class QualifiedType * node, Node::ref_type ref ) { node->decrement( ref ); } 47 inline void increment( const class FunctionType * node, Node::ref_type ref ) { node->increment( ref ); } 48 inline void decrement( const class FunctionType * node, Node::ref_type ref ) { node->decrement( ref ); } 49 inline void increment( const class ReferenceToType * node, Node::ref_type ref ) { node->increment( ref ); } 50 inline void decrement( const class ReferenceToType * node, Node::ref_type ref ) { node->decrement( ref ); } 51 inline void increment( const class StructInstType * node, Node::ref_type ref ) { node->increment( ref ); } 52 inline void decrement( const class StructInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 53 inline void increment( const class UnionInstType * node, Node::ref_type ref ) { node->increment( ref ); } 54 inline void decrement( const class UnionInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 55 inline void increment( const class EnumInstType * node, Node::ref_type ref ) { node->increment( ref ); } 56 inline void decrement( const class EnumInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 57 inline void increment( const class TraitInstType * node, Node::ref_type ref ) { node->increment( ref ); } 58 inline void decrement( const class TraitInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 59 inline void increment( const class TypeInstType * node, Node::ref_type ref ) { node->increment( ref ); } 60 inline void decrement( const class TypeInstType * node, Node::ref_type ref ) { node->decrement( ref ); } 61 inline void increment( const class TupleType * node, Node::ref_type ref ) { node->increment( ref ); } 62 inline void decrement( const class TupleType * node, Node::ref_type ref ) { node->decrement( ref ); } 63 inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); } 64 inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); } 65 inline void increment( const class AttrType * node, Node::ref_type ref ) { node->increment( ref ); } 66 inline void decrement( const class AttrType * node, Node::ref_type ref ) { node->decrement( ref ); } 67 inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); } 68 inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); } 69 inline void increment( const class ZeroType * node, Node::ref_type ref ) { node->increment( ref ); } 70 inline void decrement( const class ZeroType * node, Node::ref_type ref ) { node->decrement( ref ); } 71 inline void increment( const class OneType * node, Node::ref_type ref ) { node->increment( ref ); } 72 inline void decrement( const class OneType * node, Node::ref_type ref ) { node->decrement( ref ); } 73 inline void increment( const class GlobalScopeType * node, Node::ref_type ref ) { node->increment( ref ); } 74 inline void decrement( const class GlobalScopeType * node, Node::ref_type ref ) { node->decrement( ref ); } 75 26 76 } 27 77 -
src/Common/PassVisitor.impl.h
r7e89526 r2a5e8a6 168 168 template< typename Container, typename pass_type > 169 169 inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) { 170 170 171 if ( ! mutator.get_visit_children() ) return; 171 172 SemanticErrorException errors; … … 217 218 try { 218 219 func( *i ); 220 assert( *i ); 219 221 assert(( empty( beforeStmts ) && empty( afterStmts )) 220 222 || ( empty( beforeDecls ) && empty( afterDecls )) ); -
src/Common/PassVisitor.proto.h
r7e89526 r2a5e8a6 222 222 INDEXER_FUNC2( addWith , std::list< Expression * > &, BaseSyntaxNode * ); 223 223 224 #undef INDEXER_FUNC1 225 #undef INDEXER_FUNC2 224 226 225 227 template<typename pass_type> -
src/SynTree/Declaration.h
r7e89526 r2a5e8a6 71 71 static Declaration *declFromId( UniqueId id ); 72 72 73 private: 73 UniqueId uniqueId; 74 74 Type::StorageClasses storageClasses; 75 UniqueId uniqueId; 75 private: 76 76 }; 77 77 … … 213 213 TypeDecl::Kind kind; 214 214 bool isComplete; 215 215 216 216 Data() : kind( (TypeDecl::Kind)-1 ), isComplete( false ) {} 217 217 Data( TypeDecl * typeDecl ) : Data( typeDecl->get_kind(), typeDecl->isComplete() ) {} 218 218 Data( Kind kind, bool isComplete ) : kind( kind ), isComplete( isComplete ) {} 219 Data( const Data& d1, const Data& d2 ) 219 Data( const Data& d1, const Data& d2 ) 220 220 : kind( d1.kind ), isComplete ( d1.isComplete || d2.isComplete ) {} 221 221
Note: See TracChangeset
for help on using the changeset viewer.