Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/InitTweak.cc

    r3351cc0 rc5f3c68  
    55#include <memory>                  // for __shared_ptr
    66
     7#include "Common/PassVisitor.h"
    78#include "Common/SemanticError.h"  // for SemanticError
    89#include "Common/UniqueName.h"     // for UniqueName
     
    1213#include "Parser/LinkageSpec.h"    // for Spec, isBuiltin, Intrinsic
    1314#include "ResolvExpr/typeops.h"    // for typesCompatibleIgnoreQualifiers
     15#include "SymTab/Autogen.h"
    1416#include "SymTab/Indexer.h"        // for Indexer
    1517#include "SynTree/Attribute.h"     // for Attribute
     
    1820#include "SynTree/Expression.h"    // for Expression, UntypedExpr, Applicati...
    1921#include "SynTree/Initializer.h"   // for Initializer, ListInit, Designation
    20 #include "SynTree/Label.h"         // for Label, noLabels
     22#include "SynTree/Label.h"         // for Label
    2123#include "SynTree/Statement.h"     // for CompoundStmt, ExprStmt, BranchStmt
    2224#include "SynTree/Type.h"          // for FunctionType, ArrayType, PointerType
     
    2830namespace InitTweak {
    2931        namespace {
    30                 class HasDesignations : public Visitor {
    31                 public:
     32                struct HasDesignations : public WithShortCircuiting {
    3233                        bool hasDesignations = false;
    33                         virtual void visit( Designation * des ) {
    34                                 if ( ! des->get_designators().empty() ) hasDesignations = true;
    35                                 else Visitor::visit( des );
     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                                }
    3647                        }
    3748                };
    3849
    39                 class InitDepthChecker : public Visitor {
    40                 public:
     50                struct InitDepthChecker : public WithGuards {
    4151                        bool depthOkay = true;
    4252                        Type * type;
     
    5060                                maxDepth++;
    5161                        }
    52                         virtual void visit( ListInit * listInit ) {
     62                        void previsit( ListInit * ) {
    5363                                curDepth++;
     64                                GuardAction( [this]() { curDepth--; } );
    5465                                if ( curDepth > maxDepth ) depthOkay = false;
    55                                 Visitor::visit( listInit );
    56                                 curDepth--;
    5766                        }
    5867                };
    5968
    60                 class InitFlattener : public Visitor {
    61                         public:
    62                         virtual void visit( SingleInit * singleInit );
    63                         virtual void visit( ListInit * listInit );
     69                struct InitFlattener : public WithShortCircuiting {
     70                        void previsit( SingleInit * singleInit ) {
     71                                visit_children = false;
     72                                argList.push_back( singleInit->value->clone() );
     73                        }
    6474                        std::list< Expression * > argList;
    6575                };
    6676
    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                 }
    7877        }
    7978
    8079        std::list< Expression * > makeInitList( Initializer * init ) {
    81                 InitFlattener flattener;
     80                PassVisitor<InitFlattener> flattener;
    8281                maybeAccept( init, flattener );
    83                 return flattener.argList;
     82                return flattener.pass.argList;
    8483        }
    8584
    8685        bool isDesignated( Initializer * init ) {
    87                 HasDesignations finder;
     86                PassVisitor<HasDesignations> finder;
    8887                maybeAccept( init, finder );
    89                 return finder.hasDesignations;
     88                return finder.pass.hasDesignations;
    9089        }
    9190
    9291        bool checkInitDepth( ObjectDecl * objDecl ) {
    93                 InitDepthChecker checker( objDecl->get_type() );
    94                 maybeAccept( objDecl->get_init(), checker );
    95                 return checker.depthOkay;
     92                PassVisitor<InitDepthChecker> checker( objDecl->type );
     93                maybeAccept( objDecl->init, checker );
     94                return checker.pass.depthOkay;
    9695        }
    9796
     
    194193                        callExpr->get_args().splice( callExpr->get_args().end(), args );
    195194
    196                         *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, callExpr ), nullptr );
     195                        *out++ = new IfStmt( cond, new ExprStmt( callExpr ), nullptr );
    197196
    198197                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
    199198                        increment->get_args().push_back( index->clone() );
    200                         *out++ = new ExprStmt( noLabels, increment );
     199                        *out++ = new ExprStmt( increment );
    201200                }
    202201
     
    243242                                        std::list< Statement * > stmts;
    244243                                        build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
    245                                         stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) );
    246                                         CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts );
     244                                        stmts.push_back( new BranchStmt( switchLabel, BranchStmt::Break ) );
     245                                        CaseStmt * caseStmt = new CaseStmt( condition, stmts );
    247246                                        branches.push_back( caseStmt );
    248247                                }
    249                                 *out++ = new SwitchStmt( noLabels, index->clone(), branches );
    250                                 *out++ = new NullStmt( std::list<Label>{ switchLabel } );
     248                                *out++ = new SwitchStmt( index->clone(), branches );
     249                                *out++ = new NullStmt( { switchLabel } );
    251250                        }
    252251                }
     
    261260        Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    262261                if ( ! init ) return nullptr;
    263                 CompoundStmt * block = new CompoundStmt( noLabels );
     262                CompoundStmt * block = new CompoundStmt();
    264263                build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
    265264                if ( block->get_kids().empty() ) {
     
    308307        }
    309308
    310         class CallFinder : public Visitor {
    311         public:
    312                 typedef Visitor Parent;
     309        struct CallFinder {
    313310                CallFinder( const std::list< std::string > & names ) : names( names ) {}
    314311
    315                 virtual void visit( ApplicationExpr * appExpr ) {
     312                void postvisit( ApplicationExpr * appExpr ) {
    316313                        handleCallExpr( appExpr );
    317314                }
    318315
    319                 virtual void visit( UntypedExpr * untypedExpr ) {
     316                void postvisit( UntypedExpr * untypedExpr ) {
    320317                        handleCallExpr( untypedExpr );
    321318                }
     
    327324                template< typename CallExpr >
    328325                void handleCallExpr( CallExpr * expr ) {
    329                         Parent::visit( expr );
    330326                        std::string fname = getFunctionName( expr );
    331327                        if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
     
    336332
    337333        void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
    338                 static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } );
    339                 finder.matches = &matches;
     334                static PassVisitor<CallFinder> finder( std::list< std::string >{ "?{}", "^?{}" } );
     335                finder.pass.matches = &matches;
    340336                maybeAccept( stmt, finder );
    341337        }
     
    524520        }
    525521
    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 ) {
     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
    537548                        // address of a variable or member expression is constexpr
    538549                        Expression * arg = addressExpr->get_arg();
    539550                        if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false;
    540551                }
    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;
     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;
    563567        };
    564568
    565569        bool isConstExpr( Expression * expr ) {
    566570                if ( expr ) {
    567                         ConstExprChecker checker;
     571                        PassVisitor<ConstExprChecker> checker;
    568572                        expr->accept( checker );
    569                         return checker.isConstExpr;
     573                        return checker.pass.isConstExpr;
    570574                }
    571575                return true;
     
    574578        bool isConstExpr( Initializer * init ) {
    575579                if ( init ) {
    576                         ConstExprChecker checker;
     580                        PassVisitor<ConstExprChecker> checker;
    577581                        init->accept( checker );
    578                         return checker.isConstExpr;
     582                        return checker.pass.isConstExpr;
    579583                } // if
    580584                // for all intents and purposes, no initializer means const expr
Note: See TracChangeset for help on using the changeset viewer.