Changes in src/InitTweak/InitTweak.cc [20eacb7:c5f3c68]
- File:
-
- 1 edited
-
src/InitTweak/InitTweak.cc (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/InitTweak.cc
r20eacb7 rc5f3c68 5 5 #include <memory> // for __shared_ptr 6 6 7 #include "Common/PassVisitor.h" 7 8 #include "Common/SemanticError.h" // for SemanticError 8 9 #include "Common/UniqueName.h" // for UniqueName … … 12 13 #include "Parser/LinkageSpec.h" // for Spec, isBuiltin, Intrinsic 13 14 #include "ResolvExpr/typeops.h" // for typesCompatibleIgnoreQualifiers 15 #include "SymTab/Autogen.h" 14 16 #include "SymTab/Indexer.h" // for Indexer 15 17 #include "SynTree/Attribute.h" // for Attribute … … 18 20 #include "SynTree/Expression.h" // for Expression, UntypedExpr, Applicati... 19 21 #include "SynTree/Initializer.h" // for Initializer, ListInit, Designation 20 #include "SynTree/Label.h" // for Label , noLabels22 #include "SynTree/Label.h" // for Label 21 23 #include "SynTree/Statement.h" // for CompoundStmt, ExprStmt, BranchStmt 22 24 #include "SynTree/Type.h" // for FunctionType, ArrayType, PointerType … … 28 30 namespace InitTweak { 29 31 namespace { 30 class HasDesignations : public Visitor { 31 public: 32 struct HasDesignations : public WithShortCircuiting { 32 33 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 } 36 47 } 37 48 }; 38 49 39 class InitDepthChecker : public Visitor { 40 public: 50 struct InitDepthChecker : public WithGuards { 41 51 bool depthOkay = true; 42 52 Type * type; … … 50 60 maxDepth++; 51 61 } 52 v irtual void visit( ListInit * listInit) {62 void previsit( ListInit * ) { 53 63 curDepth++; 64 GuardAction( [this]() { curDepth--; } ); 54 65 if ( curDepth > maxDepth ) depthOkay = false; 55 Visitor::visit( listInit );56 curDepth--;57 66 } 58 67 }; 59 68 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 } 64 74 std::list< Expression * > argList; 65 75 }; 66 76 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 inits73 std::list<Initializer*>::iterator it = listInit->begin();74 for ( ; it != listInit->end(); ++it ) {75 (*it)->accept( *this );76 }77 }78 77 } 79 78 80 79 std::list< Expression * > makeInitList( Initializer * init ) { 81 InitFlattenerflattener;80 PassVisitor<InitFlattener> flattener; 82 81 maybeAccept( init, flattener ); 83 return flattener. argList;82 return flattener.pass.argList; 84 83 } 85 84 86 85 bool isDesignated( Initializer * init ) { 87 HasDesignationsfinder;86 PassVisitor<HasDesignations> finder; 88 87 maybeAccept( init, finder ); 89 return finder. hasDesignations;88 return finder.pass.hasDesignations; 90 89 } 91 90 92 91 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; 96 95 } 97 96 98 97 class InitExpander::ExpanderImpl { 99 98 public: 99 virtual ~ExpanderImpl() = default; 100 100 virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0; 101 101 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0; … … 105 105 public: 106 106 InitImpl( Initializer * init ) : init( init ) {} 107 virtual ~InitImpl() = default; 107 108 108 109 virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) { … … 121 122 public: 122 123 ExprImpl( Expression * expr ) : arg( expr ) {} 123 124 ~ExprImpl() { delete arg; } 124 virtual ~ExprImpl() { delete arg; } 125 125 126 126 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { … … 193 193 callExpr->get_args().splice( callExpr->get_args().end(), args ); 194 194 195 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels,callExpr ), nullptr );195 *out++ = new IfStmt( cond, new ExprStmt( callExpr ), nullptr ); 196 196 197 197 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); 198 198 increment->get_args().push_back( index->clone() ); 199 *out++ = new ExprStmt( noLabels,increment );199 *out++ = new ExprStmt( increment ); 200 200 } 201 201 … … 242 242 std::list< Statement * > stmts; 243 243 build( callExpr, idx, idxEnd, init, back_inserter( stmts ) ); 244 stmts.push_back( new BranchStmt( noLabels,switchLabel, BranchStmt::Break ) );245 CaseStmt * caseStmt = new CaseStmt( noLabels,condition, stmts );244 stmts.push_back( new BranchStmt( switchLabel, BranchStmt::Break ) ); 245 CaseStmt * caseStmt = new CaseStmt( condition, stmts ); 246 246 branches.push_back( caseStmt ); 247 247 } 248 *out++ = new SwitchStmt( noLabels,index->clone(), branches );249 *out++ = new NullStmt( std::list<Label>{ switchLabel } );248 *out++ = new SwitchStmt( index->clone(), branches ); 249 *out++ = new NullStmt( { switchLabel } ); 250 250 } 251 251 } … … 260 260 Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 261 261 if ( ! init ) return nullptr; 262 CompoundStmt * block = new CompoundStmt( noLabels);262 CompoundStmt * block = new CompoundStmt(); 263 263 build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) ); 264 264 if ( block->get_kids().empty() ) { … … 307 307 } 308 308 309 class CallFinder : public Visitor { 310 public: 311 typedef Visitor Parent; 309 struct CallFinder { 312 310 CallFinder( const std::list< std::string > & names ) : names( names ) {} 313 311 314 v irtual voidvisit( ApplicationExpr * appExpr ) {312 void postvisit( ApplicationExpr * appExpr ) { 315 313 handleCallExpr( appExpr ); 316 314 } 317 315 318 v irtual voidvisit( UntypedExpr * untypedExpr ) {316 void postvisit( UntypedExpr * untypedExpr ) { 319 317 handleCallExpr( untypedExpr ); 320 318 } … … 326 324 template< typename CallExpr > 327 325 void handleCallExpr( CallExpr * expr ) { 328 Parent::visit( expr );329 326 std::string fname = getFunctionName( expr ); 330 327 if ( std::find( names.begin(), names.end(), fname ) != names.end() ) { … … 335 332 336 333 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) { 337 static CallFinderfinder( std::list< std::string >{ "?{}", "^?{}" } );338 finder. matches = &matches;334 static PassVisitor<CallFinder> finder( std::list< std::string >{ "?{}", "^?{}" } ); 335 finder.pass.matches = &matches; 339 336 maybeAccept( stmt, finder ); 340 337 } … … 343 340 std::list< Expression * > matches; 344 341 collectCtorDtorCalls( stmt, matches ); 345 assert f( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str());342 assert( matches.size() <= 1 ); 346 343 return matches.size() == 1 ? matches.front() : nullptr; 347 344 } … … 523 520 } 524 521 525 class ConstExprChecker : public Visitor { 526 public: 527 ConstExprChecker() : isConstExpr( true ) {} 528 529 using Visitor::visit; 530 531 virtual void visit( ApplicationExpr * ) { isConstExpr = false; } 532 virtual void visit( UntypedExpr * ) { isConstExpr = false; } 533 virtual void visit( NameExpr * ) { isConstExpr = false; } 534 // virtual void visit( CastExpr *castExpr ) { isConstExpr = false; } 535 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 536 548 // address of a variable or member expression is constexpr 537 549 Expression * arg = addressExpr->get_arg(); 538 550 if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false; 539 551 } 540 virtual void visit( UntypedMemberExpr * ) { isConstExpr = false; } 541 virtual void visit( MemberExpr * ) { isConstExpr = false; } 542 virtual void visit( VariableExpr * ) { isConstExpr = false; } 543 // these might be okay? 544 // virtual void visit( SizeofExpr *sizeofExpr ); 545 // virtual void visit( AlignofExpr *alignofExpr ); 546 // virtual void visit( UntypedOffsetofExpr *offsetofExpr ); 547 // virtual void visit( OffsetofExpr *offsetofExpr ); 548 // virtual void visit( OffsetPackExpr *offsetPackExpr ); 549 // virtual void visit( AttrExpr *attrExpr ); 550 // virtual void visit( CommaExpr *commaExpr ); 551 // virtual void visit( LogicalExpr *logicalExpr ); 552 // virtual void visit( ConditionalExpr *conditionalExpr ); 553 virtual void visit( TypeExpr * ) { isConstExpr = false; } 554 virtual void visit( AsmExpr * ) { isConstExpr = false; } 555 virtual void visit( UntypedValofExpr * ) { isConstExpr = false; } 556 virtual void visit( CompoundLiteralExpr * ) { isConstExpr = false; } 557 virtual void visit( UntypedTupleExpr * ) { isConstExpr = false; } 558 virtual void visit( TupleExpr * ) { isConstExpr = false; } 559 virtual void visit( TupleAssignExpr * ) { isConstExpr = false; } 560 561 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; 562 567 }; 563 568 564 569 bool isConstExpr( Expression * expr ) { 565 570 if ( expr ) { 566 ConstExprCheckerchecker;571 PassVisitor<ConstExprChecker> checker; 567 572 expr->accept( checker ); 568 return checker. isConstExpr;573 return checker.pass.isConstExpr; 569 574 } 570 575 return true; … … 573 578 bool isConstExpr( Initializer * init ) { 574 579 if ( init ) { 575 ConstExprCheckerchecker;580 PassVisitor<ConstExprChecker> checker; 576 581 init->accept( checker ); 577 return checker. isConstExpr;582 return checker.pass.isConstExpr; 578 583 } // if 579 584 // for all intents and purposes, no initializer means const expr
Note:
See TracChangeset
for help on using the changeset viewer.