Changes in src/InitTweak/InitTweak.cc [c5f3c68:20eacb7]
- File:
-
- 1 edited
-
src/InitTweak/InitTweak.cc (modified) (16 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/InitTweak.cc
rc5f3c68 r20eacb7 5 5 #include <memory> // for __shared_ptr 6 6 7 #include "Common/PassVisitor.h"8 7 #include "Common/SemanticError.h" // for SemanticError 9 8 #include "Common/UniqueName.h" // for UniqueName … … 13 12 #include "Parser/LinkageSpec.h" // for Spec, isBuiltin, Intrinsic 14 13 #include "ResolvExpr/typeops.h" // for typesCompatibleIgnoreQualifiers 15 #include "SymTab/Autogen.h"16 14 #include "SymTab/Indexer.h" // for Indexer 17 15 #include "SynTree/Attribute.h" // for Attribute … … 20 18 #include "SynTree/Expression.h" // for Expression, UntypedExpr, Applicati... 21 19 #include "SynTree/Initializer.h" // for Initializer, ListInit, Designation 22 #include "SynTree/Label.h" // for Label 20 #include "SynTree/Label.h" // for Label, noLabels 23 21 #include "SynTree/Statement.h" // for CompoundStmt, ExprStmt, BranchStmt 24 22 #include "SynTree/Type.h" // for FunctionType, ArrayType, PointerType … … 30 28 namespace InitTweak { 31 29 namespace { 32 struct HasDesignations : public WithShortCircuiting { 30 class HasDesignations : public Visitor { 31 public: 33 32 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 ); 47 36 } 48 37 }; 49 38 50 struct InitDepthChecker : public WithGuards { 39 class InitDepthChecker : public Visitor { 40 public: 51 41 bool depthOkay = true; 52 42 Type * type; … … 60 50 maxDepth++; 61 51 } 62 v oid previsit( ListInit *) {52 virtual void visit( ListInit * listInit ) { 63 53 curDepth++; 64 GuardAction( [this]() { curDepth--; } );65 54 if ( curDepth > maxDepth ) depthOkay = false; 55 Visitor::visit( listInit ); 56 curDepth--; 66 57 } 67 58 }; 68 59 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 ); 74 64 std::list< Expression * > argList; 75 65 }; 76 66 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 } 77 78 } 78 79 79 80 std::list< Expression * > makeInitList( Initializer * init ) { 80 PassVisitor<InitFlattener>flattener;81 InitFlattener flattener; 81 82 maybeAccept( init, flattener ); 82 return flattener. pass.argList;83 return flattener.argList; 83 84 } 84 85 85 86 bool isDesignated( Initializer * init ) { 86 PassVisitor<HasDesignations>finder;87 HasDesignations finder; 87 88 maybeAccept( init, finder ); 88 return finder. pass.hasDesignations;89 return finder.hasDesignations; 89 90 } 90 91 91 92 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; 95 96 } 96 97 97 98 class InitExpander::ExpanderImpl { 98 99 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;108 107 109 108 virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) { … … 122 121 public: 123 122 ExprImpl( Expression * expr ) : arg( expr ) {} 124 virtual ~ExprImpl() { delete arg; } 123 124 ~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( cond, new ExprStmt(callExpr ), nullptr );195 *out++ = new IfStmt( noLabels, cond, new ExprStmt( noLabels, 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( increment );199 *out++ = new ExprStmt( noLabels, 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( switchLabel, BranchStmt::Break ) );245 CaseStmt * caseStmt = new CaseStmt( condition, stmts );244 stmts.push_back( new BranchStmt( noLabels, switchLabel, BranchStmt::Break ) ); 245 CaseStmt * caseStmt = new CaseStmt( noLabels, condition, stmts ); 246 246 branches.push_back( caseStmt ); 247 247 } 248 *out++ = new SwitchStmt( index->clone(), branches );249 *out++ = new NullStmt( { switchLabel } );248 *out++ = new SwitchStmt( noLabels, index->clone(), branches ); 249 *out++ = new NullStmt( std::list<Label>{ 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( );262 CompoundStmt * block = new CompoundStmt( noLabels ); 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 struct CallFinder { 309 class CallFinder : public Visitor { 310 public: 311 typedef Visitor Parent; 310 312 CallFinder( const std::list< std::string > & names ) : names( names ) {} 311 313 312 v oid postvisit( ApplicationExpr * appExpr ) {314 virtual void visit( ApplicationExpr * appExpr ) { 313 315 handleCallExpr( appExpr ); 314 316 } 315 317 316 v oid postvisit( UntypedExpr * untypedExpr ) {318 virtual void visit( UntypedExpr * untypedExpr ) { 317 319 handleCallExpr( untypedExpr ); 318 320 } … … 324 326 template< typename CallExpr > 325 327 void handleCallExpr( CallExpr * expr ) { 328 Parent::visit( expr ); 326 329 std::string fname = getFunctionName( expr ); 327 330 if ( std::find( names.begin(), names.end(), fname ) != names.end() ) { … … 332 335 333 336 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) { 334 static PassVisitor<CallFinder>finder( std::list< std::string >{ "?{}", "^?{}" } );335 finder. pass.matches = &matches;337 static CallFinder finder( std::list< std::string >{ "?{}", "^?{}" } ); 338 finder.matches = &matches; 336 339 maybeAccept( stmt, finder ); 337 340 } … … 340 343 std::list< Expression * > matches; 341 344 collectCtorDtorCalls( stmt, matches ); 342 assert ( matches.size() <= 1);345 assertf( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str() ); 343 346 return matches.size() == 1 ? matches.front() : nullptr; 344 347 } … … 520 523 } 521 524 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 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 ) { 548 536 // address of a variable or member expression is constexpr 549 537 Expression * arg = addressExpr->get_arg(); 550 538 if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false; 551 539 } 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; 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; 567 562 }; 568 563 569 564 bool isConstExpr( Expression * expr ) { 570 565 if ( expr ) { 571 PassVisitor<ConstExprChecker>checker;566 ConstExprChecker checker; 572 567 expr->accept( checker ); 573 return checker. pass.isConstExpr;568 return checker.isConstExpr; 574 569 } 575 570 return true; … … 578 573 bool isConstExpr( Initializer * init ) { 579 574 if ( init ) { 580 PassVisitor<ConstExprChecker>checker;575 ConstExprChecker checker; 581 576 init->accept( checker ); 582 return checker. pass.isConstExpr;577 return checker.isConstExpr; 583 578 } // if 584 579 // for all intents and purposes, no initializer means const expr
Note:
See TracChangeset
for help on using the changeset viewer.