Changes in / [0727d97:336d0b3]


Ignore:
Location:
src
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • src/AST/Attribute.hpp

    r0727d97 r336d0b3  
    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
     56inline void increment( const class Attribute * node, Node::ref_type ref ) { node->increment( ref ); }
     57inline void decrement( const class Attribute * node, Node::ref_type ref ) { node->decrement( ref ); }
    4958}
    5059
  • src/AST/Bitfield.hpp

    r0727d97 r336d0b3  
    2222/// does not allow it. Requires type to have `unsigned val` field
    2323/// @param BFType  Name of containing type
    24 #define MakeBitfield( BFType )                                         \
    25         constexpr BFType() : val( 0 ) {}                                   \
    26         constexpr BFType( unsigned int v ) : val( v ) {}                   \
    27         bool operator[]( unsigned int i ) const { return val & (1 << i); } \
    28         bool any() const { return val != 0; }                              \
    29         void reset() { val = 0; }                                          \
    30         int ffs() { return ::ffs( val ) - 1; }                             \
    31         BFType operator&=( BFType other ) {                                \
    32                 val &= other.val; return *this;                                \
    33         }                                                                  \
    34         BFType operator&( BFType other ) const {                           \
    35                 BFType q = other;                                              \
    36                 q &= *this;                                                    \
    37                 return q;                                                      \
    38         }                                                                  \
    39         BFType operator|=( BFType other ) {                                \
    40                 val |= other.val; return *this;                                \
    41         }                                                                  \
    42         BFType operator|( BFType other ) const {                           \
    43                 BFType q = other;                                              \
    44                 q |= *this;                                                    \
    45                 return q;                                                      \
    46         }                                                                  \
    47         BFType operator-=( BFType other ) {                                \
    48                 val &= ~other.val; return *this;                               \
     24template<typename T>
     25struct 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;
    4940        }
     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};
    5058
    5159/// Adds default printing operator to a bitfield type.
    5260/// Include in definition to add print function, requires other bitfield operators.
    5361/// @param N  Number of bits in bitfield
    54 #define MakeBitfieldPrint( N )                                         \
    55         static const char* Names[];                                        \
    56         void print( std::ostream & os ) const {                            \
    57                 if ( (*this).any() ) {                                         \
    58                         for ( unsigned int i = 0; i < N; i += 1 ) {                \
    59                                 if ( (*this)[i] ) {                                    \
    60                                         os << Names[i] << ' ';                             \
    61                                 }                                                      \
    62                         }                                                          \
    63                 }                                                              \
     62#define MakeBitfieldPrint( N ) \
     63        static const char* Names[]; \
     64 \
     65        void print( std::ostream & os ) const { \
     66                if ( (*this).any() ) { \
     67                        for ( unsigned int i = 0; i < N; i += 1 ) { \
     68                                if ( (*this)[i] ) { \
     69                                        os << Names[i] << ' '; \
     70                                } \
     71                        } \
     72                } \
    6473        }
    6574
  • src/AST/Decl.hpp

    r0727d97 r336d0b3  
    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
     283inline void increment( const class Decl * node, Node::ref_type ref ) { node->increment(ref); }
     284inline void decrement( const class Decl * node, Node::ref_type ref ) { node->decrement(ref); }
     285inline void increment( const class DeclWithType * node, Node::ref_type ref ) { node->increment(ref); }
     286inline void decrement( const class DeclWithType * node, Node::ref_type ref ) { node->decrement(ref); }
     287inline void increment( const class ObjectDecl * node, Node::ref_type ref ) { node->increment(ref); }
     288inline void decrement( const class ObjectDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     289inline void increment( const class FunctionDecl * node, Node::ref_type ref ) { node->increment(ref); }
     290inline void decrement( const class FunctionDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     291inline void increment( const class AggregateDecl * node, Node::ref_type ref ) { node->increment(ref); }
     292inline void decrement( const class AggregateDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     293inline void increment( const class StructDecl * node, Node::ref_type ref ) { node->increment(ref); }
     294inline void decrement( const class StructDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     295inline void increment( const class UnionDecl * node, Node::ref_type ref ) { node->increment(ref); }
     296inline void decrement( const class UnionDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     297inline void increment( const class EnumDecl * node, Node::ref_type ref ) { node->increment(ref); }
     298inline void decrement( const class EnumDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     299inline void increment( const class TraitDecl * node, Node::ref_type ref ) { node->increment(ref); }
     300inline void decrement( const class TraitDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     301inline void increment( const class NamedTypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
     302inline void decrement( const class NamedTypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     303inline void increment( const class TypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
     304inline void decrement( const class TypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     305inline void increment( const class FtypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
     306inline void decrement( const class FtypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     307inline void increment( const class DtypeDecl * node, Node::ref_type ref ) { node->increment(ref); }
     308inline void decrement( const class DtypeDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     309inline void increment( const class TypedefDecl * node, Node::ref_type ref ) { node->increment(ref); }
     310inline void decrement( const class TypedefDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     311inline void increment( const class AsmDecl * node, Node::ref_type ref ) { node->increment(ref); }
     312inline void decrement( const class AsmDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     313inline void increment( const class StaticAssertDecl * node, Node::ref_type ref ) { node->increment(ref); }
     314inline void decrement( const class StaticAssertDecl * node, Node::ref_type ref ) { node->decrement(ref); }
     315
    277316}
    278317
  • src/AST/FunctionSpec.hpp

    r0727d97 r336d0b3  
    3131
    3232        /// Bitflag type for storage classes
    33         union Specs {
    34                 unsigned int val;
    35                 struct {
    36                         bool is_inline   : 1;
    37                         bool is_noreturn : 1;
    38                         bool is_fortran  : 1;
     33        struct spec_flags {
     34                union {
     35                        unsigned int val;
     36                        struct {
     37                                bool is_inline   : 1;
     38                                bool is_noreturn : 1;
     39                                bool is_fortran  : 1;
     40                        };
     41
     42                        // MakeBitfieldPrint( NumSpecs )
    3943                };
    4044
    41                 MakeBitfield( Specs )
    42                 MakeBitfieldPrint( NumSpecs )
     45                constexpr spec_flags( unsigned int val ) : val(val) {}
    4346        };
    4447
     48        using Specs = bitfield<spec_flags>;
    4549}
    4650}
  • src/AST/Fwd.hpp

    r0727d97 r336d0b3  
    1616#pragma once
    1717
     18#include "AST/Node.hpp"
     19
    1820namespace ast {
    1921
    20 class Node;
    2122class ParseNode;
    2223
     
    137138class TypeSubstitution;
    138139
     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
     145inline void decrement( const class Node * node, Node::ref_type ref ) { node->decrement(ref); }
     146inline void increment( const class Node * node, Node::ref_type ref ) { node->increment(ref); }
     147inline void increment( const class ParseNode *, Node::ref_type );
     148inline void decrement( const class ParseNode *, Node::ref_type );
     149inline void increment( const class Decl *, Node::ref_type );
     150inline void decrement( const class Decl *, Node::ref_type );
     151inline void increment( const class DeclWithType *, Node::ref_type );
     152inline void decrement( const class DeclWithType *, Node::ref_type );
     153inline void increment( const class ObjectDecl *, Node::ref_type );
     154inline void decrement( const class ObjectDecl *, Node::ref_type );
     155inline void increment( const class FunctionDecl *, Node::ref_type );
     156inline void decrement( const class FunctionDecl *, Node::ref_type );
     157inline void increment( const class AggregateDecl *, Node::ref_type );
     158inline void decrement( const class AggregateDecl *, Node::ref_type );
     159inline void increment( const class StructDecl *, Node::ref_type );
     160inline void decrement( const class StructDecl *, Node::ref_type );
     161inline void increment( const class UnionDecl *, Node::ref_type );
     162inline void decrement( const class UnionDecl *, Node::ref_type );
     163inline void increment( const class EnumDecl *, Node::ref_type );
     164inline void decrement( const class EnumDecl *, Node::ref_type );
     165inline void increment( const class TraitDecl *, Node::ref_type );
     166inline void decrement( const class TraitDecl *, Node::ref_type );
     167inline void increment( const class NamedTypeDecl *, Node::ref_type );
     168inline void decrement( const class NamedTypeDecl *, Node::ref_type );
     169inline void increment( const class TypeDecl *, Node::ref_type );
     170inline void decrement( const class TypeDecl *, Node::ref_type );
     171inline void increment( const class FtypeDecl *, Node::ref_type );
     172inline void decrement( const class FtypeDecl *, Node::ref_type );
     173inline void increment( const class DtypeDecl *, Node::ref_type );
     174inline void decrement( const class DtypeDecl *, Node::ref_type );
     175inline void increment( const class TypedefDecl *, Node::ref_type );
     176inline void decrement( const class TypedefDecl *, Node::ref_type );
     177inline void increment( const class AsmDecl *, Node::ref_type );
     178inline void decrement( const class AsmDecl *, Node::ref_type );
     179inline void increment( const class StaticAssertDecl *, Node::ref_type );
     180inline void decrement( const class StaticAssertDecl *, Node::ref_type );
     181inline void increment( const class Stmt *, Node::ref_type );
     182inline void decrement( const class Stmt *, Node::ref_type );
     183inline void increment( const class CompoundStmt *, Node::ref_type );
     184inline void decrement( const class CompoundStmt *, Node::ref_type );
     185inline void increment( const class ExprStmt *, Node::ref_type );
     186inline void decrement( const class ExprStmt *, Node::ref_type );
     187inline void increment( const class AsmStmt *, Node::ref_type );
     188inline void decrement( const class AsmStmt *, Node::ref_type );
     189inline void increment( const class DirectiveStmt *, Node::ref_type );
     190inline void decrement( const class DirectiveStmt *, Node::ref_type );
     191inline void increment( const class IfStmt *, Node::ref_type );
     192inline void decrement( const class IfStmt *, Node::ref_type );
     193inline void increment( const class WhileStmt *, Node::ref_type );
     194inline void decrement( const class WhileStmt *, Node::ref_type );
     195inline void increment( const class ForStmt *, Node::ref_type );
     196inline void decrement( const class ForStmt *, Node::ref_type );
     197inline void increment( const class SwitchStmt *, Node::ref_type );
     198inline void decrement( const class SwitchStmt *, Node::ref_type );
     199inline void increment( const class CaseStmt *, Node::ref_type );
     200inline void decrement( const class CaseStmt *, Node::ref_type );
     201inline void increment( const class BranchStmt *, Node::ref_type );
     202inline void decrement( const class BranchStmt *, Node::ref_type );
     203inline void increment( const class ReturnStmt *, Node::ref_type );
     204inline void decrement( const class ReturnStmt *, Node::ref_type );
     205inline void increment( const class ThrowStmt *, Node::ref_type );
     206inline void decrement( const class ThrowStmt *, Node::ref_type );
     207inline void increment( const class TryStmt *, Node::ref_type );
     208inline void decrement( const class TryStmt *, Node::ref_type );
     209inline void increment( const class CatchStmt *, Node::ref_type );
     210inline void decrement( const class CatchStmt *, Node::ref_type );
     211inline void increment( const class FinallyStmt *, Node::ref_type );
     212inline void decrement( const class FinallyStmt *, Node::ref_type );
     213inline void increment( const class WaitForStmt *, Node::ref_type );
     214inline void decrement( const class WaitForStmt *, Node::ref_type );
     215inline void increment( const class WithStmt *, Node::ref_type );
     216inline void decrement( const class WithStmt *, Node::ref_type );
     217inline void increment( const class DeclStmt *, Node::ref_type );
     218inline void decrement( const class DeclStmt *, Node::ref_type );
     219inline void increment( const class NullStmt *, Node::ref_type );
     220inline void decrement( const class NullStmt *, Node::ref_type );
     221inline void increment( const class ImplicitCtorDtorStmt *, Node::ref_type );
     222inline void decrement( const class ImplicitCtorDtorStmt *, Node::ref_type );
     223inline void increment( const class Expr *, Node::ref_type );
     224inline void decrement( const class Expr *, Node::ref_type );
     225inline void increment( const class ApplicationExpr *, Node::ref_type );
     226inline void decrement( const class ApplicationExpr *, Node::ref_type );
     227inline void increment( const class UntypedExpr *, Node::ref_type );
     228inline void decrement( const class UntypedExpr *, Node::ref_type );
     229inline void increment( const class NameExpr *, Node::ref_type );
     230inline void decrement( const class NameExpr *, Node::ref_type );
     231inline void increment( const class AddressExpr *, Node::ref_type );
     232inline void decrement( const class AddressExpr *, Node::ref_type );
     233inline void increment( const class LabelAddressExpr *, Node::ref_type );
     234inline void decrement( const class LabelAddressExpr *, Node::ref_type );
     235inline void increment( const class CastExpr *, Node::ref_type );
     236inline void decrement( const class CastExpr *, Node::ref_type );
     237inline void increment( const class KeywordCastExpr *, Node::ref_type );
     238inline void decrement( const class KeywordCastExpr *, Node::ref_type );
     239inline void increment( const class VirtualCastExpr *, Node::ref_type );
     240inline void decrement( const class VirtualCastExpr *, Node::ref_type );
     241inline void increment( const class MemberExpr *, Node::ref_type );
     242inline void decrement( const class MemberExpr *, Node::ref_type );
     243inline void increment( const class UntypedMemberExpr *, Node::ref_type );
     244inline void decrement( const class UntypedMemberExpr *, Node::ref_type );
     245inline void increment( const class VariableExpr *, Node::ref_type );
     246inline void decrement( const class VariableExpr *, Node::ref_type );
     247inline void increment( const class ConstantExpr *, Node::ref_type );
     248inline void decrement( const class ConstantExpr *, Node::ref_type );
     249inline void increment( const class SizeofExpr *, Node::ref_type );
     250inline void decrement( const class SizeofExpr *, Node::ref_type );
     251inline void increment( const class AlignofExpr *, Node::ref_type );
     252inline void decrement( const class AlignofExpr *, Node::ref_type );
     253inline void increment( const class UntypedOffsetofExpr *, Node::ref_type );
     254inline void decrement( const class UntypedOffsetofExpr *, Node::ref_type );
     255inline void increment( const class OffsetofExpr *, Node::ref_type );
     256inline void decrement( const class OffsetofExpr *, Node::ref_type );
     257inline void increment( const class OffsetPackExpr *, Node::ref_type );
     258inline void decrement( const class OffsetPackExpr *, Node::ref_type );
     259inline void increment( const class AttrExpr *, Node::ref_type );
     260inline void decrement( const class AttrExpr *, Node::ref_type );
     261inline void increment( const class LogicalExpr *, Node::ref_type );
     262inline void decrement( const class LogicalExpr *, Node::ref_type );
     263inline void increment( const class ConditionalExpr *, Node::ref_type );
     264inline void decrement( const class ConditionalExpr *, Node::ref_type );
     265inline void increment( const class CommaExpr *, Node::ref_type );
     266inline void decrement( const class CommaExpr *, Node::ref_type );
     267inline void increment( const class TypeExpr *, Node::ref_type );
     268inline void decrement( const class TypeExpr *, Node::ref_type );
     269inline void increment( const class AsmExpr *, Node::ref_type );
     270inline void decrement( const class AsmExpr *, Node::ref_type );
     271inline void increment( const class ImplicitCopyCtorExpr *, Node::ref_type );
     272inline void decrement( const class ImplicitCopyCtorExpr *, Node::ref_type );
     273inline void increment( const class ConstructorExpr *, Node::ref_type );
     274inline void decrement( const class ConstructorExpr *, Node::ref_type );
     275inline void increment( const class CompoundLiteralExpr *, Node::ref_type );
     276inline void decrement( const class CompoundLiteralExpr *, Node::ref_type );
     277inline void increment( const class UntypedValofExpr *, Node::ref_type );
     278inline void decrement( const class UntypedValofExpr *, Node::ref_type );
     279inline void increment( const class RangeExpr *, Node::ref_type );
     280inline void decrement( const class RangeExpr *, Node::ref_type );
     281inline void increment( const class UntypedTupleExpr *, Node::ref_type );
     282inline void decrement( const class UntypedTupleExpr *, Node::ref_type );
     283inline void increment( const class TupleExpr *, Node::ref_type );
     284inline void decrement( const class TupleExpr *, Node::ref_type );
     285inline void increment( const class TupleIndexExpr *, Node::ref_type );
     286inline void decrement( const class TupleIndexExpr *, Node::ref_type );
     287inline void increment( const class TupleAssignExpr *, Node::ref_type );
     288inline void decrement( const class TupleAssignExpr *, Node::ref_type );
     289inline void increment( const class StmtExpr *, Node::ref_type );
     290inline void decrement( const class StmtExpr *, Node::ref_type );
     291inline void increment( const class UniqueExpr *, Node::ref_type );
     292inline void decrement( const class UniqueExpr *, Node::ref_type );
     293inline void increment( const class UntypedInitExpr *, Node::ref_type );
     294inline void decrement( const class UntypedInitExpr *, Node::ref_type );
     295inline void increment( const class InitExpr *, Node::ref_type );
     296inline void decrement( const class InitExpr *, Node::ref_type );
     297inline void increment( const class DeletedExpr *, Node::ref_type );
     298inline void decrement( const class DeletedExpr *, Node::ref_type );
     299inline void increment( const class DefaultArgExpr *, Node::ref_type );
     300inline void decrement( const class DefaultArgExpr *, Node::ref_type );
     301inline void increment( const class GenericExpr *, Node::ref_type );
     302inline void decrement( const class GenericExpr *, Node::ref_type );
     303inline void increment( const class Type *, Node::ref_type );
     304inline void decrement( const class Type *, Node::ref_type );
     305inline void increment( const class VoidType *, Node::ref_type );
     306inline void decrement( const class VoidType *, Node::ref_type );
     307inline void increment( const class BasicType *, Node::ref_type );
     308inline void decrement( const class BasicType *, Node::ref_type );
     309inline void increment( const class PointerType *, Node::ref_type );
     310inline void decrement( const class PointerType *, Node::ref_type );
     311inline void increment( const class ArrayType *, Node::ref_type );
     312inline void decrement( const class ArrayType *, Node::ref_type );
     313inline void increment( const class ReferenceType *, Node::ref_type );
     314inline void decrement( const class ReferenceType *, Node::ref_type );
     315inline void increment( const class QualifiedType *, Node::ref_type );
     316inline void decrement( const class QualifiedType *, Node::ref_type );
     317inline void increment( const class FunctionType *, Node::ref_type );
     318inline void decrement( const class FunctionType *, Node::ref_type );
     319inline void increment( const class ReferenceToType *, Node::ref_type );
     320inline void decrement( const class ReferenceToType *, Node::ref_type );
     321inline void increment( const class StructInstType *, Node::ref_type );
     322inline void decrement( const class StructInstType *, Node::ref_type );
     323inline void increment( const class UnionInstType *, Node::ref_type );
     324inline void decrement( const class UnionInstType *, Node::ref_type );
     325inline void increment( const class EnumInstType *, Node::ref_type );
     326inline void decrement( const class EnumInstType *, Node::ref_type );
     327inline void increment( const class TraitInstType *, Node::ref_type );
     328inline void decrement( const class TraitInstType *, Node::ref_type );
     329inline void increment( const class TypeInstType *, Node::ref_type );
     330inline void decrement( const class TypeInstType *, Node::ref_type );
     331inline void increment( const class TupleType *, Node::ref_type );
     332inline void decrement( const class TupleType *, Node::ref_type );
     333inline void increment( const class TypeofType *, Node::ref_type );
     334inline void decrement( const class TypeofType *, Node::ref_type );
     335inline void increment( const class AttrType *, Node::ref_type );
     336inline void decrement( const class AttrType *, Node::ref_type );
     337inline void increment( const class VarArgsType *, Node::ref_type );
     338inline void decrement( const class VarArgsType *, Node::ref_type );
     339inline void increment( const class ZeroType *, Node::ref_type );
     340inline void decrement( const class ZeroType *, Node::ref_type );
     341inline void increment( const class OneType *, Node::ref_type );
     342inline void decrement( const class OneType *, Node::ref_type );
     343inline void increment( const class GlobalScopeType *, Node::ref_type );
     344inline void decrement( const class GlobalScopeType *, Node::ref_type );
     345inline void increment( const class Designation *, Node::ref_type );
     346inline void decrement( const class Designation *, Node::ref_type );
     347inline void increment( const class Init *, Node::ref_type );
     348inline void decrement( const class Init *, Node::ref_type );
     349inline void increment( const class SingleInit *, Node::ref_type );
     350inline void decrement( const class SingleInit *, Node::ref_type );
     351inline void increment( const class ListInit *, Node::ref_type );
     352inline void decrement( const class ListInit *, Node::ref_type );
     353inline void increment( const class ConstructorInit *, Node::ref_type );
     354inline void decrement( const class ConstructorInit *, Node::ref_type );
     355inline void increment( const class Constant *, Node::ref_type );
     356inline void decrement( const class Constant *, Node::ref_type );
     357inline void increment( const class Label *, Node::ref_type );
     358inline void decrement( const class Label *, Node::ref_type );
     359inline void increment( const class Attribute *, Node::ref_type );
     360inline void decrement( const class Attribute *, Node::ref_type );
     361inline void increment( const class TypeSubstitution *, Node::ref_type );
     362inline void decrement( const class TypeSubstitution *, Node::ref_type );
     363
    139364typedef unsigned int UniqueId;
    140365
  • src/AST/Init.hpp

    r0727d97 r336d0b3  
    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
     119inline void increment( const class Init * node, Node::ref_type ref ) { node->increment( ref ); }
     120inline void decrement( const class Init * node, Node::ref_type ref ) { node->decrement( ref ); }
     121inline void increment( const class SingleInit * node, Node::ref_type ref ) { node->increment( ref ); }
     122inline void decrement( const class SingleInit * node, Node::ref_type ref ) { node->decrement( ref ); }
     123inline void increment( const class ListInit * node, Node::ref_type ref ) { node->increment( ref ); }
     124inline void decrement( const class ListInit * node, Node::ref_type ref ) { node->decrement( ref ); }
     125inline void increment( const class ConstructorInit * node, Node::ref_type ref ) { node->increment( ref ); }
     126inline void decrement( const class ConstructorInit * node, Node::ref_type ref ) { node->decrement( ref ); }
    113127}
    114128
  • src/AST/Label.hpp

    r0727d97 r336d0b3  
    2525namespace ast {
    2626
    27         class Attribute;
     27class 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
     30class Label {
     31public:
     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; }
     44inline bool operator== ( const Label& l1, const Label& l2 ) { return l1.name == l2.name; }
     45inline bool operator!= ( const Label& l1, const Label& l2 ) { return !(l1 == l2); }
     46inline 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; }
     48inline 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
     56inline void increment( const class Label * node, Node::ref_type ref ) { node->increment( ref ); }
     57inline void decrement( const class Label * node, Node::ref_type ref ) { node->decrement( ref ); }
    4958
    5059}
  • src/AST/LinkageSpec.hpp

    r0727d97 r336d0b3  
    3535
    3636        /// Bitflag type for storage classes
    37         union Spec {
    38                 unsigned int val;
    39                 struct {
    40                         bool is_mangled      : 1;
    41                         bool is_generatable  : 1;
    42                         bool is_overrideable : 1;
    43                         bool is_builtin      : 1;
    44                         bool is_gcc_builtin  : 1;
     37        struct spec_flags {
     38                union {
     39                        unsigned int val;
     40                        struct {
     41                                bool is_mangled      : 1;
     42                                bool is_generatable  : 1;
     43                                bool is_overrideable : 1;
     44                                bool is_builtin      : 1;
     45                                bool is_gcc_builtin  : 1;
     46                        };
    4547                };
    4648
    47                 MakeBitfield( Spec )
     49                constexpr spec_flags( unsigned int val ) : val(val) {}
    4850        };
     51
     52        using Spec = bitfield<spec_flags>;
    4953
    5054        /// If `cmd` = "C" returns `spec` with `is_mangled = false`.
  • src/AST/ParseNode.hpp

    r0727d97 r336d0b3  
    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
     25class ParseNode : public Node {
     26public:
     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
     44inline void increment( const class ParseNode * node, Node::ref_type ref ) { node->increment( ref ); }
     45inline void decrement( const class ParseNode * node, Node::ref_type ref ) { node->decrement( ref ); }
    3846}
    3947
  • src/AST/Pass.hpp

    r0727d97 r336d0b3  
     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
    116#pragma once
    2 // IWYU pragma: private, include "Common/PassVisitor.h"
     17// IWYU pragma: private, include "AST/Pass.hpp"
    318
    419#include <functional>
     
    621#include <stack>
    722
    8 #include "Fwd.hpp"
    9 #include "Node.hpp"
     23#include "AST/Fwd.hpp"
     24#include "AST/Node.hpp"
     25#include "AST/Decl.hpp"
     26#include "AST/Visitor.hpp"
     27
     28#include "SymTab/Indexer.h"
    1029
    1130// Private prelude header, needed for some of the magic tricks this class pulls off
    12 #include "Pass.proto.hpp"
     31#include "AST/Pass.proto.hpp"
    1332
    1433namespace ast {
     
    2039//
    2140// Several additional features are available through inheritance
    22 // | WithTypeSubstitution - provides polymorphic TypeSubstitution * env for the current expression
     41// | WithTypeSubstitution - provides polymorphic const TypeSubstitution * env for the
     42//                          current expression
    2343// | WithStmtsToAdd       - provides the ability to insert statements before or after the current
    2444//                          statement by adding new statements into stmtsToAddBefore or
    2545//                          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.
    2649// | WithShortCircuiting  - provides the ability to skip visiting child nodes; set visit_children
    2750//                          to false in pre{visit,visit} to skip visiting children
     
    3053//                          automatically be restored to its previous value after the corresponding
    3154//                          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)
    3257//-------------------------------------------------------------------------------------------------
    3358template< typename pass_t >
    3459class Pass final : public ast::Visitor {
    3560public:
     61        /// Forward any arguments to the pass constructor
     62        /// Propagate 'this' if necessary
    3663        template< typename... Args >
    3764        Pass( Args &&... args)
    38                 : m_pass( std::forward<Args>( args )... )
     65                : pass( std::forward<Args>( args )... )
    3966        {
    4067                // After the pass is constructed, check if it wants the have a pointer to the wrapping visitor
    4168                typedef Pass<pass_t> this_t;
    42                 this_t * const * visitor = __pass::visitor(m_pass, 0);
     69                this_t * const * visitor = __pass::visitor(pass, 0);
    4370                if(visitor) {
    4471                        *const_cast<this_t **>( visitor ) = this;
     
    4875        virtual ~Pass() = default;
    4976
    50         pass_t m_pass;
    51 
     77        /// Storage for the actual pass
     78        pass_t pass;
     79
     80        /// Visit function declarations
    5281        virtual DeclWithType *     visit( const ObjectDecl           * ) override final;
    5382        virtual DeclWithType *     visit( const FunctionDecl         * ) override final;
     
    145174        virtual TypeSubstitution * visit( const TypeSubstitution     * ) override final;
    146175
     176        friend void acceptAll( std::list< ptr<Decl> > & decls, Pass<pass_t>& visitor );
    147177private:
    148178
    149         bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(m_pass, 0); return ptr ? *ptr : true; }
     179        bool __visit_children() { __pass::bool_ref * ptr = __pass::visit_children(pass, 0); return ptr ? *ptr : true; }
    150180
    151181private:
     182        /// Logic to call the accept and mutate the parent if needed, delegates call to accept
    152183        template<typename parent_t, typename child_t>
    153184        void maybe_accept(parent_t * & , typename parent_t::child_t *);
    154185
    155         ast::Statement  * call_accept( const ast::Statement * );
    156         ast::Expression * call_accept( const ast::Expression * );
     186        Stmt * call_accept( const Stmt * );
     187        Expr * call_accept( const Expr * );
    157188
    158189        template< template <class> class container_t >
    159         container_t< ast::ptr<ast::Statement> > call_accept( const container_t< ast::ptr<ast::Statement> > & );
     190        container_t< ptr<Stmt> > call_accept( const container_t< ptr<Stmt> > & );
    160191
    161192        template< template <class> class container_t, typename node_t >
    162         container_t< ast::ptr<node_t> > call_accept( const container_t< ast::ptr<node_t> > & container );
     193        container_t< ptr<node_t> > call_accept( const container_t< ptr<node_t> > & container );
    163194
    164195private:
    165         struct indexer_guard {
     196        /// Internal RAII guard for indexer features
     197        struct guard_indexer {
     198                guard_indexer( Pass<pass_t> & pass ): pass( pass ) { __pass::indexer::enter(pass, 0); }
     199                ~guard_indexer()                                   { __pass::indexer::leave(pass, 0); }
    166200                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); }
    170201        };
    171202
    172         indexer_guard make_indexer_guard() { return { *this }; }
    173 
    174 private:
    175         struct scope_guard {
     203        /// Internal RAII guard for scope features
     204        struct guard_scope {
     205                guard_scope( Pass<pass_t> & pass ): pass( pass ) { __pass::scope::enter(pass, 0); }
     206                ~guard_scope()                                   { __pass::scope::leave(pass, 0); }
    176207                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); }
    180208        };
    181 
    182         scope_guard make_scope_guard() { return { *this }; }
    183 };
    184 
    185 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    186 // Guard value : RAII type to restore a value when the Pass finishes visiting this node
    187 template<typename pass_t, typename T>
    188 void GuardValue( pass_t * pass, T& val ) {
    189         pass->at_cleanup( [ val ]( void * newVal ) {
    190                 * static_cast< T * >( newVal ) = val;
    191         }, static_cast< void * >( & val ) );
    192 }
    193 
    194 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     209};
     210
     211template<typename pass_t>
     212void acceptAll( std::list< ptr<Decl> >, Pass<pass_t>& visitor );
     213
     214//-------------------------------------------------------------------------------------------------
    195215// PASS ACCESSORIES
    196 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    197 
    198 // Keep track of the type substitution
    199 struct WithConstTypeSubstitution {
    200         const ast::TypeSubstitution * env = nullptr;
    201 };
     216//-------------------------------------------------------------------------------------------------
    202217
    203218template<typename T>
    204219using std_list = std::list<T>;
    205220
    206 // Used if visitor requires added statements before or after the current node.
    207 // The Pass template handles what *before* and *after* means automatically
     221/// Keep track of the polymorphic const TypeSubstitution * env for the current expression
     222struct 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
    208228template< template<class> class container_t = std_list >
    209229struct WithStmtsToAdd {
    210         container_t< ast::ptr< ast::Statement > > stmtsToAddBefore;
    211         container_t< ast::ptr< ast::Statement > > stmtsToAddAfter;
    212 };
    213 
    214 // Used if visitor requires added declarations before or after the current node.
    215 // The Pass template handles what *before* and *after* means automatically
     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
    216236template< template<class> class container_t = std_list >
    217237struct WithDeclsToAdd {
    218         ~WithDeclsToAdd() {
    219                 assert( declsToAddBefore.empty() );
    220         }
    221 
    222         container_t< ast::ptr< ast::Declaration > > declsToAddBefore;
    223         container_t< ast::ptr< ast::Declaration > > declsToAddAfter;
    224 };
    225 
    226 // Use if visitation should stop at certain levels
    227 // set visit_children false of all child nodes should be ignored
     238        container_t< ptr<Decl> > declsToAddBefore;
     239        container_t< ptr<Decl> > declsToAddAfter;
     240};
     241
     242/// Use if visitation should stop at certain levels
     243/// set visit_children false of all child nodes should be ignored
    228244struct WithShortCircuiting {
    229245        __pass::bool_ref visit_children;
    230246};
    231247
    232 // class WithGuards {
    233 // protected:
    234 //      WithGuards() = default;
    235 //      ~WithGuards() = default;
    236 
    237 // public:
    238 //      at_cleanup_t at_cleanup;
    239 
    240 //      template< typename T >
    241 //      void GuardValue( T& val ) {
    242 //              at_cleanup( [ val ]( void * newVal ) {
    243 //                      * static_cast< T * >( newVal ) = val;
    244 //              }, static_cast< void * >( & val ) );
    245 //      }
    246 
    247 //      template< typename T >
    248 //      void GuardScope( T& val ) {
    249 //              val.beginScope();
    250 //              at_cleanup( []( void * val ) {
    251 //                      static_cast< T * >( val )->endScope();
    252 //              }, static_cast< void * >( & val ) );
    253 //      }
    254 
    255 //      template< typename Func >
    256 //      void GuardAction( Func func ) {
    257 //              at_cleanup( [func](__attribute__((unused)) void *) { func(); }, nullptr );
    258 //      }
    259 // };
    260 
    261 // template<typename pass_type>
    262 // class WithVisitorRef {
    263 // protected:
    264 //      WithVisitorRef() {}
    265 //      ~WithVisitorRef() {}
    266 
    267 // public:
    268 //      PassVisitor<pass_type> * const visitor = nullptr;
    269 // };
    270 
     248/// Used to restore values/functions/etc. when the Pass finishes visiting this node
     249class WithGuards {
     250        __pass::at_cleanup_t at_cleanup;
     251
     252public:
     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
     278template<typename pass_t>
     279struct WithVisitorRef {
     280        Pass<pass_t> * const visitor = nullptr;
     281};
     282
     283/// Use when the templated visitor should update the indexer
    271284struct WithIndexer {
    272285        SymTab::Indexer indexer;
  • src/AST/Pass.impl.hpp

    r0727d97 r336d0b3  
     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
    116#pragma once
    2 // IWYU pragma: private, include "Pass.hpp"
     17// IWYU pragma: private, include "AST/Pass.hpp"
    318
    419#define VISIT_START( node ) \
     20        using namespace ast; \
    521        /* back-up the visit children */ \
    6         __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(m_pass, 0) ); \
     22        __attribute__((unused)) ast::__pass::visit_children_guard guard1( ast::__pass::visit_children(pass, 0) ); \
    723        /* setup the scope for passes that want to run code at exit */ \
    8         __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (m_pass, 0) ); \
     24        __attribute__((unused)) ast::__pass::guard_value          guard2( ast::__pass::at_cleanup    (pass, 0) ); \
    925        /* call the implementation of the previsit of this pass */ \
    10         __pass::previsit( m_pass, node, 0 );
     26        __pass::previsit( pass, node, 0 );
    1127
    1228#define VISIT( code ) \
     
    98114
    99115        template< typename pass_t >
    100         ast::Expression * Pass< pass_t >::call_accept( const ast::Expression * expr ) {
     116        ast::Expr * Pass< pass_t >::call_accept( const ast::Expr * expr ) {
    101117                __pedantic_pass_assert( __visit_children() );
    102118                __pedantic_pass_assert( expr );
    103119
    104                 const ast::TypeSubstitution ** env_ptr = __pass::env( m_pass, 0);
     120                const ast::TypeSubstitution ** env_ptr = __pass::env( pass, 0);
    105121                if ( env_ptr && expr->env ) {
    106122                        *env_ptr = expr->env;
     
    111127
    112128        template< typename pass_t >
    113         ast::Statement * Pass< pass_t >::call_accept( const ast::Statement * stmt ) {
     129        Stmt * Pass< pass_t >::call_accept( const Stmt * stmt ) {
    114130                __pedantic_pass_assert( __visit_children() );
    115131                __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;
    173132
    174133                // add a few useful symbols to the scope
     
    182141
    183142                // 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);  );
    184144                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_before) > __old_decls_before( stmts_before );
    185145                ValueGuardPtr< typename std::remove_pointer< decltype(stmts_after ) > __old_decls_after ( stmts_after  );
     
    187147                ValueGuardPtr< typename std::remove_pointer< decltype(decls_after ) > __old_stmts_after ( decls_after  );
    188148
     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
    189203                // update pass statitistics
    190204                pass_visitor_stats.depth++;
     
    193207
    194208                bool mutated = false;
    195                 container_t<ast::ptr< ast::Statement >> new_kids;
    196                 for( const ast::Statement * stmt : statements ) {
     209                container_t< ptr<Stmt> > new_kids;
     210                for( const Stmt * stmt : statements ) {
    197211                        try {
    198212                                __pedantic_pass_assert( stmt );
     
    269283//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    270284
     285template< typename pass_t >
     286inline 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
    271325// A NOTE ON THE ORDER OF TRAVERSAL
    272326//
     
    289343// ObjectDecl
    290344template< typename pass_t >
    291 ast::DeclarationWithType * Pass< pass_t >::mutate( ast::ObjectDecl * node ) {
     345ast::DeclWithType * ast::Pass< pass_t >::visit( const ast::ObjectDecl * node ) {
    292346        VISIT_START( node );
    293347
    294348        VISIT(
    295349                {
    296                         auto guard = make_indexer_guard();
    297                         maybe_accept( node, ast::ObjectDecl::type );
    298                 }
    299                 maybe_accept( node, ast::ObjectDecl::init          );
    300                 maybe_accept( node, ast::ObjectDecl::bitfieldWidth );
    301                 maybe_accept( node, ast::ObjectDecl::attributes    );
     350                        indexer_guard guard { *this };
     351                        maybe_accept( node, ObjectDecl::type );
     352                }
     353                maybe_accept( node, ObjectDecl::init          );
     354                maybe_accept( node, ObjectDecl::bitfieldWidth );
     355                maybe_accept( node, ObjectDecl::attributes    );
    302356        )
    303357
    304         __pass::indexer::AddId( m_pass, 0, node );
    305 
    306         VISIT_END( DeclarationWithType, node );
     358        __pass::indexer::AddId( pass, 0, node );
     359
     360        VISIT_END( DeclWithType, node );
    307361}
    308362
     
    310364// Attribute
    311365template< typename pass_type >
    312 ast::Attribute * ast::Pass< pass_type >::visit( ast::ptr<ast::Attribute> & node  )  {
     366ast::Attribute * ast::Pass< pass_type >::visit( const ast::Attribute * node  )  {
    313367        VISIT_START(node);
    314368
     
    323377// TypeSubstitution
    324378template< typename pass_type >
    325 TypeSubstitution * PassVisitor< pass_type >::mutate( TypeSubstitution * node ) {
     379TypeSubstitution * PassVisitor< pass_type >::mutate( const TypeSubstitution * node ) {
    326380        MUTATE_START( node );
    327381
  • src/AST/Pass.proto.hpp

    r0727d97 r336d0b3  
     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
    116#pragma once
    217// IWYU pragma: private, include "Pass.hpp"
    318
    419namespace ast {
    5         template<typename pass_type>
    6         class Pass;
    7 
    8         namespace __pass {
    9                 typedef std::function<void( void * )> cleanup_func_t;
    10                 typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t;
    11 
    12 
    13                 // boolean reference that may be null
    14                 // either refers to a boolean value or is null and returns true
    15                 class bool_ref {
    16                 public:
    17                         bool_ref() = default;
    18                         ~bool_ref() = default;
    19 
    20                         operator bool() { return m_ref ? *m_ref : true; }
    21                         bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
    22 
    23                 private:
    24 
    25                         friend class visit_children_guard;
    26 
    27                         bool * set( bool * val ) {
    28                                 bool * prev = m_ref;
    29                                 m_ref = val;
    30                                 return prev;
     20template<typename pass_type>
     21class Pass;
     22
     23namespace __pass {
     24        typedef std::function<void( void * )> cleanup_func_t;
     25        typedef std::function<void( cleanup_func_t, void * )> at_cleanup_t;
     26
     27
     28        // boolean reference that may be null
     29        // either refers to a boolean value or is null and returns true
     30        class bool_ref {
     31        public:
     32                bool_ref() = default;
     33                ~bool_ref() = default;
     34
     35                operator bool() { return m_ref ? *m_ref : true; }
     36                bool operator=( bool val ) { assert(m_ref); return *m_ref = val; }
     37
     38        private:
     39
     40                friend class visit_children_guard;
     41
     42                bool * set( bool * val ) {
     43                        bool * prev = m_ref;
     44                        m_ref = val;
     45                        return prev;
     46                }
     47
     48                bool * m_ref = nullptr;
     49        };
     50
     51        // Implementation of the guard value
     52        // Created inside the visit scope
     53        class guard_value {
     54        public:
     55                /// Push onto the cleanup
     56                guard_value( at_cleanup_t * at_cleanup ) {
     57                        if( at_cleanup ) {
     58                                *at_cleanup = [this]( cleanup_func_t && func, void* val ) {
     59                                        push( std::move( func ), val );
     60                                };
    3161                        }
    32 
    33                         bool * m_ref = nullptr;
     62                }
     63
     64                ~guard_value() {
     65                        while( !cleanups.empty() ) {
     66                                auto& cleanup = cleanups.top();
     67                                cleanup.func( cleanup.val );
     68                                cleanups.pop();
     69                        }
     70                }
     71
     72                void push( cleanup_func_t && func, void* val ) {
     73                        cleanups.emplace( std::move(func), val );
     74                }
     75
     76        private:
     77                struct cleanup_t {
     78                        cleanup_func_t func;
     79                        void * val;
     80
     81                        cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {}
    3482                };
    3583
    36                 // Implementation of the guard value
    37                 // Created inside the visit scope
    38                 class guard_value {
    39                 public:
    40                         guard_value( at_cleanup_t * at_cleanup ) {
    41                                 if( at_cleanup ) {
    42                                         *at_cleanup = [this]( cleanup_func_t && func, void* val ) {
    43                                                 push( std::move( func ), val );
    44                                         };
    45                                 }
     84                std::stack< cleanup_t > cleanups;
     85        };
     86
     87        // Guard structure implementation for whether or not children should be visited
     88        class visit_children_guard {
     89        public:
     90
     91                visit_children_guard( bool_ref * ref )
     92                        : m_val ( true )
     93                        , m_prev( ref ? ref->set( &m_val ) : nullptr )
     94                        , m_ref ( ref )
     95                {}
     96
     97                ~visit_children_guard() {
     98                        if( m_ref ) {
     99                                m_ref->set( m_prev );
    46100                        }
    47 
    48                         ~guard_value() {
    49                                 while( !cleanups.empty() ) {
    50                                         auto& cleanup = cleanups.top();
    51                                         cleanup.func( cleanup.val );
    52                                         cleanups.pop();
    53                                 }
    54                         }
    55 
    56                         void push( cleanup_func_t && func, void* val ) {
    57                                 cleanups.emplace( std::move(func), val );
    58                         }
    59 
    60                 private:
    61                         struct cleanup_t {
    62                                 cleanup_func_t func;
    63                                 void * val;
    64 
    65                                 cleanup_t( cleanup_func_t&& func, void * val ) : func(func), val(val) {}
    66                         };
    67 
    68                         std::stack< cleanup_t > cleanups;
    69                 };
    70 
    71                 // Guard structure implementation for whether or not children should be visited
    72                 class visit_children_guard {
    73                 public:
    74 
    75                         visit_children_guard( bool_ref * ref )
    76                                 : m_val ( true )
    77                                 , m_prev( ref ? ref->set( &m_val ) : nullptr )
    78                                 , m_ref ( ref )
    79                         {}
    80 
    81                         ~visit_children_guard() {
    82                                 if( m_ref ) {
    83                                         m_ref->set( m_prev );
    84                                 }
    85                         }
    86 
    87                         operator bool() { return m_val; }
    88 
    89                 private:
    90                         bool       m_val;
    91                         bool     * m_prev;
    92                         bool_ref * m_ref;
    93                 };
    94 
    95                 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    96                 // Deep magic (a.k.a template meta programming) to make the templated visitor work
    97                 // Basically the goal is to make 2 previsit
    98                 // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
    99                 //     'pass.previsit( node )' that compiles will be used for that node for that type
    100                 //     This requires that this option only compile for passes that actually define an appropriate visit.
    101                 //     SFINAE will make sure the compilation errors in this function don't halt the build.
    102                 //     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
    103                 // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
    104                 //     This is needed only to eliminate the need for passes to specify any kind of handlers.
    105                 //     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
    106                 //     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
    107                 //     the first implementation takes priority in regards to overloading.
    108                 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    109                 // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
    110                 template<typename pass_t, typename node_t>
    111                 static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) {
    112                         node = pass.previsit( node );
    113                         assert(node);
    114                 }
    115 
    116                 template<typename pass_t, typename node_t>
    117                 static inline auto previsit( pass_t &, const node_t *, long ) {}
    118 
    119                 // PostVisit : never mutates the passed pointer but may return a different node
    120                 template<typename pass_t, typename node_t>
    121                 static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> decltype( pass.postvisit( node ), (const node_t *)nullptr ) {
    122                         return pass.postvisit( node );
    123                 }
    124 
    125                 template<typename pass_t, typename node_t>
    126                 static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; }
    127 
    128                 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    129                 // Deep magic (a.k.a template meta programming) continued
    130                 // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit
    131                 // from in order to get extra functionallity for example
    132                 // class ErrorChecker : WithShortCircuiting { ... };
    133                 // Pass<ErrorChecker> checker;
    134                 // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting
    135                 // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched
    136                 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    137                 // For several accessories, the feature is enabled by detecting that a specific field is present
    138                 // Use a macro the encapsulate the logic of detecting a particular field
    139                 // The type is not strictly enforced but does match the accessory
    140                 #define FIELD_PTR( name, default_type ) \
    141                 template< typename pass_t > \
    142                 static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \
     101                }
     102
     103                operator bool() { return m_val; }
     104
     105        private:
     106                bool       m_val;
     107                bool     * m_prev;
     108                bool_ref * m_ref;
     109        };
     110
     111        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     112        // Deep magic (a.k.a template meta programming) to make the templated visitor work
     113        // Basically the goal is to make 2 previsit
     114        // 1 - Use when a pass implements a valid previsit. This uses overloading which means the any overload of
     115        //     'pass.previsit( node )' that compiles will be used for that node for that type
     116        //     This requires that this option only compile for passes that actually define an appropriate visit.
     117        //     SFINAE will make sure the compilation errors in this function don't halt the build.
     118        //     See http://en.cppreference.com/w/cpp/language/sfinae for details on SFINAE
     119        // 2 - Since the first implementation might not be specilizable, the second implementation exists and does nothing.
     120        //     This is needed only to eliminate the need for passes to specify any kind of handlers.
     121        //     The second implementation only works because it has a lower priority. This is due to the bogus last parameter.
     122        //     The second implementation takes a long while the first takes an int. Since the caller always passes an literal 0
     123        //     the first implementation takes priority in regards to overloading.
     124        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     125        // PreVisit : may mutate the pointer passed in if the node is mutated in the previsit call
     126        template<typename pass_t, typename node_t>
     127        static inline auto previsit( pass_t & pass, const node_t * & node, int ) -> decltype( pass.previsit( node ), void() ) {
     128                node = pass.previsit( node );
     129                assert(node);
     130        }
     131
     132        template<typename pass_t, typename node_t>
     133        static inline auto previsit( pass_t &, const node_t *, long ) {}
     134
     135        // PostVisit : never mutates the passed pointer but may return a different node
     136        template<typename pass_t, typename node_t>
     137        static inline auto postvisit( pass_t & pass, const node_t * node, int ) -> decltype( pass.postvisit( node ), (const node_t *)nullptr ) {
     138                return pass.postvisit( node );
     139        }
     140
     141        template<typename pass_t, typename node_t>
     142        static inline const node_t * postvisit( pass_t &, const node_t * node, long ) { return node; }
     143
     144        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     145        // Deep magic (a.k.a template meta programming) continued
     146        // To make the templated visitor be more expressive, we allow 'accessories' : classes/structs the implementation can inherit
     147        // from in order to get extra functionallity for example
     148        // class ErrorChecker : WithShortCircuiting { ... };
     149        // Pass<ErrorChecker> checker;
     150        // this would define a pass that uses the templated visitor with the additionnal feature that it has short circuiting
     151        // Note that in all cases the accessories are not required but guarantee the requirements of the feature is matched
     152        //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     153        // For several accessories, the feature is enabled by detecting that a specific field is present
     154        // Use a macro the encapsulate the logic of detecting a particular field
     155        // The type is not strictly enforced but does match the accessory
     156        #define FIELD_PTR( name, default_type ) \
     157        template< typename pass_t > \
     158        static inline auto name( pass_t & pass, int ) -> decltype( &pass.name ) { return &pass.name; } \
     159        \
     160        template< typename pass_t > \
     161        static inline default_type * name( pass_t &, long ) { return nullptr; }
     162
     163        // List of fields and their expected types
     164        FIELD_PTR( env, const ast::TypeSubstitution )
     165        FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
     166        FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
     167        FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > )
     168        FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > )
     169        FIELD_PTR( visit_children, __pass::bool_ref )
     170        FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
     171        FIELD_PTR( visitor, ast::Pass<pass_t> * const )
     172
     173        // Remove the macro to make sure we don't clash
     174        #undef FIELD_PTR
     175
     176        // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
     177        // All passes which have such functions are assumed desire this behaviour
     178        // detect it using the same strategy
     179        namespace scope {
     180                template<typename pass_t>
     181                static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) {
     182                        pass.beginScope();
     183                }
     184
     185                template<typename pass_t>
     186                static inline void enter( pass_t &, long ) {}
     187
     188                template<typename pass_t>
     189                static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) {
     190                        pass.endScope();
     191                }
     192
     193                template<typename pass_t>
     194                static inline void leave( pass_t &, long ) {}
     195        };
     196
     197        // Finally certain pass desire an up to date indexer automatically
     198        // detect the presence of a member name indexer and call all the members appropriately
     199        namespace indexer {
     200                // Some simple scoping rules
     201                template<typename pass_t>
     202                static inline auto enter( pass_t & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) {
     203                        pass.indexer.enterScope();
     204                }
     205
     206                template<typename pass_t>
     207                static inline auto enter( pass_t &, long ) {}
     208
     209                template<typename pass_t>
     210                static inline auto leave( pass_t & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) {
     211                        pass.indexer.leaveScope();
     212                }
     213
     214                template<typename pass_t>
     215                static inline auto leave( pass_t &, long ) {}
     216
     217                // The indexer has 2 kind of functions mostly, 1 argument and 2 arguments
     218                // Create macro to condense these common patterns
     219                #define INDEXER_FUNC1( func, type ) \
     220                template<typename pass_t> \
     221                static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {\
     222                        pass.indexer.func( arg ); \
     223                } \
    143224                \
    144                 template< typename pass_t > \
    145                 static inline default_type * name( pass_t &, long ) { return nullptr; }
    146 
    147                 // List of fields and their expected types
    148                 FIELD_PTR( env, const ast::TypeSubstitution )
    149                 FIELD_PTR( stmtsToAddBefore, std::list< ast::ptr< ast::Stmt > > )
    150                 FIELD_PTR( stmtsToAddAfter , std::list< ast::ptr< ast::Stmt > > )
    151                 FIELD_PTR( declsToAddBefore, std::list< ast::ptr< ast::Decl > > )
    152                 FIELD_PTR( declsToAddAfter , std::list< ast::ptr< ast::Decl > > )
    153                 FIELD_PTR( visit_children, __pass::bool_ref )
    154                 FIELD_PTR( at_cleanup, __pass::at_cleanup_t )
    155                 FIELD_PTR( visitor, ast::Pass<pass_t> * const )
    156 
    157                 // Remove the macro to make sure we don't clash
    158                 #undef FIELD_PTR
    159 
    160                 // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
    161                 // All passes which have such functions are assumed desire this behaviour
    162                 // detect it using the same strategy
    163                 namespace scope {
    164                         template<typename pass_t>
    165                         static inline auto enter( pass_t & pass, int ) -> decltype( pass.beginScope(), void() ) {
    166                                 pass.beginScope();
    167                         }
    168 
    169                         template<typename pass_t>
    170                         static inline void enter( pass_t &, long ) {}
    171 
    172                         template<typename pass_t>
    173                         static inline auto leave( pass_t & pass, int ) -> decltype( pass.endScope(), void() ) {
    174                                 pass.endScope();
    175                         }
    176 
    177                         template<typename pass_t>
    178                         static inline void leave( pass_t &, long ) {}
    179                 };
    180 
    181                 // Finally certain pass desire an up to date indexer automatically
    182                 // detect the presence of a member name indexer and call all the members appropriately
    183                 namespace indexer {
    184                         // Some simple scoping rules
    185                         template<typename pass_t>
    186                         static inline auto enter( pass_t & pass, int ) -> decltype( pass.indexer.enterScope(), void() ) {
    187                                 pass.indexer.enterScope();
    188                         }
    189 
    190                         template<typename pass_t>
    191                         static inline auto enter( pass_t &, long ) {}
    192 
    193                         template<typename pass_t>
    194                         static inline auto leave( pass_t & pass, int ) -> decltype( pass.indexer.leaveScope(), void() ) {
    195                                 pass.indexer.leaveScope();
    196                         }
    197 
    198                         template<typename pass_t>
    199                         static inline auto leave( pass_t &, long ) {}
    200 
    201                         // The indexer has 2 kind of functions mostly, 1 argument and 2 arguments
    202                         // Create macro to condense these common patterns
    203                         #define INDEXER_FUNC1( func, type ) \
    204                         template<typename pass_t> \
    205                         static inline auto func( pass_t & pass, int, type arg ) -> decltype( pass.indexer.func( arg ), void() ) {\
    206                                 pass.indexer.func( arg ); \
    207                         } \
     225                template<typename pass_t> \
     226                static inline void func( pass_t &, long, type ) {}
     227
     228                #define INDEXER_FUNC2( func, type1, type2 ) \
     229                template<typename pass_t> \
     230                static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void () ) {\
     231                        pass.indexer.func( arg1, arg2 ); \
     232                } \
    208233                        \
    209                         template<typename pass_t> \
    210                         static inline void func( pass_t &, long, type ) {}
    211 
    212                         #define INDEXER_FUNC2( func, type1, type2 ) \
    213                         template<typename pass_t> \
    214                         static inline auto func( pass_t & pass, int, type1 arg1, type2 arg2 ) -> decltype( pass.indexer.func( arg1, arg2 ), void () ) {\
    215                                 pass.indexer.func( arg1, arg2 ); \
    216                         } \
    217                          \
    218                         template<typename pass_t> \
    219                         static inline void func( pass_t &, long, type1, type2 ) {}
    220 
    221                         INDEXER_FUNC1( addId     , DeclarationWithType *       );
    222                         INDEXER_FUNC1( addType   , NamedTypeDecl *             );
    223                         INDEXER_FUNC1( addStruct , StructDecl *                );
    224                         INDEXER_FUNC1( addEnum   , EnumDecl *                  );
    225                         INDEXER_FUNC1( addUnion  , UnionDecl *                 );
    226                         INDEXER_FUNC1( addTrait  , TraitDecl *                 );
    227                         INDEXER_FUNC2( addWith   , std::list< Expression * > &, BaseSyntaxNode * );
    228 
    229                         // A few extra functions have more complicated behaviour, they are hand written
    230                         template<typename pass_t>
    231                         static inline auto addStructFwd( pass_t & pass, int, ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
    232                                 ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
    233                                 fwd->parameters = decl->parameters;
    234                                 pass.indexer.addStruct( fwd );
    235                         }
    236 
    237                         template<typename pass_t>
    238                         static inline void addStructFwd( pass_t &, long, ast::StructDecl * ) {}
    239 
    240                         template<typename pass_t>
    241                         static inline auto addUnionFwd( pass_t & pass, int, ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
    242                                 UnionDecl * fwd = new UnionDecl( decl->name );
    243                                 fwd->parameters = decl->parameters;
    244                                 pass.indexer.addUnion( fwd );
    245                         }
    246 
    247                         template<typename pass_t>
    248                         static inline void addUnionFwd( pass_t &, long, ast::UnionDecl * ) {}
    249 
    250                         template<typename pass_t>
    251                         static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) {
    252                                 if ( ! pass.indexer.lookupStruct( str ) ) {
    253                                         pass.indexer.addStruct( str );
    254                                 }
    255                         }
    256 
    257                         template<typename pass_t>
    258                         static inline void addStruct( pass_t &, long, const std::string & ) {}
    259 
    260                         template<typename pass_t>
    261                         static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) {
    262                                 if ( ! pass.indexer.lookupUnion( str ) ) {
    263                                         pass.indexer.addUnion( str );
    264                                 }
    265                         }
    266 
    267                         template<typename pass_t>
    268                         static inline void addUnion( pass_t &, long, const std::string & ) {}
    269 
    270                         #undef INDEXER_FUNC1
    271                         #undef INDEXER_FUNC2
    272                 };
     234                template<typename pass_t> \
     235                static inline void func( pass_t &, long, type1, type2 ) {}
     236
     237                INDEXER_FUNC1( addId     , DeclWithType *  );
     238                INDEXER_FUNC1( addType   , NamedTypeDecl * );
     239                INDEXER_FUNC1( addStruct , StructDecl *    );
     240                INDEXER_FUNC1( addEnum   , EnumDecl *      );
     241                INDEXER_FUNC1( addUnion  , UnionDecl *     );
     242                INDEXER_FUNC1( addTrait  , TraitDecl *     );
     243                INDEXER_FUNC2( addWith   , std::list< Expression * > &, Node * );
     244
     245                // A few extra functions have more complicated behaviour, they are hand written
     246                // template<typename pass_t>
     247                // static inline auto addStructFwd( pass_t & pass, int, ast::StructDecl * decl ) -> decltype( pass.indexer.addStruct( decl ), void() ) {
     248                //      ast::StructDecl * fwd = new ast::StructDecl( decl->location, decl->name );
     249                //      fwd->parameters = decl->parameters;
     250                //      pass.indexer.addStruct( fwd );
     251                // }
     252
     253                // template<typename pass_t>
     254                // static inline void addStructFwd( pass_t &, long, ast::StructDecl * ) {}
     255
     256                // template<typename pass_t>
     257                // static inline auto addUnionFwd( pass_t & pass, int, ast::UnionDecl * decl ) -> decltype( pass.indexer.addUnion( decl ), void() ) {
     258                //      UnionDecl * fwd = new UnionDecl( decl->name );
     259                //      fwd->parameters = decl->parameters;
     260                //      pass.indexer.addUnion( fwd );
     261                // }
     262
     263                // template<typename pass_t>
     264                // static inline void addUnionFwd( pass_t &, long, ast::UnionDecl * ) {}
     265
     266                // template<typename pass_t>
     267                // static inline auto addStruct( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addStruct( str ), void() ) {
     268                //      if ( ! pass.indexer.lookupStruct( str ) ) {
     269                //              pass.indexer.addStruct( str );
     270                //      }
     271                // }
     272
     273                // template<typename pass_t>
     274                // static inline void addStruct( pass_t &, long, const std::string & ) {}
     275
     276                // template<typename pass_t>
     277                // static inline auto addUnion( pass_t & pass, int, const std::string & str ) -> decltype( pass.indexer.addUnion( str ), void() ) {
     278                //      if ( ! pass.indexer.lookupUnion( str ) ) {
     279                //              pass.indexer.addUnion( str );
     280                //      }
     281                // }
     282
     283                // template<typename pass_t>
     284                // static inline void addUnion( pass_t &, long, const std::string & ) {}
     285
     286                #undef INDEXER_FUNC1
     287                #undef INDEXER_FUNC2
    273288        };
    274289};
     290};
  • src/AST/Stmt.hpp

    r0727d97 r336d0b3  
    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
     96inline void increment( const class Stmt * node, Node::ref_type ref ) { node->increment( ref ); }
     97inline void decrement( const class Stmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     98inline void increment( const class CompoundStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     99inline void decrement( const class CompoundStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     100inline void increment( const class ExprStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     101inline void decrement( const class ExprStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     102inline void increment( const class AsmStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     103inline void decrement( const class AsmStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     104inline void increment( const class DirectiveStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     105inline void decrement( const class DirectiveStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     106inline void increment( const class IfStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     107inline void decrement( const class IfStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     108inline void increment( const class WhileStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     109inline void decrement( const class WhileStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     110inline void increment( const class ForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     111inline void decrement( const class ForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     112inline void increment( const class SwitchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     113inline void decrement( const class SwitchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     114inline void increment( const class CaseStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     115inline void decrement( const class CaseStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     116inline void increment( const class BranchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     117inline void decrement( const class BranchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     118inline void increment( const class ReturnStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     119inline void decrement( const class ReturnStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     120inline void increment( const class ThrowStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     121inline void decrement( const class ThrowStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     122inline void increment( const class TryStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     123inline void decrement( const class TryStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     124inline void increment( const class CatchStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     125inline void decrement( const class CatchStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     126inline void increment( const class FinallyStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     127inline void decrement( const class FinallyStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     128inline void increment( const class WaitForStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     129inline void decrement( const class WaitForStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     130inline void increment( const class WithStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     131inline void decrement( const class WithStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     132inline void increment( const class DeclStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     133inline void decrement( const class DeclStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     134inline void increment( const class NullStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     135inline void decrement( const class NullStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     136inline void increment( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->increment( ref ); }
     137inline void decrement( const class ImplicitCtorDtorStmt * node, Node::ref_type ref ) { node->decrement( ref ); }
     138
    91139}
    92140
  • src/AST/StorageClasses.hpp

    r0727d97 r336d0b3  
    3333
    3434        /// Bitflag type for storage classes
    35         union Classes {
    36                 unsigned int val;
    37                 struct {
    38                         bool is_extern      : 1;
    39                         bool is_static      : 1;
    40                         bool is_auto        : 1;
    41                         bool is_register    : 1;
    42                         bool is_threadlocal : 1;
     35        struct class_flags {
     36                union {
     37                        unsigned int val;
     38                        struct {
     39                                bool is_extern      : 1;
     40                                bool is_static      : 1;
     41                                bool is_auto        : 1;
     42                                bool is_register    : 1;
     43                                bool is_threadlocal : 1;
     44                        };
     45
     46                        // MakeBitfieldPrint( NumClasses )
    4347                };
    4448
    45                 MakeBitfield( Classes )
    46                 MakeBitfieldPrint( NumClasses )
     49                constexpr class_flags( unsigned int val ) : val(val) {}
    4750        };
    4851
     52        using Classes = bitfield<class_flags>;
    4953}
    5054}
  • src/AST/Type.hpp

    r0727d97 r336d0b3  
    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
     33inline void increment( const class Type * node, Node::ref_type ref ) { node->increment( ref ); }
     34inline void decrement( const class Type * node, Node::ref_type ref ) { node->decrement( ref ); }
     35inline void increment( const class VoidType * node, Node::ref_type ref ) { node->increment( ref ); }
     36inline void decrement( const class VoidType * node, Node::ref_type ref ) { node->decrement( ref ); }
     37inline void increment( const class BasicType * node, Node::ref_type ref ) { node->increment( ref ); }
     38inline void decrement( const class BasicType * node, Node::ref_type ref ) { node->decrement( ref ); }
     39inline void increment( const class PointerType * node, Node::ref_type ref ) { node->increment( ref ); }
     40inline void decrement( const class PointerType * node, Node::ref_type ref ) { node->decrement( ref ); }
     41inline void increment( const class ArrayType * node, Node::ref_type ref ) { node->increment( ref ); }
     42inline void decrement( const class ArrayType * node, Node::ref_type ref ) { node->decrement( ref ); }
     43inline void increment( const class ReferenceType * node, Node::ref_type ref ) { node->increment( ref ); }
     44inline void decrement( const class ReferenceType * node, Node::ref_type ref ) { node->decrement( ref ); }
     45inline void increment( const class QualifiedType * node, Node::ref_type ref ) { node->increment( ref ); }
     46inline void decrement( const class QualifiedType * node, Node::ref_type ref ) { node->decrement( ref ); }
     47inline void increment( const class FunctionType * node, Node::ref_type ref ) { node->increment( ref ); }
     48inline void decrement( const class FunctionType * node, Node::ref_type ref ) { node->decrement( ref ); }
     49inline void increment( const class ReferenceToType * node, Node::ref_type ref ) { node->increment( ref ); }
     50inline void decrement( const class ReferenceToType * node, Node::ref_type ref ) { node->decrement( ref ); }
     51inline void increment( const class StructInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     52inline void decrement( const class StructInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     53inline void increment( const class UnionInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     54inline void decrement( const class UnionInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     55inline void increment( const class EnumInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     56inline void decrement( const class EnumInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     57inline void increment( const class TraitInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     58inline void decrement( const class TraitInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     59inline void increment( const class TypeInstType * node, Node::ref_type ref ) { node->increment( ref ); }
     60inline void decrement( const class TypeInstType * node, Node::ref_type ref ) { node->decrement( ref ); }
     61inline void increment( const class TupleType * node, Node::ref_type ref ) { node->increment( ref ); }
     62inline void decrement( const class TupleType * node, Node::ref_type ref ) { node->decrement( ref ); }
     63inline void increment( const class TypeofType * node, Node::ref_type ref ) { node->increment( ref ); }
     64inline void decrement( const class TypeofType * node, Node::ref_type ref ) { node->decrement( ref ); }
     65inline void increment( const class AttrType * node, Node::ref_type ref ) { node->increment( ref ); }
     66inline void decrement( const class AttrType * node, Node::ref_type ref ) { node->decrement( ref ); }
     67inline void increment( const class VarArgsType * node, Node::ref_type ref ) { node->increment( ref ); }
     68inline void decrement( const class VarArgsType * node, Node::ref_type ref ) { node->decrement( ref ); }
     69inline void increment( const class ZeroType * node, Node::ref_type ref ) { node->increment( ref ); }
     70inline void decrement( const class ZeroType * node, Node::ref_type ref ) { node->decrement( ref ); }
     71inline void increment( const class OneType * node, Node::ref_type ref ) { node->increment( ref ); }
     72inline void decrement( const class OneType * node, Node::ref_type ref ) { node->decrement( ref ); }
     73inline void increment( const class GlobalScopeType * node, Node::ref_type ref ) { node->increment( ref ); }
     74inline void decrement( const class GlobalScopeType * node, Node::ref_type ref ) { node->decrement( ref ); }
     75
    2676}
    2777
  • src/Common/PassVisitor.impl.h

    r0727d97 r336d0b3  
    168168template< typename Container, typename pass_type >
    169169inline void maybeMutate_impl( Container & container, PassVisitor< pass_type > & mutator ) {
     170
    170171        if ( ! mutator.get_visit_children() ) return;
    171172        SemanticErrorException errors;
     
    217218                try {
    218219                        func( *i );
     220                        assert( *i );
    219221                        assert(( empty( beforeStmts ) && empty( afterStmts ))
    220222                            || ( empty( beforeDecls ) && empty( afterDecls )) );
  • src/Common/PassVisitor.proto.h

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

    r0727d97 r336d0b3  
    7171        static Declaration *declFromId( UniqueId id );
    7272
    73   private:
     73        UniqueId uniqueId;
    7474        Type::StorageClasses storageClasses;
    75         UniqueId uniqueId;
     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.