Changes in / [4ab0669:1531ef5]


Ignore:
Location:
src
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    r4ab0669 r1531ef5  
    4747};
    4848
    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 Attribute * node, Node::ref_type ref ) { node->increment( ref ); }
    57 inline void decrement( const class Attribute * node, Node::ref_type ref ) { node->decrement( ref ); }
    5849}
    5950
  • src/AST/Bitfield.hpp

    r4ab0669 r1531ef5  
    2222/// does not allow it. Requires type to have `unsigned val` field
    2323/// @param BFType  Name of containing type
    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;
     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;                               \
    4049        }
    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 };
    5850
    5951/// Adds default printing operator to a bitfield type.
    6052/// Include in definition to add print function, requires other bitfield operators.
    6153/// @param N  Number of bits in bitfield
    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                 } \
     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                }                                                              \
    7364        }
    7465
  • src/AST/Decl.hpp

    r4ab0669 r1531ef5  
    122122        std::vector<ptr<DeclWithType>> assertions;
    123123
    124         NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
     124        NamedTypeDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 
    125125                Type* b, Linkage::Spec spec = Linkage::Cforall )
    126126        : Decl( loc, name, storage, spec ), base( b ), parameters(), assertions() {}
     
    149149                Data( TypeDecl* d ) : kind( d->kind ), isComplete( d->sized ) {}
    150150                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 ) 
    152152                : kind( d1.kind ), isComplete( d1.isComplete || d2.isComplete ) {}
    153153
     
    158158        };
    159159
    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, 
    161161                Kind k, bool s, Type* i = nullptr )
    162162        : NamedTypeDecl( loc, name, storage, b ), kind( k ), sized( k == Ttype || s ), init( i ) {}
     
    174174class TypedefDecl final : public NamedTypeDecl {
    175175public:
    176         TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
     176        TypedefDecl( const CodeLocation& loc, const std::string& name, Storage::Classes storage, 
    177177                Type* b, Linkage::Spec spec = Linkage::Cforall )
    178178        : NamedTypeDecl( loc, name, storage, b, spec ) {}
     
    275275};
    276276
    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 
    316277}
    317278
  • src/AST/FunctionSpec.hpp

    r4ab0669 r1531ef5  
    3131
    3232        /// Bitflag type for storage classes
    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 )
     33        union Specs {
     34                unsigned int val;
     35                struct {
     36                        bool is_inline   : 1;
     37                        bool is_noreturn : 1;
     38                        bool is_fortran  : 1;
    4339                };
    4440
    45                 constexpr spec_flags( unsigned int val ) : val(val) {}
     41                MakeBitfield( Specs )
     42                MakeBitfieldPrint( NumSpecs )
    4643        };
    4744
    48         using Specs = bitfield<spec_flags>;
    4945}
    5046}
  • src/AST/Fwd.hpp

    r4ab0669 r1531ef5  
    1616#pragma once
    1717
    18 #include "AST/Node.hpp"
    19 
    2018namespace ast {
    2119
     20class Node;
    2221class ParseNode;
    2322
     
    138137class TypeSubstitution;
    139138
    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 
    364139typedef unsigned int UniqueId;
    365140
  • src/AST/Init.hpp

    r4ab0669 r1531ef5  
    2828class Stmt;
    2929
    30 /// List of designator (NameExpr, VariableExpr, and ConstantExpr) expressions that specify an
     30/// List of designator (NameExpr, VariableExpr, and ConstantExpr) expressions that specify an 
    3131/// object being initialized
    3232class Designation final : public ParseNode {
     
    3434        std::vector<ptr<Expr>> designators;
    3535
    36         Designation( const CodeLocation& loc, std::vector<ptr<Expr>>&& ds = {} )
     36        Designation( const CodeLocation& loc, std::vector<ptr<Expr>>&& ds = {} ) 
    3737        : ParseNode( loc ), designators( std::move(ds) ) {}
    3838
     
    6060        ptr<Expr> value;
    6161
    62         SingleInit( const CodeLocation& loc, Expr* val, bool mc = false )
     62        SingleInit( const CodeLocation& loc, Expr* val, bool mc = false ) 
    6363        : Init( loc, mc ), value( val ) {}
    6464
     
    7777        std::vector<ptr<Designation>> designations;
    7878
    79         ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is,
     79        ListInit( const CodeLocation& loc, std::vector<ptr<Init>>&& is, 
    8080                std::vector<ptr<Designation>>&& ds = {}, bool mc = false );
    81 
     81       
    8282        using iterator = std::vector<ptr<Init>>::iterator;
    8383        using const_iterator = std::vector<ptr<Init>>::const_iterator;
     
    9393
    9494/// 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` 
    9696/// or `ListInit` if the object should be constructed.
    9797class ConstructorInit final : public Init {
     
    9999        ptr<Stmt> ctor;
    100100        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 
    102102        /// appropriate constructor definition is not found by the resolver.
    103103        ptr<Init> init;
     
    111111};
    112112
    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 ); }
    127113}
    128114
  • src/AST/Label.hpp

    r4ab0669 r1531ef5  
    2525namespace ast {
    2626
    27 class Attribute;
     27        class Attribute;
    2828
    29 /// Named labels for statements
    30 class Label {
    31 public:
    32         CodeLocation location;
    33         std::string name;
    34         std::vector< ptr<Attribute> > attributes;
     29        /// Named labels for statements
     30        class Label {
     31        public:
     32                CodeLocation location;
     33                std::string name;
     34                std::vector< ptr<Attribute> > attributes;
    3535
    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 ) {}
     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 ) {}
    3939
    40         operator std::string () const { return name; }
    41         bool empty() { return name.empty(); }
    42 };
     40                operator std::string () const { return name; }
     41                bool empty() { return name.empty(); }
     42        };
    4343
    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; }
     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; }
    4747
    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 ); }
     48        inline std::ostream& operator<< ( std::ostream& out, const Label& l ) { return out << l.name; }
    5849
    5950}
  • src/AST/LinkageSpec.hpp

    r4ab0669 r1531ef5  
    3535
    3636        /// Bitflag type for storage classes
    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                         };
     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;
    4745                };
    4846
    49                 constexpr spec_flags( unsigned int val ) : val(val) {}
     47                MakeBitfield( Spec )
    5048        };
    51 
    52         using Spec = bitfield<spec_flags>;
    5349
    5450        /// If `cmd` = "C" returns `spec` with `is_mangled = false`.
  • src/AST/ParseNode.hpp

    r4ab0669 r1531ef5  
    2222namespace ast {
    2323
    24 /// AST node with an included source location
    25 class ParseNode : public Node {
    26 public:
    27         CodeLocation location;
     24        /// AST node with an included source location
     25        class ParseNode : public Node {
     26        public:
     27                CodeLocation location;
    2828
    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.
     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.
    3232
    33         ParseNode( const CodeLocation& loc ) : Node(), location(loc) {}
     33                ParseNode( const CodeLocation& loc ) : Node(), location(loc) {}
    3434
    35         ParseNode( const ParseNode& o ) = default;
    36 };
     35                ParseNode( const ParseNode& o ) = default;
     36        };
    3737
    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 ); }
    4638}
    4739
  • src/AST/Pass.hpp

    r4ab0669 r1531ef5  
    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 
    161#pragma once
    17 // IWYU pragma: private, include "AST/Pass.hpp"
     2// IWYU pragma: private, include "Common/PassVisitor.h"
    183
    194#include <functional>
     
    216#include <stack>
    227
    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"
     8#include "Fwd.hpp"
     9#include "Node.hpp"
    2910
    3011// Private prelude header, needed for some of the magic tricks this class pulls off
    31 #include "AST/Pass.proto.hpp"
     12#include "Pass.proto.hpp"
    3213
    3314namespace ast {
     
    3920//
    4021// Several additional features are available through inheritance
    41 // | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the
    42 //                          current expression
     22// | WithTypeSubstitution - provides polymorphic TypeSubstitution * env for the current expression
    4323// | WithStmtsToAdd       - provides the ability to insert statements before or after the current
    4424//                          statement by adding new statements into stmtsToAddBefore or
    4525//                          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.
    4926// | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children
    5027//                          to false in pre{visit,visit} to skip visiting children
     
    5330//                          automatically be restored to its previous value after the corresponding
    5431//                          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)
    5732//-------------------------------------------------------------------------------------------------
    5833template< typename pass_t >
    5934class Pass final : public ast::Visitor {
    6035public:
    61         /// Forward any arguments to the pass constructor
    62         /// Propagate 'this' if necessary
    6336        template< typename... Args >
    6437        Pass( Args &&... args)
    65                 : pass( std::forward<Args>( args )... )
     38                : m_pass( std::forward<Args>( args )... )
    6639        {
    6740                // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor
    6841                typedef Pass<pass_t> this_t;
    69                 this_t * const * visitor = __pass::visitor(pass, 0);
     42                this_t * const * visitor = __pass::visitor(m_pass, 0);
    7043                if(visitor) {
    7144                        *const_cast<this_t **>( visitor ) = this;
     
    7548        virtual ~Pass() = default;
    7649
    77         /// Storage for the actual pass
    78         pass_t pass;
    79 
    80         /// Visit function declarations
     50        pass_t m_pass;
     51
    8152        virtual DeclWithType *     visit( const ObjectDecl           * ) override final;
    8253        virtual DeclWithType *     visit( const FunctionDecl         * ) override final;
     
    174145        virtual TypeSubstitution * visit( const TypeSubstitution     * ) override final;
    175146
    176         friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_t>& visitor );
    177 private:
    178 
    179         bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(pass, 0); return ptr ? *ptr : true; }
    180 
    181 private:
    182         /// Logic to call the accept and mutate the parent if needed, delegates call to accept
     147private:
     148
     149        bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(m_pass, 0); return ptr ? *ptr : true; }
     150
     151private:
    183152        template<typename parent_t, typename child_t>
    184153        void maybe_accept(parent_t * & , typename parent_t::child_t *);
    185154
    186         Stmt * call_accept( const Stmt * );
    187         Expr * call_accept( const Expr * );
     155        ast::Statement  * call_accept( const ast::Statement * );
     156        ast::Expression * call_accept( const ast::Expression * );
    188157
    189158        template< template <class> class container_t >
    190         container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & );
     159        container_t< ast::ptr<ast::Statement> > call_accept( const container_t< ast::ptr<ast::Statement> > & );
    191160
    192161        template< template <class> class container_t, typename node_t >
    193         container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    194 
    195 private:
    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); }
     162        container_t< ast::ptr<node_t> > call_accept( const container_t< ast::ptr<node_t> > & container );
     163
     164private:
     165        struct indexer_guard {
    200166                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); }
    201170        };
    202171
    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); }
     172        indexer_guard make_indexer_guard() { return { *this }; }
     173
     174private:
     175        struct scope_guard {
    207176                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); }
    208180        };
    209 };
    210 
    211 template<typename pass_t>
    212 void acceptAll( std::list< ptr<Decl> >, Pass<pass_t>& visitor );
    213 
    214 //-------------------------------------------------------------------------------------------------
     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
     187template<typename pass_t, typename T>
     188void 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//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    215195// PASS ACCESSORIES
    216 //-------------------------------------------------------------------------------------------------
     196//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     197
     198// Keep track of the type substitution
     199struct WithConstTypeSubstitution {
     200        const ast::TypeSubstitution * env = nullptr;
     201};
    217202
    218203template<typename T>
    219204using std_list = std::list<T>;
    220205
    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
     206// Used if visitor requires added statements before or after the current node.
     207// The Pass template handles what *before* and *after* means automatically
    228208template< template<class> class container_t = std_list >
    229209struct WithStmtsToAdd {
    230         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
     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 automatically
    236216template< template<class> class container_t = std_list >
    237217struct WithDeclsToAdd {
    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
     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
    244228struct WithShortCircuiting {
    245229        __pass::bool_ref visit_children;
    246230};
    247231
    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
     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
    284271struct WithIndexer {
    285272        SymTab::Indexer indexer;
  • src/AST/Pass.impl.hpp

    r4ab0669 r1531ef5  
    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 
    161#pragma once
    17 // IWYU pragma: private, include "AST/Pass.hpp"
     2// IWYU pragma: private, include "Pass.hpp"
    183
    194#define VISIT_START( node ) \
    20         using namespace ast; \
    215        /* back-up the visit children */ \
    22         __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \
     6        __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(m_pass, 0) ); \
    237        /* setup the scope for passes that want to run code at exit */ \
    24         __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (pass, 0) ); \
     8        __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (m_pass, 0) ); \
    259        /* call the implementation of the previsit of this pass */ \
    26         __pass::previsit( pass, node, 0 );
     10        __pass::previsit( m_pass, node, 0 );
    2711
    2812#define VISIT( code ) \
     
    11498
    11599        template< typename pass_t >
    116         ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) {
     100        ast::Expression * Pass< pass_t >::call_accept( const ast::Expression * expr ) {
    117101                __pedantic_pass_assert( __visit_children() );
    118102                __pedantic_pass_assert( expr );
    119103
    120                 const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0);
     104                const ast::TypeSubstitution ** env_ptr = __pass::env( m_pass, 0);
    121105                if ( env_ptr && expr->env ) {
    122106                        *env_ptr = expr->env;
     
    127111
    128112        template< typename pass_t >
    129         Stmt * Pass< pass_t >::call_accept( const Stmt * stmt ) {
     113        ast::Statement * Pass< pass_t >::call_accept( const ast::Statement * stmt ) {
    130114                __pedantic_pass_assert( __visit_children() );
    131115                __pedantic_pass_assert( stmt );
     116
     117                // add a few useful symbols to the scope
     118                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 in
     123                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 node
     136                ast::Statement * nstmt = stmt->accept( *this );
     137
     138                // If the pass doesn't want to add anything then we are done
     139                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 both
     144                // this is because otherwise the order would be awkward to predict
     145                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/stmts
     149                ast::CompoundStmt * compound = new ast::CompoundStmt( parent->*child.location );
     150
     151                // Take all the declarations that go before
     152                __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 declaration
     156                compound->kids.push_back( nstmt );
     157
     158                // Insert all the declarations that go before
     159                __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 statements
     172                SemanticErrorException errors;
    132173
    133174                // add a few useful symbols to the scope
     
    141182
    142183                // 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);  );
    144184                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before );
    145185                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after  );
     
    147187                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after  );
    148188
    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 
    203189                // update pass statitistics
    204190                pass_visitor_stats.depth++;
     
    207193
    208194                bool mutated = false;
    209                 container_t< ptr<Stmt> > new_kids;
    210                 for( const Stmt * stmt : statements ) {
     195                container_t<ast::ptr< ast::Statement >> new_kids;
     196                for( const ast::Statement * stmt : statements ) {
    211197                        try {
    212198                                __pedantic_pass_assert( stmt );
     
    283269//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    284270
    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 
    325271// A NOTE ON THE ORDER OF TRAVERSAL
    326272//
     
    343289// ObjectDecl
    344290template< typename pass_t >
    345 ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {
     291ast::DeclarationWithType * Pass< pass_t >::mutate( ast::ObjectDecl * node ) {
    346292        VISIT_START( node );
    347293
    348294        VISIT(
    349295                {
    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    );
     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    );
    356302        )
    357303
    358         __pass::indexer::AddId( pass, 0, node );
    359 
    360         VISIT_END( DeclWithType, node );
     304        __pass::indexer::AddId( m_pass, 0, node );
     305
     306        VISIT_END( DeclarationWithType, node );
    361307}
    362308
     
    364310// Attribute
    365311template< typename pass_type >
    366 ast::Attribute * ast::Pass< pass_type >::visit( const ast::Attribute * node  )  {
     312ast::Attribute * ast::Pass< pass_type >::visit( ast::ptr<ast::Attribute> & node  )  {
    367313        VISIT_START(node);
    368314
     
    377323// TypeSubstitution
    378324template< typename pass_type >
    379 TypeSubstitution * PassVisitor< pass_type >::mutate( const TypeSubstitution * node ) {
     325TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {
    380326        MUTATE_START( node );
    381327
  • src/AST/Pass.proto.hpp

    r4ab0669 r1531ef5  
    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 
    161#pragma once
    172// IWYU pragma: private, include "Pass.hpp"
    183
    194namespace ast {
    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;
     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;
     31                        }
     32
     33                        bool * m_ref = nullptr;
     34                };
     35
     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                                }
     46                        }
     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);
    46114                }
    47115
    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                                 };
    61                         }
     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 );
    62123                }
    63124
    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) {}
    82                 };
    83 
    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 );
    100                         }
    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                 } \
     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; } \
    224143                \
    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                 } \
     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                        } \
    233208                        \
    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
     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                };
    288273        };
    289274};
    290 };
  • src/AST/Stmt.hpp

    r4ab0669 r1531ef5  
    8989
    9090
    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 
    13991}
    14092
  • src/AST/StorageClasses.hpp

    r4ab0669 r1531ef5  
    3333
    3434        /// Bitflag type for storage classes
    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 )
     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;
    4743                };
    4844
    49                 constexpr class_flags( unsigned int val ) : val(val) {}
     45                MakeBitfield( Classes )
     46                MakeBitfieldPrint( NumClasses )
    5047        };
    5148
    52         using Classes = bitfield<class_flags>;
    5349}
    5450}
  • src/AST/Type.hpp

    r4ab0669 r1531ef5  
    2424};
    2525
    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 
    7626}
    7727
  • src/Common/PassVisitor.impl.h

    r4ab0669 r1531ef5  
    168168template< typename Container, typename pass_type >
    169169inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) {
    170 
    171170        if ( ! mutator.get_visit_children() ) return;
    172171        SemanticErrorException errors;
     
    218217                try {
    219218                        func( *i );
    220                         assert( *i );
    221219                        assert(( empty( beforeStmts ) && empty( afterStmts ))
    222220                            || ( empty( beforeDecls ) && empty( afterDecls )) );
  • src/Common/PassVisitor.proto.h

    r4ab0669 r1531ef5  
    222222INDEXER_FUNC2( addWith   , std::list< Expression * > &, BaseSyntaxNode * );
    223223
    224 #undef INDEXER_FUNC1
    225 #undef INDEXER_FUNC2
    226224
    227225template<typename pass_type>
  • src/SynTree/Declaration.h

    r4ab0669 r1531ef5  
    7171        static Declaration *declFromId( UniqueId id );
    7272
     73  private:
     74        Type::StorageClasses storageClasses;
    7375        UniqueId uniqueId;
    74         Type::StorageClasses storageClasses;
    75   private:
    7676};
    7777
     
    213213                TypeDecl::Kind kind;
    214214                bool isComplete;
    215 
     215               
    216216                Data() : kind( (TypeDecl::Kind)-1 ), isComplete( false ) {}
    217217                Data( TypeDecl * typeDecl ) : Data( typeDecl->get_kind(), typeDecl->isComplete() ) {}
    218218                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 ) 
    220220                : kind( d1.kind ), isComplete ( d1.isComplete || d2.isComplete ) {}
    221221
Note: See TracChangeset for help on using the changeset viewer.