Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/InitTweak.cc

    rc5f3c68 r3351cc0  
    55#include <memory>                  // for __shared_ptr
    66
    7 #include "Common/PassVisitor.h"
    87#include "Common/SemanticError.h"  // for SemanticError
    98#include "Common/UniqueName.h"     // for UniqueName
     
    1312#include "Parser/LinkageSpec.h"    // for Spec, isBuiltin, Intrinsic
    1413#include "ResolvExpr/typeops.h"    // for typesCompatibleIgnoreQualifiers
    15 #include "SymTab/Autogen.h"
    1614#include "SymTab/Indexer.h"        // for Indexer
    1715#include "SynTree/Attribute.h"     // for Attribute
     
    2018#include "SynTree/Expression.h"    // for Expression, UntypedExpr, Applicati...
    2119#include "SynTree/Initializer.h"   // for Initializer, ListInit, Designation
    22 #include "SynTree/Label.h"         // for Label
     20#include "SynTree/Label.h"         // for Label, noLabels
    2321#include "SynTree/Statement.h"     // for CompoundStmt, ExprStmt, BranchStmt
    2422#include "SynTree/Type.h"          // for FunctionType, ArrayType, PointerType
     
    3028namespace InitTweak {
    3129        namespace {
    32                 struct HasDesignations : public WithShortCircuiting {
     30                class HasDesignations : public Visitor {
     31                public:
    3332                        bool hasDesignations = false;
    34 
    35                         void previsit( BaseSyntaxNode * ) {
    36                                 // short circuit if we already know there are designations
    37                                 if ( hasDesignations ) visit_children = false;
    38                         }
    39 
    40                         void previsit( Designation * des ) {
    41                                 // short circuit if we already know there are designations
    42                                 if ( hasDesignations ) visit_children = false;
    43                                 else if ( ! des->get_designators().empty() ) {
    44                                         hasDesignations = true;
    45                                         visit_children = false;
    46                                 }
     33                        virtual void visit( Designation * des ) {
     34                                if ( ! des->get_designators().empty() ) hasDesignations = true;
     35                                else Visitor::visit( des );
    4736                        }
    4837                };
    4938
    50                 struct InitDepthChecker : public WithGuards {
     39                class InitDepthChecker : public Visitor {
     40                public:
    5141                        bool depthOkay = true;
    5242                        Type * type;
     
    6050                                maxDepth++;
    6151                        }
    62                         void previsit( ListInit * ) {
     52                        virtual void visit( ListInit * listInit ) {
    6353                                curDepth++;
    64                                 GuardAction( [this]() { curDepth--; } );
    6554                                if ( curDepth > maxDepth ) depthOkay = false;
     55                                Visitor::visit( listInit );
     56                                curDepth--;
    6657                        }
    6758                };
    6859
    69                 struct InitFlattener : public WithShortCircuiting {
    70                         void previsit( SingleInit * singleInit ) {
    71                                 visit_children = false;
    72                                 argList.push_back( singleInit->value->clone() );
    73                         }
     60                class InitFlattener : public Visitor {
     61                        public:
     62                        virtual void visit( SingleInit * singleInit );
     63                        virtual void visit( ListInit * listInit );
    7464                        std::list< Expression * > argList;
    7565                };
    7666
     67                void InitFlattener::visit( SingleInit * singleInit ) {
     68                        argList.push_back( singleInit->get_value()->clone() );
     69                }
     70
     71                void InitFlattener::visit( ListInit * listInit ) {
     72                        // flatten nested list inits
     73                        std::list<Initializer*>::iterator it = listInit->begin();
     74                        for ( ; it != listInit->end(); ++it ) {
     75                                (*it)->accept( *this );
     76                        }
     77                }
    7778        }
    7879
    7980        std::list< Expression * > makeInitList( Initializer * init ) {
    80                 PassVisitor<InitFlattener> flattener;
     81                InitFlattener flattener;
    8182                maybeAccept( init, flattener );
    82                 return flattener.pass.argList;
     83                return flattener.argList;
    8384        }
    8485
    8586        bool isDesignated( Initializer * init ) {
    86                 PassVisitor<HasDesignations> finder;
     87                HasDesignations finder;
    8788                maybeAccept( init, finder );
    88                 return finder.pass.hasDesignations;
     89                return finder.hasDesignations;
    8990        }
    9091
    9192        bool checkInitDepth( ObjectDecl * objDecl ) {
    92                 PassVisitor<InitDepthChecker> checker( objDecl->type );
    93                 maybeAccept( objDecl->init, checker );
    94                 return checker.pass.depthOkay;
     93                InitDepthChecker checker( objDecl->get_type() );
     94                maybeAccept( objDecl->get_init(), checker );
     95                return checker.depthOkay;
    9596        }
    9697
     
    193194                        callExpr->get_args().splice( callExpr->get_args().end(), args );
    194195
    195                         *out++ = new IfStmt( cond, new ExprStmt( callExpr ), nullptr );
     196                        *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr );
    196197
    197198                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
    198199                        increment->get_args().push_back( index->clone() );
    199                         *out++ = new ExprStmt( increment );
     200                        *out++ = new ExprStmt( noLabels, increment );
    200201                }
    201202
     
    242243                                        std::list< Statement * > stmts;
    243244                                        build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
    244                                         stmts.push_back( new BranchStmt( switchLabel, BranchStmt::Break ) );
    245                                         CaseStmt * caseStmt = new CaseStmt( condition, stmts );
     245                                        stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );
     246                                        CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
    246247                                        branches.push_back( caseStmt );
    247248                                }
    248                                 *out++ = new SwitchStmt( index->clone(), branches );
    249                                 *out++ = new NullStmt( { switchLabel } );
     249                                *out++ = new SwitchStmt( noLabels, index->clone(), branches );
     250                                *out++ = new NullStmt( std::list<Label>{ switchLabel } );
    250251                        }
    251252                }
     
    260261        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    261262                if ( ! init ) return nullptr;
    262                 CompoundStmt * block = new CompoundStmt();
     263                CompoundStmt * block = new CompoundStmt( noLabels );
    263264                build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
    264265                if ( block->get_kids().empty() ) {
     
    307308        }
    308309
    309         struct CallFinder {
     310        class CallFinder : public Visitor {
     311        public:
     312                typedef Visitor Parent;
    310313                CallFinder( const std::list< std::string > & names ) : names( names ) {}
    311314
    312                 void postvisit( ApplicationExpr * appExpr ) {
     315                virtual void visit( ApplicationExpr * appExpr ) {
    313316                        handleCallExpr( appExpr );
    314317                }
    315318
    316                 void postvisit( UntypedExpr * untypedExpr ) {
     319                virtual void visit( UntypedExpr * untypedExpr ) {
    317320                        handleCallExpr( untypedExpr );
    318321                }
     
    324327                template< typename CallExpr >
    325328                void handleCallExpr( CallExpr * expr ) {
     329                        Parent::visit( expr );
    326330                        std::string fname = getFunctionName( expr );
    327331                        if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
     
    332336
    333337        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
    334                 static PassVisitor<CallFinder> finder( std::list< std::string >{ "?{}", "^?{}" } );
    335                 finder.pass.matches = &matches;
     338                static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
     339                finder.matches = &matches;
    336340                maybeAccept( stmt, finder );
    337341        }
     
    520524        }
    521525
    522         ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src ) {
    523                 static FunctionDecl * assign = nullptr;
    524                 if ( ! assign ) {
    525                         // temporary? Generate a fake assignment operator to represent bitwise assignments.
    526                         // This operator could easily exist as a real function, but it's tricky because nothing should resolve to this function.
    527                         TypeDecl * td = new TypeDecl( "T", noStorageClasses, nullptr, TypeDecl::Dtype, true );
    528                         assign = new FunctionDecl( "?=?", noStorageClasses, LinkageSpec::Intrinsic, SymTab::genAssignType( new TypeInstType( noQualifiers, td->name, td ) ), nullptr );
    529                 }
    530                 if ( dynamic_cast< ReferenceType * >( dst->result ) ) {
    531                         dst = new AddressExpr( dst );
    532                 } else {
    533                         dst = new CastExpr( dst, new ReferenceType( noQualifiers, dst->result->clone() ) );
    534                 }
    535                 if ( dynamic_cast< ReferenceType * >( src->result ) ) {
    536                         src = new CastExpr( src, new ReferenceType( noQualifiers, src->result->stripReferences()->clone() ) );
    537                 }
    538                 return new ApplicationExpr( VariableExpr::functionPointer( assign ), { dst, src } );
    539         }
    540 
    541         struct ConstExprChecker : public WithShortCircuiting {
    542                 // most expressions are not const expr
    543                 void previsit( Expression * ) { isConstExpr = false; visit_children = false; }
    544 
    545                 void previsit( AddressExpr *addressExpr ) {
    546                         visit_children = false;
    547 
     526        class ConstExprChecker : public Visitor {
     527        public:
     528                ConstExprChecker() : isConstExpr( true ) {}
     529
     530                using Visitor::visit;
     531
     532                virtual void visit( ApplicationExpr * ) { isConstExpr = false; }
     533                virtual void visit( UntypedExpr * ) { isConstExpr = false; }
     534                virtual void visit( NameExpr * ) { isConstExpr = false; }
     535                // virtual void visit( CastExpr *castExpr ) { isConstExpr = false; }
     536                virtual void visit( AddressExpr *addressExpr ) {
    548537                        // address of a variable or member expression is constexpr
    549538                        Expression * arg = addressExpr->get_arg();
    550539                        if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false;
    551540                }
    552 
    553                 // these expressions may be const expr, depending on their children
    554                 void previsit( SizeofExpr * ) {}
    555                 void previsit( AlignofExpr * ) {}
    556                 void previsit( UntypedOffsetofExpr * ) {}
    557                 void previsit( OffsetofExpr * ) {}
    558                 void previsit( OffsetPackExpr * ) {}
    559                 void previsit( AttrExpr * ) {}
    560                 void previsit( CommaExpr * ) {}
    561                 void previsit( LogicalExpr * ) {}
    562                 void previsit( ConditionalExpr * ) {}
    563                 void previsit( CastExpr * ) {}
    564                 void previsit( ConstantExpr * ) {}
    565 
    566                 bool isConstExpr = true;
     541                virtual void visit( UntypedMemberExpr * ) { isConstExpr = false; }
     542                virtual void visit( MemberExpr * ) { isConstExpr = false; }
     543                virtual void visit( VariableExpr * ) { isConstExpr = false; }
     544                // these might be okay?
     545                // virtual void visit( SizeofExpr *sizeofExpr );
     546                // virtual void visit( AlignofExpr *alignofExpr );
     547                // virtual void visit( UntypedOffsetofExpr *offsetofExpr );
     548                // virtual void visit( OffsetofExpr *offsetofExpr );
     549                // virtual void visit( OffsetPackExpr *offsetPackExpr );
     550                // virtual void visit( AttrExpr *attrExpr );
     551                // virtual void visit( CommaExpr *commaExpr );
     552                // virtual void visit( LogicalExpr *logicalExpr );
     553                // virtual void visit( ConditionalExpr *conditionalExpr );
     554                virtual void visit( TypeExpr * ) { isConstExpr = false; }
     555                virtual void visit( AsmExpr * ) { isConstExpr = false; }
     556                virtual void visit( UntypedValofExpr * ) { isConstExpr = false; }
     557                virtual void visit( CompoundLiteralExpr * ) { isConstExpr = false; }
     558                virtual void visit( UntypedTupleExpr * ) { isConstExpr = false; }
     559                virtual void visit( TupleExpr * ) { isConstExpr = false; }
     560                virtual void visit( TupleAssignExpr * ) { isConstExpr = false; }
     561
     562                bool isConstExpr;
    567563        };
    568564
    569565        bool isConstExpr( Expression * expr ) {
    570566                if ( expr ) {
    571                         PassVisitor<ConstExprChecker> checker;
     567                        ConstExprChecker checker;
    572568                        expr->accept( checker );
    573                         return checker.pass.isConstExpr;
     569                        return checker.isConstExpr;
    574570                }
    575571                return true;
     
    578574        bool isConstExpr( Initializer * init ) {
    579575                if ( init ) {
    580                         PassVisitor<ConstExprChecker> checker;
     576                        ConstExprChecker checker;
    581577                        init->accept( checker );
    582                         return checker.pass.isConstExpr;
     578                        return checker.isConstExpr;
    583579                } // if
    584580                // for all intents and purposes, no initializer means const expr
Note: See TracChangeset for help on using the changeset viewer.