Changes in / [2b72090:bee7f04]
- Location:
- src
- Files:
-
- 16 added
- 16 deleted
- 22 edited
-
Common/PassVisitor.h (modified) (2 diffs)
-
Common/PassVisitor.impl.h (modified) (2 diffs)
-
ControlStruct/LabelFixer.cc (modified) (1 diff)
-
ControlStruct/MLEMutator.cc (modified) (8 diffs)
-
ControlStruct/MLEMutator.h (modified) (4 diffs)
-
GenPoly/Box.cc (modified) (4 diffs)
-
GenPoly/Lvalue.cc (modified) (7 diffs)
-
GenPoly/ScrubTyVars.cc (modified) (6 diffs)
-
GenPoly/ScrubTyVars.h (modified) (6 diffs)
-
InitTweak/FixInit.cc (modified) (11 diffs)
-
ResolvExpr/CastCost.cc (modified) (4 diffs)
-
ResolvExpr/ConversionCost.cc (modified) (22 diffs)
-
ResolvExpr/ConversionCost.h (modified) (3 diffs)
-
ResolvExpr/Resolver.cc (modified) (5 diffs)
-
SynTree/AggregateDecl.cc (modified) (1 diff)
-
SynTree/Expression.cc (modified) (2 diffs)
-
SynTree/Label.h (modified) (1 diff)
-
SynTree/TypeSubstitution.cc (modified) (3 diffs)
-
SynTree/TypeSubstitution.h (modified) (5 diffs)
-
Tuples/TupleExpansion.cc (modified) (5 diffs)
-
tests/.expect/ctor-autogen-ERR1.txt (deleted)
-
tests/.expect/ctor-autogen.txt (deleted)
-
tests/.expect/dtor-early-exit-ERR1.txt (deleted)
-
tests/.expect/dtor-early-exit-ERR2.txt (deleted)
-
tests/.expect/dtor-early-exit.txt (deleted)
-
tests/.expect/globals.txt (deleted)
-
tests/.expect/init_once.txt (deleted)
-
tests/.expect/memberCtors-ERR1.txt (deleted)
-
tests/.expect/memberCtors.txt (deleted)
-
tests/.expect/multiDimension.txt (deleted)
-
tests/Makefile.am (modified) (3 diffs)
-
tests/Makefile.in (modified) (3 diffs)
-
tests/ctor-autogen.c (deleted)
-
tests/dtor-early-exit.c (deleted)
-
tests/globals.c (deleted)
-
tests/init_once.c (deleted)
-
tests/memberCtors.c (deleted)
-
tests/multiDimension.c (deleted)
-
tests/raii/.expect/ctor-autogen-ERR1.txt (added)
-
tests/raii/.expect/ctor-autogen.txt (added)
-
tests/raii/.expect/dtor-early-exit-ERR1.txt (added)
-
tests/raii/.expect/dtor-early-exit-ERR2.txt (added)
-
tests/raii/.expect/dtor-early-exit.txt (added)
-
tests/raii/.expect/globals.txt (added)
-
tests/raii/.expect/init_once.txt (added)
-
tests/raii/.expect/memberCtors-ERR1.txt (added)
-
tests/raii/.expect/memberCtors.txt (added)
-
tests/raii/ctor-autogen.c (added)
-
tests/raii/dtor-early-exit.c (added)
-
tests/raii/globals.c (added)
-
tests/raii/init_once.c (added)
-
tests/raii/memberCtors.c (added)
-
tests/raii/multiDimension.c (added)
-
tests/raii/multiDimension.txt (added)
Legend:
- Unmodified
- Added
- Removed
-
src/Common/PassVisitor.h
r2b72090 rbee7f04 19 19 #include "SynTree/Expression.h" 20 20 #include "SynTree/Constant.h" 21 #include "SynTree/TypeSubstitution.h" 21 22 class TypeSubstitution; 22 23 23 24 #include "PassVisitor.proto.h" … … 403 404 }; 404 405 406 #include "SynTree/TypeSubstitution.h" 405 407 #include "PassVisitor.impl.h" -
src/Common/PassVisitor.impl.h
r2b72090 rbee7f04 62 62 63 63 template< typename pass_type > 64 staticinline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) {64 inline void acceptAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& visitor ) { 65 65 DeclList_t* beforeDecls = visitor.get_beforeDecls(); 66 66 DeclList_t* afterDecls = visitor.get_afterDecls(); … … 90 90 91 91 template< typename pass_type > 92 staticinline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) {92 inline void mutateAll( std::list< Declaration* > &decls, PassVisitor< pass_type >& mutator ) { 93 93 DeclList_t* beforeDecls = mutator.get_beforeDecls(); 94 94 DeclList_t* afterDecls = mutator.get_afterDecls(); -
src/ControlStruct/LabelFixer.cc
r2b72090 rbee7f04 44 44 45 45 void LabelFixer::postvisit( FunctionDecl * functionDecl ) { 46 MLEMutatormlemut( resolveJumps(), generator );46 PassVisitor<MLEMutator> mlemut( resolveJumps(), generator ); 47 47 functionDecl->acceptMutator( mlemut ); 48 48 } -
src/ControlStruct/MLEMutator.cc
r2b72090 rbee7f04 46 46 void MLEMutator::fixBlock( std::list< Statement * > &kids ) { 47 47 for ( std::list< Statement * >::iterator k = kids.begin(); k != kids.end(); k++ ) { 48 *k = (*k)->acceptMutator(* this);48 *k = (*k)->acceptMutator(*visitor); 49 49 50 50 if ( ! get_breakLabel().empty() ) { … … 57 57 } 58 58 59 CompoundStmt* MLEMutator::mutate( CompoundStmt *cmpndStmt ) { 60 bool labeledBlock = !(cmpndStmt->get_labels().empty()); 59 void MLEMutator::premutate( CompoundStmt *cmpndStmt ) { 60 visit_children = false; 61 bool labeledBlock = !(cmpndStmt->labels.empty()); 61 62 if ( labeledBlock ) { 62 63 Label brkLabel = generator->newLabel("blockBreak", cmpndStmt); … … 65 66 66 67 // a child statement may set the break label - if they do, attach it to the next statement 67 std::list< Statement * > &kids = cmpndStmt-> get_kids();68 std::list< Statement * > &kids = cmpndStmt->kids; 68 69 fixBlock( kids ); 69 70 … … 75 76 enclosingControlStructures.pop_back(); 76 77 } // if 77 78 return cmpndStmt; 79 } 80 81 template< typename LoopClass > 82 Statement *MLEMutator::handleLoopStmt( LoopClass *loopStmt ) { 83 // remember this as the most recent enclosing loop, then mutate the body of the loop -- this will determine 84 // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested 85 // loops 86 Label brkLabel = generator->newLabel("loopBreak", loopStmt); 87 Label contLabel = generator->newLabel("loopContinue", loopStmt); 88 enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) ); 89 loopStmt->set_body ( loopStmt->get_body()->acceptMutator( *this ) ); 90 91 assert( ! enclosingControlStructures.empty() ); 92 Entry &e = enclosingControlStructures.back(); 93 // sanity check that the enclosing loops have been popped correctly 94 assert ( e == loopStmt ); 95 96 // this will take the necessary steps to add definitions of the previous two labels, if they are used. 97 loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) ); 98 enclosingControlStructures.pop_back(); 99 100 return loopStmt; 101 } 102 103 Statement *MLEMutator::mutate( CaseStmt *caseStmt ) { 104 caseStmt->set_condition( maybeMutate( caseStmt->get_condition(), *this ) ); 105 fixBlock( caseStmt->get_statements() ); 106 107 return caseStmt; 108 } 109 110 template< typename IfClass > 111 Statement *MLEMutator::handleIfStmt( IfClass *ifStmt ) { 112 // generate a label for breaking out of a labeled if 113 bool labeledBlock = !(ifStmt->get_labels().empty()); 114 if ( labeledBlock ) { 115 Label brkLabel = generator->newLabel("blockBreak", ifStmt); 116 enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) ); 117 } // if 118 119 Parent::mutate( ifStmt ); 120 121 if ( labeledBlock ) { 122 if ( ! enclosingControlStructures.back().useBreakExit().empty() ) { 123 set_breakLabel( enclosingControlStructures.back().useBreakExit() ); 124 } // if 125 enclosingControlStructures.pop_back(); 126 } // if 127 return ifStmt; 128 } 129 130 template< typename SwitchClass > 131 Statement *MLEMutator::handleSwitchStmt( SwitchClass *switchStmt ) { 132 // generate a label for breaking out of a labeled switch 133 Label brkLabel = generator->newLabel("switchBreak", switchStmt); 134 enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) ); 135 mutateAll( switchStmt->get_statements(), *this ); 136 137 Entry &e = enclosingControlStructures.back(); 138 assert ( e == switchStmt ); 139 140 // only generate break label if labeled break is used 141 if ( e.isBreakUsed() ) { 142 // for the purposes of keeping switch statements uniform (i.e. all statements that are direct children of a 143 // switch should be CastStmts), append the exit label + break to the last case statement; create a default 144 // case if there are no cases 145 std::list< Statement * > &statements = switchStmt->get_statements(); 146 if ( statements.empty() ) { 147 statements.push_back( CaseStmt::makeDefault() ); 148 } // if 149 150 if ( CaseStmt * c = dynamic_cast< CaseStmt * >( statements.back() ) ) { 151 Statement * stmt = new BranchStmt( Label("brkLabel"), BranchStmt::Break ); 152 stmt->labels.push_back( brkLabel ); 153 c->get_statements().push_back( stmt ); 154 } else assert(0); // as of this point, all statements of a switch are still CaseStmts 155 } // if 156 157 assert ( enclosingControlStructures.back() == switchStmt ); 158 enclosingControlStructures.pop_back(); 159 return switchStmt; 160 } 78 } 79 161 80 162 81 void addUnused( Statement * stmt, const Label & originalTarget ) { … … 179 98 180 99 181 Statement *MLEMutator:: mutate( BranchStmt *branchStmt ) throw ( SemanticError ) {182 std::string originalTarget = branchStmt-> get_originalTarget();100 Statement *MLEMutator::postmutate( BranchStmt *branchStmt ) throw ( SemanticError ) { 101 std::string originalTarget = branchStmt->originalTarget; 183 102 184 103 std::list< Entry >::reverse_iterator targetEntry; … … 215 134 // branch error checks, get the appropriate label name and create a goto 216 135 Label exitLabel; 217 switch ( branchStmt-> get_type()) {136 switch ( branchStmt->type ) { 218 137 case BranchStmt::Break: 219 138 assert( targetEntry->useBreakExit() != ""); … … 229 148 230 149 // add unused attribute to label to silence warnings 231 addUnused( targetEntry->get_controlStructure(), branchStmt-> get_originalTarget());150 addUnused( targetEntry->get_controlStructure(), branchStmt->originalTarget ); 232 151 233 152 // transform break/continue statements into goto to simplify later handling of branches … … 260 179 } 261 180 262 Statement *MLEMutator::mutate( WhileStmt *whileStmt ) { 263 return handleLoopStmt( whileStmt ); 264 } 265 266 Statement *MLEMutator::mutate( ForStmt *forStmt ) { 267 return handleLoopStmt( forStmt ); 268 } 269 270 Statement *MLEMutator::mutate( IfStmt *ifStmt ) { 271 return handleIfStmt( ifStmt ); 272 } 273 274 Statement *MLEMutator::mutate( SwitchStmt *switchStmt ) { 275 return handleSwitchStmt( switchStmt ); 181 template< typename LoopClass > 182 void MLEMutator::prehandleLoopStmt( LoopClass * loopStmt ) { 183 // remember this as the most recent enclosing loop, then mutate the body of the loop -- this will determine 184 // whether brkLabel and contLabel are used with branch statements and will recursively do the same to nested 185 // loops 186 Label brkLabel = generator->newLabel("loopBreak", loopStmt); 187 Label contLabel = generator->newLabel("loopContinue", loopStmt); 188 enclosingControlStructures.push_back( Entry( loopStmt, brkLabel, contLabel ) ); 189 } 190 191 template< typename LoopClass > 192 Statement * MLEMutator::posthandleLoopStmt( LoopClass * loopStmt ) { 193 assert( ! enclosingControlStructures.empty() ); 194 Entry &e = enclosingControlStructures.back(); 195 // sanity check that the enclosing loops have been popped correctly 196 assert ( e == loopStmt ); 197 198 // this will take the necessary steps to add definitions of the previous two labels, if they are used. 199 loopStmt->set_body( mutateLoop( loopStmt->get_body(), e ) ); 200 enclosingControlStructures.pop_back(); 201 return loopStmt; 202 } 203 204 void MLEMutator::premutate( WhileStmt * whileStmt ) { 205 return prehandleLoopStmt( whileStmt ); 206 } 207 208 void MLEMutator::premutate( ForStmt * forStmt ) { 209 return prehandleLoopStmt( forStmt ); 210 } 211 212 Statement * MLEMutator::postmutate( WhileStmt * whileStmt ) { 213 return posthandleLoopStmt( whileStmt ); 214 } 215 216 Statement * MLEMutator::postmutate( ForStmt * forStmt ) { 217 return posthandleLoopStmt( forStmt ); 218 } 219 220 void MLEMutator::premutate( IfStmt * ifStmt ) { 221 // generate a label for breaking out of a labeled if 222 bool labeledBlock = !(ifStmt->get_labels().empty()); 223 if ( labeledBlock ) { 224 Label brkLabel = generator->newLabel("blockBreak", ifStmt); 225 enclosingControlStructures.push_back( Entry( ifStmt, brkLabel ) ); 226 } // if 227 } 228 229 Statement * MLEMutator::postmutate( IfStmt * ifStmt ) { 230 bool labeledBlock = !(ifStmt->get_labels().empty()); 231 if ( labeledBlock ) { 232 if ( ! enclosingControlStructures.back().useBreakExit().empty() ) { 233 set_breakLabel( enclosingControlStructures.back().useBreakExit() ); 234 } // if 235 enclosingControlStructures.pop_back(); 236 } // if 237 return ifStmt; 238 } 239 240 void MLEMutator::premutate( CaseStmt *caseStmt ) { 241 visit_children = false; 242 caseStmt->condition = maybeMutate( caseStmt->condition, *visitor ); 243 fixBlock( caseStmt->stmts ); 244 } 245 246 void MLEMutator::premutate( SwitchStmt *switchStmt ) { 247 // generate a label for breaking out of a labeled switch 248 Label brkLabel = generator->newLabel("switchBreak", switchStmt); 249 enclosingControlStructures.push_back( Entry(switchStmt, brkLabel) ); 250 } 251 252 Statement * MLEMutator::postmutate( SwitchStmt * switchStmt ) { 253 Entry &e = enclosingControlStructures.back(); 254 assert ( e == switchStmt ); 255 256 // only generate break label if labeled break is used 257 if ( e.isBreakUsed() ) { 258 // for the purposes of keeping switch statements uniform (i.e. all statements that are direct children of a 259 // switch should be CastStmts), append the exit label + break to the last case statement; create a default 260 // case if there are no cases 261 std::list< Statement * > &statements = switchStmt->statements; 262 if ( statements.empty() ) { 263 statements.push_back( CaseStmt::makeDefault() ); 264 } // if 265 266 if ( CaseStmt * c = dynamic_cast< CaseStmt * >( statements.back() ) ) { 267 Statement * stmt = new BranchStmt( Label("brkLabel"), BranchStmt::Break ); 268 stmt->labels.push_back( e.useBreakExit() ); 269 c->stmts.push_back( stmt ); 270 } else assert(0); // as of this point, all statements of a switch are still CaseStmts 271 } // if 272 273 assert ( enclosingControlStructures.back() == switchStmt ); 274 enclosingControlStructures.pop_back(); 275 return switchStmt; 276 276 } 277 277 } // namespace ControlStruct -
src/ControlStruct/MLEMutator.h
r2b72090 rbee7f04 20 20 #include <string> // for string 21 21 22 #include "Common/PassVisitor.h" 22 23 #include "Common/SemanticError.h" // for SemanticError 23 24 #include "SynTree/Label.h" // for Label … … 26 27 27 28 namespace ControlStruct { 28 class LabelGenerator;29 class LabelGenerator; 29 30 30 class MLEMutator : public Mutator{31 class MLEMutator : public WithVisitorRef<MLEMutator>, public WithShortCircuiting { 31 32 class Entry; 32 33 33 typedef Mutator Parent;34 34 public: 35 35 MLEMutator( std::map<Label, Statement *> *t, LabelGenerator *gen = 0 ) : targetTable( t ), breakLabel(std::string("")), generator( gen ) {} 36 36 ~MLEMutator(); 37 37 38 virtual CompoundStmt *mutate( CompoundStmt *cmpndStmt ) override; 39 virtual Statement *mutate( WhileStmt *whileStmt ) override; 40 virtual Statement *mutate( ForStmt *forStmt ) override; 41 virtual Statement *mutate( BranchStmt *branchStmt ) throw ( SemanticError ) override; 42 virtual Statement *mutate( CaseStmt *caseStmt ) override; 43 virtual Statement *mutate( IfStmt *ifStmt ) override; 44 virtual Statement *mutate( SwitchStmt *switchStmt ) override; 38 void premutate( CompoundStmt *cmpndStmt ); 39 Statement * postmutate( BranchStmt *branchStmt ) throw ( SemanticError ); 40 void premutate( WhileStmt *whileStmt ); 41 Statement * postmutate( WhileStmt *whileStmt ); 42 void premutate( ForStmt *forStmt ); 43 Statement * postmutate( ForStmt *forStmt ); 44 void premutate( CaseStmt *caseStmt ); 45 void premutate( IfStmt *ifStmt ); 46 Statement * postmutate( IfStmt *ifStmt ); 47 void premutate( SwitchStmt *switchStmt ); 48 Statement * postmutate( SwitchStmt *switchStmt ); 45 49 46 50 Statement *mutateLoop( Statement *bodyLoop, Entry &e ); … … 54 58 loop( _loop ), breakExit( _breakExit ), contExit( _contExit ), breakUsed(false), contUsed(false) {} 55 59 56 bool operator==( const Statement *stmt ) { return ( loop == stmt ); }57 bool operator!=( const Statement *stmt ) { return ( loop != stmt ); }60 bool operator==( const Statement *stmt ) { return loop == stmt; } 61 bool operator!=( const Statement *stmt ) { return loop != stmt; } 58 62 59 bool operator==( const Entry &other ) { return ( loop == other.get_controlStructure()); }63 bool operator==( const Entry &other ) { return loop == other.get_controlStructure(); } 60 64 61 65 Statement *get_controlStructure() const { return loop; } … … 78 82 79 83 template< typename LoopClass > 80 Statement *handleLoopStmt( LoopClass *loopStmt );84 void prehandleLoopStmt( LoopClass * loopStmt ); 81 85 82 template< typename IfClass > 83 Statement *handleIfStmt( IfClass *switchStmt ); 84 85 template< typename SwitchClass > 86 Statement *handleSwitchStmt( SwitchClass *switchStmt ); 86 template< typename LoopClass > 87 Statement * posthandleLoopStmt( LoopClass * loopStmt ); 87 88 88 89 void fixBlock( std::list< Statement * > &kids ); -
src/GenPoly/Box.cc
r2b72090 rbee7f04 302 302 Expression *makeOp( const std::string &name, Expression *arg ) { 303 303 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) ); 304 expr-> get_args().push_back( arg );304 expr->args.push_back( arg ); 305 305 return expr; 306 306 } … … 309 309 Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) { 310 310 UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) ); 311 expr-> get_args().push_back( lhs );312 expr-> get_args().push_back( rhs );311 expr->args.push_back( lhs ); 312 expr->args.push_back( rhs ); 313 313 return expr; 314 314 } … … 316 316 /// Returns the dereference of a local pointer variable 317 317 Expression *derefVar( ObjectDecl *var ) { 318 return makeOp( "*?",new VariableExpr( var ) );318 return UntypedExpr::createDeref( new VariableExpr( var ) ); 319 319 } 320 320 … … 831 831 if ( ! isPolyType( arg->get_type() ) ) { 832 832 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 833 deref->get_args().push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) ); 834 deref->set_result( arg->get_type()->clone() ); 833 deref->args.push_back( new CastExpr( new VariableExpr( param ), new PointerType( Type::Qualifiers(), arg->get_type()->clone() ) ) ); 834 deref->result = arg->get_type()->clone(); 835 deref->result->set_lvalue( true ); 835 836 return deref; 836 837 } // if -
src/GenPoly/Lvalue.cc
r2b72090 rbee7f04 47 47 if ( SymTab::dereferenceOperator ) { 48 48 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator ); 49 deref-> set_result( new PointerType( Type::Qualifiers(), deref->get_result() ));50 Type * base = InitTweak::getPointerBase( arg-> get_result());51 assertf( base, "expected pointer type in dereference (type was %s)", toString( arg-> get_result()).c_str() );49 deref->result = new PointerType( Type::Qualifiers(), deref->result ); 50 Type * base = InitTweak::getPointerBase( arg->result ); 51 assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->result ).c_str() ); 52 52 ApplicationExpr * ret = new ApplicationExpr( deref, { arg } ); 53 delete ret-> get_result();54 ret-> set_result( base->clone());55 ret-> get_result()->set_lvalue( true );53 delete ret->result; 54 ret->result = base->clone(); 55 ret->result->set_lvalue( true ); 56 56 return ret; 57 57 } else { … … 308 308 int diff = depth1-depth2; 309 309 if ( diff == 0 ) { 310 // conversion between references of the same depth 310 311 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 311 312 PRINT( std::cerr << castExpr << std::endl; ) 312 313 return castExpr; 313 314 } else if ( diff < 0 ) { 314 Expression * ret = castExpr->get_arg(); 315 // conversion from reference to reference with less depth (e.g. int && -> int &): add dereferences 316 Expression * ret = castExpr->arg; 315 317 for ( int i = 0; i < diff; ++i ) { 316 318 ret = mkDeref( ret ); 317 319 } 318 ret->set_env( castExpr->get_env() ); 319 delete ret->get_result(); 320 ret->set_result( castExpr->get_result() ); 321 castExpr->set_env( nullptr ); 322 castExpr->set_arg( nullptr ); 323 castExpr->set_result( nullptr ); 320 ret->env = castExpr->env; 321 delete ret->result; 322 ret->result = castExpr->result; 323 ret->result->set_lvalue( true ); // ensure result is lvalue 324 castExpr->env = nullptr; 325 castExpr->arg = nullptr; 326 castExpr->result = nullptr; 324 327 delete castExpr; 325 328 return ret; 326 329 } else if ( diff > 0 ) { 327 Expression * ret = castExpr->get_arg(); 330 // conversion from reference to reference with more depth (e.g. int & -> int &&): add address-of 331 Expression * ret = castExpr->arg; 328 332 for ( int i = 0; i < diff; ++i ) { 329 333 ret = new AddressExpr( ret ); 330 334 } 331 ret-> set_env( castExpr->get_env() );332 delete ret-> get_result();333 ret-> set_result( castExpr->get_result() );334 castExpr-> set_env( nullptr );335 castExpr-> set_arg( nullptr );336 castExpr-> set_result( nullptr );335 ret->env = castExpr->env; 336 delete ret->result; 337 ret->result = castExpr->result; 338 castExpr->env = nullptr; 339 castExpr->arg = nullptr; 340 castExpr->result = nullptr; 337 341 delete castExpr; 338 342 return ret; … … 342 346 PRINT( std::cerr << castExpr << std::endl; ) 343 347 return castExpr; 344 } else if ( castExpr-> get_arg()->get_result()->get_lvalue() ) {348 } else if ( castExpr->arg->result->get_lvalue() ) { 345 349 // conversion from lvalue to reference 346 350 // xxx - keep cast, but turn into pointer cast?? … … 348 352 PRINT( 349 353 std::cerr << "convert lvalue to reference -- &" << std::endl; 350 std::cerr << castExpr-> get_arg()<< std::endl;354 std::cerr << castExpr->arg << std::endl; 351 355 ) 352 AddressExpr * ret = new AddressExpr( castExpr-> get_arg());353 if ( refType-> get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {356 AddressExpr * ret = new AddressExpr( castExpr->arg ); 357 if ( refType->base->get_qualifiers() != castExpr->arg->result->get_qualifiers() ) { 354 358 // must keep cast if cast-to type is different from the actual type 355 castExpr-> set_arg( ret );359 castExpr->arg = ret; 356 360 return castExpr; 357 361 } 358 ret-> set_env( castExpr->get_env() );359 delete ret-> get_result();360 ret-> set_result( castExpr->get_result() );361 castExpr-> set_env( nullptr );362 castExpr-> set_arg( nullptr );363 castExpr-> set_result( nullptr );362 ret->env = castExpr->env; 363 delete ret->result; 364 ret->result = castExpr->result; 365 castExpr->env = nullptr; 366 castExpr->arg = nullptr; 367 castExpr->result = nullptr; 364 368 delete castExpr; 365 369 return ret; … … 368 372 } 369 373 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() ); 370 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr-> get_arg()->get_result()) ) {374 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->arg->result ) ) { 371 375 (void)refType; 372 376 // conversion from reference to rvalue … … 375 379 std::cerr << "was = " << castExpr << std::endl; 376 380 ) 377 Expression * ret = castExpr-> get_arg();378 TypeSubstitution * env = castExpr-> get_env();381 Expression * ret = castExpr->arg; 382 TypeSubstitution * env = castExpr->env; 379 383 castExpr->set_env( nullptr ); 380 384 if ( ! isIntrinsicReference( ret ) ) { … … 382 386 ret = mkDeref( ret ); 383 387 } 384 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr-> get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {388 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->result, castExpr->arg->result->stripReferences(), SymTab::Indexer() ) ) { 385 389 // can remove cast if types are compatible, changing expression type to value type 386 ret->set_result( castExpr->get_result()->clone() ); 387 castExpr->set_arg( nullptr ); 390 ret->result = castExpr->result->clone(); 391 ret->result->set_lvalue( true ); // ensure result is lvalue 392 castExpr->arg = nullptr; 388 393 delete castExpr; 389 394 } else { 390 395 // must keep cast if types are different 391 castExpr-> set_arg( ret );396 castExpr->arg = ret; 392 397 ret = castExpr; 393 398 } -
src/GenPoly/ScrubTyVars.cc
r2b72090 rbee7f04 25 25 26 26 namespace GenPoly { 27 Type * ScrubTyVars:: mutate( TypeInstType *typeInst ) {27 Type * ScrubTyVars::postmutate( TypeInstType * typeInst ) { 28 28 if ( ! tyVars ) { 29 29 if ( typeInst->get_isFtype() ) { … … 31 31 return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) ); 32 32 } else { 33 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );33 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) ); 34 34 delete typeInst; 35 35 return ret; … … 37 37 } 38 38 39 TyVarMap::const_iterator tyVar = tyVars->find( typeInst-> get_name());39 TyVarMap::const_iterator tyVar = tyVars->find( typeInst->name ); 40 40 if ( tyVar != tyVars->end() ) { 41 41 switch ( tyVar->second.kind ) { … … 43 43 case TypeDecl::Ttype: 44 44 { 45 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );45 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) ); 46 46 delete typeInst; 47 47 return ret; … … 55 55 } 56 56 57 Type * ScrubTyVars::mutateAggregateType( Type * ty ) {57 Type * ScrubTyVars::mutateAggregateType( Type * ty ) { 58 58 if ( shouldScrub( ty ) ) { 59 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );59 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) ); 60 60 delete ty; 61 61 return ret; … … 64 64 } 65 65 66 Type * ScrubTyVars:: mutate( StructInstType *structInst ) {66 Type * ScrubTyVars::postmutate( StructInstType * structInst ) { 67 67 return mutateAggregateType( structInst ); 68 68 } 69 69 70 Type * ScrubTyVars:: mutate( UnionInstType *unionInst ) {70 Type * ScrubTyVars::postmutate( UnionInstType * unionInst ) { 71 71 return mutateAggregateType( unionInst ); 72 72 } 73 73 74 Expression * ScrubTyVars::mutate( SizeofExpr *szeof ) { 74 void ScrubTyVars::primeBaseScrub( Type * type ) { 75 // need to determine whether type needs to be scrubbed to determine whether 76 // automatic recursion is necessary 77 if ( Type * t = shouldScrub( type ) ) { 78 visit_children = false; 79 GuardValue( dynType ); 80 dynType = t; 81 } 82 } 83 84 Expression * ScrubTyVars::postmutate( SizeofExpr * szeof ) { 75 85 // sizeof( T ) => _sizeof_T parameter, which is the size of T 76 if ( Type *dynType = shouldScrub( szeof->get_type() )) {86 if ( dynType ) { 77 87 Expression *expr = new NameExpr( sizeofName( mangleType( dynType ) ) ); 78 88 return expr; 79 } else {80 return Mutator::mutate( szeof );81 89 } // if 90 return szeof; 82 91 } 83 92 84 Expression * ScrubTyVars:: mutate( AlignofExpr *algnof ) {93 Expression * ScrubTyVars::postmutate( AlignofExpr * algnof ) { 85 94 // alignof( T ) => _alignof_T parameter, which is the alignment of T 86 if ( Type *dynType = shouldScrub( algnof->get_type() )) {95 if ( dynType ) { 87 96 Expression *expr = new NameExpr( alignofName( mangleType( dynType ) ) ); 88 97 return expr; 89 } else {90 return Mutator::mutate( algnof );91 98 } // if 99 return algnof; 92 100 } 93 101 94 Type * ScrubTyVars::mutate( PointerType *pointer ) { 95 // // special case of shouldScrub that takes all TypeInstType pointer bases, even if they're not dynamic 96 // Type *base = pointer->get_base(); 97 // Type *dynType = 0; 98 // if ( dynamicOnly ) { 99 // if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( base ) ) { 100 // if ( tyVars.find( typeInst->get_name() ) != tyVars.end() ) { dynType = typeInst; } 101 // } else { 102 // dynType = isDynType( base, tyVars ); 103 // } 104 // } else { 105 // dynType = isPolyType( base, tyVars ); 106 // } 107 // if ( dynType ) { 108 if ( Type *dynType = shouldScrub( pointer->get_base() ) ) { 109 Type *ret = dynType->acceptMutator( *this ); 102 Type * ScrubTyVars::postmutate( PointerType * pointer ) { 103 if ( dynType ) { 104 Type * ret = dynType->acceptMutator( *visitor ); 110 105 ret->get_qualifiers() |= pointer->get_qualifiers(); 111 pointer-> set_base( 0 );106 pointer->base = nullptr; 112 107 delete pointer; 113 108 return ret; 114 109 } 115 return Mutator::mutate( pointer );110 return pointer; 116 111 } 117 112 } // namespace GenPoly -
src/GenPoly/ScrubTyVars.h
r2b72090 rbee7f04 18 18 #include <cassert> // for assert 19 19 20 #include "Common/PassVisitor.h" 20 21 #include "GenPoly.h" // for TyVarMap, isPolyType, isDynType 21 22 #include "SynTree/Mutator.h" // for Mutator … … 27 28 28 29 namespace GenPoly { 29 class ScrubTyVars : public Mutator{30 struct ScrubTyVars : public WithVisitorRef<ScrubTyVars>, public WithShortCircuiting, public WithGuards { 30 31 /// Whether to scrub all type variables from the provided map, dynamic type variables from the provided map, or all type variables 31 32 enum ScrubMode { FromMap, DynamicFromMap, All }; … … 51 52 static SynTreeClass *scrubAll( SynTreeClass *target ); 52 53 53 virtual Type* mutate( TypeInstType *typeInst ); 54 virtual Type* mutate( StructInstType *structInst ); 55 virtual Type* mutate( UnionInstType *unionInst ); 56 virtual Expression* mutate( SizeofExpr *szeof ); 57 virtual Expression* mutate( AlignofExpr *algnof ); 58 virtual Type* mutate( PointerType *pointer ); 54 /// determine if children should be visited based on whether base type should be scrubbed. 55 void primeBaseScrub( Type * ); 56 57 void premutate( TypeInstType * ) { visit_children = false; } 58 void premutate( StructInstType * ) { visit_children = false; } 59 void premutate( UnionInstType * ) { visit_children = false; } 60 void premutate( SizeofExpr * szeof ) { primeBaseScrub( szeof->type ); } 61 void premutate( AlignofExpr * algnof ) { primeBaseScrub( algnof->type ); } 62 void premutate( PointerType * pointer ) { primeBaseScrub( pointer->base ); } 63 64 Type * postmutate( TypeInstType * typeInst ); 65 Type * postmutate( StructInstType * structInst ); 66 Type * postmutate( UnionInstType * unionInst ); 67 Expression * postmutate( SizeofExpr * szeof ); 68 Expression * postmutate( AlignofExpr * algnof ); 69 Type * postmutate( PointerType * pointer ); 59 70 60 71 private: … … 75 86 const TyVarMap *tyVars; ///< Type variables to scrub 76 87 ScrubMode mode; ///< which type variables to scrub? [FromMap] 88 89 Type * dynType = nullptr; ///< result of shouldScrub 77 90 }; 78 91 79 92 template< typename SynTreeClass > 80 93 SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target, const TyVarMap &tyVars ) { 81 ScrubTyVarsscrubber( tyVars );94 PassVisitor<ScrubTyVars> scrubber( tyVars ); 82 95 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) ); 83 96 } … … 85 98 template< typename SynTreeClass > 86 99 SynTreeClass * ScrubTyVars::scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars ) { 87 ScrubTyVarsscrubber( tyVars, ScrubTyVars::DynamicFromMap );100 PassVisitor<ScrubTyVars> scrubber( tyVars, ScrubTyVars::DynamicFromMap ); 88 101 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) ); 89 102 } … … 91 104 template< typename SynTreeClass > 92 105 SynTreeClass * ScrubTyVars::scrubAll( SynTreeClass *target ) { 93 ScrubTyVarsscrubber;106 PassVisitor<ScrubTyVars> scrubber; 94 107 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) ); 95 108 } -
src/InitTweak/FixInit.cc
r2b72090 rbee7f04 197 197 }; 198 198 199 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer {199 struct GenStructMemberCalls final : public WithGuards, public WithShortCircuiting, public WithIndexer, public WithVisitorRef<GenStructMemberCalls> { 200 200 /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors 201 201 /// for any member that is missing a corresponding ctor/dtor call. … … 203 203 static void generate( std::list< Declaration * > & translationUnit ); 204 204 205 void previsit( FunctionDecl * funcDecl ); 206 void postvisit( FunctionDecl * funcDecl ); 207 208 void previsit( MemberExpr * memberExpr ); 209 void previsit( ApplicationExpr * appExpr ); 205 void premutate( FunctionDecl * funcDecl ); 206 DeclarationWithType * postmutate( FunctionDecl * funcDecl ); 207 208 void premutate( MemberExpr * memberExpr ); 209 void premutate( ApplicationExpr * appExpr ); 210 211 /// Note: this post mutate used to be in a separate visitor. If this pass breaks, one place to examine is whether it is 212 /// okay for this part of the recursion to occur alongside the rest. 213 Expression * postmutate( UntypedExpr * expr ); 210 214 211 215 SemanticError errors; … … 220 224 bool isCtor = false; // true if current function is a constructor 221 225 StructDecl * structDecl = nullptr; 222 };223 224 // very simple resolver-like mutator class - used to225 // resolve UntypedExprs that are found within newly226 // generated constructor/destructor calls227 class MutatingResolver final : public Mutator {228 public:229 MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}230 231 using Mutator::mutate;232 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ) override;233 virtual Expression* mutate( UntypedExpr *untypedExpr ) override;234 235 private:236 SymTab::Indexer & indexer;237 226 }; 238 227 … … 315 304 void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) { 316 305 PassVisitor<GenStructMemberCalls> warner; 317 acceptAll( translationUnit, warner );306 mutateAll( translationUnit, warner ); 318 307 } 319 308 … … 950 939 } 951 940 952 void GenStructMemberCalls::pre visit( FunctionDecl * funcDecl ) {941 void GenStructMemberCalls::premutate( FunctionDecl * funcDecl ) { 953 942 GuardValue( function ); 954 943 GuardValue( unhandled ); … … 984 973 } 985 974 986 void GenStructMemberCalls::postvisit( FunctionDecl * funcDecl ) {975 DeclarationWithType * GenStructMemberCalls::postmutate( FunctionDecl * funcDecl ) { 987 976 // remove the unhandled objects from usedUninit, because a call is inserted 988 977 // to handle them - only objects that are later constructed are used uninitialized. … … 1038 1027 Statement * callStmt = stmt.front(); 1039 1028 1040 MutatingResolver resolver( indexer );1041 1029 try { 1042 callStmt->acceptMutator( resolver );1030 callStmt->acceptMutator( *visitor ); 1043 1031 if ( isCtor ) { 1044 1032 function->get_statements()->push_front( callStmt ); … … 1056 1044 throw errors; 1057 1045 } 1046 return funcDecl; 1058 1047 } 1059 1048 … … 1081 1070 } 1082 1071 1083 void GenStructMemberCalls::pre visit( ApplicationExpr * appExpr ) {1072 void GenStructMemberCalls::premutate( ApplicationExpr * appExpr ) { 1084 1073 if ( ! checkWarnings( function ) ) { 1085 1074 visit_children = false; … … 1106 1095 } 1107 1096 1108 void GenStructMemberCalls::pre visit( MemberExpr * memberExpr ) {1097 void GenStructMemberCalls::premutate( MemberExpr * memberExpr ) { 1109 1098 if ( ! checkWarnings( function ) || ! isCtor ) { 1110 1099 visit_children = false; … … 1134 1123 } 1135 1124 1136 DeclarationWithType * MutatingResolver::mutate( ObjectDecl * objectDecl ) { 1137 // add object to the indexer assumes that there will be no name collisions 1138 // in generated code. If this changes, add mutate methods for entities with 1139 // scope and call {enter,leave}Scope explicitly. 1140 indexer.addId( objectDecl ); 1141 return objectDecl; 1142 } 1143 1144 Expression * MutatingResolver::mutate( UntypedExpr * untypedExpr ) { 1125 Expression * GenStructMemberCalls::postmutate( UntypedExpr * untypedExpr ) { 1145 1126 Expression * newExpr = untypedExpr; 1146 1127 ResolvExpr::findVoidExpression( newExpr, indexer ); -
src/ResolvExpr/CastCost.cc
r2b72090 rbee7f04 31 31 32 32 namespace ResolvExpr { 33 classCastCost : public ConversionCost {33 struct CastCost : public ConversionCost { 34 34 public: 35 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );35 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ); 36 36 37 virtual void visit( BasicType *basicType ); 38 virtual void visit( PointerType *pointerType ); 37 using ConversionCost::previsit; 38 using ConversionCost::postvisit; 39 void postvisit( BasicType * basicType ); 40 void postvisit( PointerType * pointerType ); 39 41 }; 40 42 … … 52 54 // all typedefs should be gone by this point 53 55 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType ); 54 if ( type-> get_base()) {55 return castCost( src, type-> get_base(), indexer, env ) + Cost::safe;56 if ( type->base ) { 57 return castCost( src, type->base, indexer, env ) + Cost::safe; 56 58 } // if 57 59 } // if … … 74 76 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 75 77 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 76 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer & indexer) {78 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) { 77 79 return ptrsCastable( t1, t2, env, indexer ); 78 80 }); 79 81 } else { 80 CastCost converter( dest, indexer, env);82 PassVisitor<CastCost> converter( dest, indexer, env, castCost ); 81 83 src->accept( converter ); 82 if ( converter. get_cost() == Cost::infinity ) {84 if ( converter.pass.get_cost() == Cost::infinity ) { 83 85 return Cost::infinity; 84 86 } else { 85 87 // xxx - why are we adding cost 0 here? 86 return converter. get_cost() + Cost::zero;88 return converter.pass.get_cost() + Cost::zero; 87 89 } // if 88 90 } // if 89 91 } 90 92 91 CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )92 : ConversionCost( dest, indexer, env ) {93 CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 94 : ConversionCost( dest, indexer, env, costFunc ) { 93 95 } 94 96 95 void CastCost:: visit( BasicType *basicType ) {97 void CastCost::postvisit( BasicType *basicType ) { 96 98 PointerType *destAsPointer = dynamic_cast< PointerType* >( dest ); 97 99 if ( destAsPointer && basicType->isInteger() ) { … … 103 105 } 104 106 105 void CastCost:: visit( PointerType *pointerType ) {107 void CastCost::postvisit( PointerType *pointerType ) { 106 108 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 107 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType-> get_base(), destAsPtr->get_base(), indexer, env ) ) {109 if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 108 110 cost = Cost::safe; 109 111 } else { 110 112 TypeEnvironment newEnv( env ); 111 newEnv.add( pointerType-> get_forall());112 newEnv.add( pointerType-> get_base()->get_forall());113 int castResult = ptrsCastable( pointerType-> get_base(), destAsPtr->get_base(), newEnv, indexer );113 newEnv.add( pointerType->forall ); 114 newEnv.add( pointerType->base->forall ); 115 int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer ); 114 116 if ( castResult > 0 ) { 115 117 cost = Cost::safe; -
src/ResolvExpr/ConversionCost.cc
r2b72090 rbee7f04 44 44 EqvClass eqvClass; 45 45 NamedTypeDecl *namedType; 46 PRINT( std::cerr << "type inst " << destAsTypeInst-> get_name(); )47 if ( env.lookup( destAsTypeInst-> get_name(), eqvClass ) ) {46 PRINT( std::cerr << "type inst " << destAsTypeInst->name; ) 47 if ( env.lookup( destAsTypeInst->name, eqvClass ) ) { 48 48 if ( eqvClass.type ) { 49 49 return conversionCost( src, eqvClass.type, indexer, env ); … … 51 51 return Cost::infinity; 52 52 } 53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst-> get_name()) ) ) {53 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->name ) ) ) { 54 54 PRINT( std::cerr << " found" << std::endl; ) 55 55 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 56 56 // all typedefs should be gone by this point 57 57 assert( type ); 58 if ( type-> get_base()) {59 return conversionCost( src, type-> get_base(), indexer, env ) + Cost::safe;58 if ( type->base ) { 59 return conversionCost( src, type->base, indexer, env ) + Cost::safe; 60 60 } // if 61 61 } // if … … 77 77 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) { 78 78 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; ) 79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const TypeEnvironment & env, const SymTab::Indexer &){79 return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){ 80 80 return ptrsAssignable( t1, t2, env ); 81 81 }); 82 82 } else { 83 ConversionCost converter( dest, indexer, env);83 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 84 84 src->accept( converter ); 85 if ( converter. get_cost() == Cost::infinity ) {85 if ( converter.pass.get_cost() == Cost::infinity ) { 86 86 return Cost::infinity; 87 87 } else { 88 return converter. get_cost() + Cost::zero;88 return converter.pass.get_cost() + Cost::zero; 89 89 } // if 90 90 } // if … … 95 95 if ( diff > 0 ) { 96 96 // TODO: document this 97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )-> get_base(), dest, diff-1, indexer, env, func );97 Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func ); 98 98 cost.incReference(); 99 99 return cost; 100 100 } else if ( diff < -1 ) { 101 101 // TODO: document this 102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )-> get_base(), diff+1, indexer, env, func );102 Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func ); 103 103 cost.incReference(); 104 104 return cost; … … 108 108 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references 109 109 PRINT( std::cerr << "converting between references" << std::endl; ) 110 Type::Qualifiers tq1 = srcAsRef-> get_base()->get_qualifiers();111 Type::Qualifiers tq2 = destAsRef-> get_base()->get_qualifiers();112 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef-> get_base(), destAsRef->get_base(), indexer, env ) ) {110 Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers(); 111 Type::Qualifiers tq2 = destAsRef->base->get_qualifiers(); 112 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) { 113 113 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 114 114 if ( tq1 == tq2 ) { … … 120 120 } 121 121 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right? 122 int assignResult = func( srcAsRef-> get_base(), destAsRef->get_base(), env, indexer);122 int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env ); 123 123 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; ) 124 124 if ( assignResult > 0 ) { … … 130 130 } else { 131 131 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; ) 132 ConversionCost converter( dest, indexer, env);132 PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost ); 133 133 src->accept( converter ); 134 return converter. get_cost();134 return converter.pass.get_cost(); 135 135 } // if 136 136 } else { … … 138 138 assert( diff == -1 && destAsRef ); 139 139 PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; ) 140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef-> get_base(), indexer, env ) ) {140 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) { 141 141 PRINT( std::cerr << "converting compatible base type" << std::endl; ) 142 142 if ( src->get_lvalue() ) { … … 146 146 ) 147 147 // lvalue-to-reference conversion: cv lvalue T => cv T & 148 if ( src->get_qualifiers() == destAsRef-> get_base()->get_qualifiers() ) {148 if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) { 149 149 return Cost::reference; // cost needs to be non-zero to add cast 150 } if ( src->get_qualifiers() < destAsRef-> get_base()->get_qualifiers() ) {150 } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) { 151 151 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same 152 152 } else { 153 153 return Cost::unsafe; 154 154 } // if 155 } else if ( destAsRef-> get_base()->get_const() ) {155 } else if ( destAsRef->base->get_const() ) { 156 156 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; ) 157 157 // rvalue-to-const-reference conversion: T => const T & … … 173 173 } 174 174 175 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )176 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {175 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc ) 176 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) { 177 177 } 178 178 … … 257 257 }; 258 258 259 void ConversionCost:: visit( VoidType * ) {259 void ConversionCost::postvisit( VoidType * ) { 260 260 cost = Cost::infinity; 261 261 } 262 262 263 void ConversionCost:: visit(BasicType *basicType) {263 void ConversionCost::postvisit(BasicType *basicType) { 264 264 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { 265 265 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ]; … … 278 278 } 279 279 280 void ConversionCost:: visit( PointerType * pointerType ) {280 void ConversionCost::postvisit( PointerType * pointerType ) { 281 281 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { 282 282 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; ) 283 Type::Qualifiers tq1 = pointerType-> get_base()->get_qualifiers();284 Type::Qualifiers tq2 = destAsPtr-> get_base()->get_qualifiers();285 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType-> get_base(), destAsPtr->get_base(), indexer, env ) ) {283 Type::Qualifiers tq1 = pointerType->base->get_qualifiers(); 284 Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers(); 285 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) { 286 286 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; ) 287 287 if ( tq1 == tq2 ) { … … 312 312 } 313 313 314 void ConversionCost:: visit( ArrayType * ) {}315 316 void ConversionCost:: visit( ReferenceType * refType ) {314 void ConversionCost::postvisit( ArrayType * ) {} 315 316 void ConversionCost::postvisit( ReferenceType * refType ) { 317 317 // Note: dest can never be a reference, since it would have been caught in an earlier check 318 318 assert( ! dynamic_cast< ReferenceType * >( dest ) ); … … 320 320 // recursively compute conversion cost from T1 to T2. 321 321 // cv can be safely dropped because of 'implicit dereference' behavior. 322 refType->base->accept( *this);322 cost = costFunc( refType->base, dest, indexer, env ); 323 323 if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) { 324 324 cost.incReference(); // prefer exact qualifiers … … 331 331 } 332 332 333 void ConversionCost:: visit( FunctionType * ) {}334 335 void ConversionCost:: visit( StructInstType * inst ) {333 void ConversionCost::postvisit( FunctionType * ) {} 334 335 void ConversionCost::postvisit( StructInstType * inst ) { 336 336 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) { 337 337 if ( inst->name == destAsInst->name ) { … … 341 341 } 342 342 343 void ConversionCost:: visit( UnionInstType * inst ) {343 void ConversionCost::postvisit( UnionInstType * inst ) { 344 344 if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) { 345 345 if ( inst->name == destAsInst->name ) { … … 349 349 } 350 350 351 void ConversionCost:: visit( EnumInstType * ) {351 void ConversionCost::postvisit( EnumInstType * ) { 352 352 static Type::Qualifiers q; 353 353 static BasicType integer( q, BasicType::SignedInt ); 354 integer.accept( *this); // safe if dest >= int354 cost = costFunc( &integer, dest, indexer, env ); // safe if dest >= int 355 355 if ( cost < Cost::unsafe ) { 356 356 cost.incSafe(); … … 358 358 } 359 359 360 void ConversionCost:: visit( TraitInstType * ) {}361 362 void ConversionCost:: visit( TypeInstType *inst ) {360 void ConversionCost::postvisit( TraitInstType * ) {} 361 362 void ConversionCost::postvisit( TypeInstType *inst ) { 363 363 EqvClass eqvClass; 364 364 NamedTypeDecl *namedType; 365 if ( env.lookup( inst-> get_name(), eqvClass ) ) {366 cost = co nversionCost( eqvClass.type, dest, indexer, env );365 if ( env.lookup( inst->name, eqvClass ) ) { 366 cost = costFunc( eqvClass.type, dest, indexer, env ); 367 367 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) { 368 if ( inst-> get_name() == destAsInst->get_name()) {368 if ( inst->name == destAsInst->name ) { 369 369 cost = Cost::zero; 370 370 } 371 } else if ( ( namedType = indexer.lookupType( inst-> get_name()) ) ) {371 } else if ( ( namedType = indexer.lookupType( inst->name ) ) ) { 372 372 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); 373 373 // all typedefs should be gone by this point 374 374 assert( type ); 375 if ( type-> get_base()) {376 cost = co nversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;377 } // if 378 } // if 379 } 380 381 void ConversionCost:: visit( TupleType * tupleType ) {375 if ( type->base ) { 376 cost = costFunc( type->base, dest, indexer, env ) + Cost::safe; 377 } // if 378 } // if 379 } 380 381 void ConversionCost::postvisit( TupleType * tupleType ) { 382 382 Cost c = Cost::zero; 383 383 if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) { 384 std::list< Type * >::const_iterator srcIt = tupleType-> get_types().begin();385 std::list< Type * >::const_iterator destIt = destAsTuple-> get_types().begin();386 while ( srcIt != tupleType-> get_types().end() && destIt != destAsTuple->get_types().end() ) {387 Cost newCost = co nversionCost( *srcIt++, *destIt++, indexer, env );384 std::list< Type * >::const_iterator srcIt = tupleType->types.begin(); 385 std::list< Type * >::const_iterator destIt = destAsTuple->types.begin(); 386 while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) { 387 Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env ); 388 388 if ( newCost == Cost::infinity ) { 389 389 return; … … 391 391 c += newCost; 392 392 } // while 393 if ( destIt != destAsTuple-> get_types().end() ) {393 if ( destIt != destAsTuple->types.end() ) { 394 394 cost = Cost::infinity; 395 395 } else { … … 399 399 } 400 400 401 void ConversionCost:: visit( VarArgsType * ) {401 void ConversionCost::postvisit( VarArgsType * ) { 402 402 if ( dynamic_cast< VarArgsType* >( dest ) ) { 403 403 cost = Cost::zero; … … 405 405 } 406 406 407 void ConversionCost:: visit( ZeroType * ) {407 void ConversionCost::postvisit( ZeroType * ) { 408 408 if ( dynamic_cast< ZeroType * >( dest ) ) { 409 409 cost = Cost::zero; … … 422 422 } 423 423 424 void ConversionCost:: visit( OneType * ) {424 void ConversionCost::postvisit( OneType * ) { 425 425 if ( dynamic_cast< OneType * >( dest ) ) { 426 426 cost = Cost::zero; -
src/ResolvExpr/ConversionCost.h
r2b72090 rbee7f04 19 19 20 20 #include "Cost.h" // for Cost 21 22 #include "Common/PassVisitor.h" 21 23 #include "SynTree/Visitor.h" // for Visitor 22 24 #include "SynTree/SynTree.h" // for Visitor Nodes … … 29 31 class TypeEnvironment; 30 32 31 class ConversionCost : public Visitor { 33 typedef std::function<Cost(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> CostFunction; 34 struct ConversionCost : public WithShortCircuiting { 32 35 public: 33 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env );36 ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction ); 34 37 35 38 Cost get_cost() const { return cost; } 36 39 37 virtual void visit(VoidType *voidType); 38 virtual void visit(BasicType *basicType); 39 virtual void visit(PointerType *pointerType); 40 virtual void visit(ArrayType *arrayType); 41 virtual void visit(ReferenceType *refType); 42 virtual void visit(FunctionType *functionType); 43 virtual void visit(StructInstType *aggregateUseType); 44 virtual void visit(UnionInstType *aggregateUseType); 45 virtual void visit(EnumInstType *aggregateUseType); 46 virtual void visit(TraitInstType *aggregateUseType); 47 virtual void visit(TypeInstType *aggregateUseType); 48 virtual void visit(TupleType *tupleType); 49 virtual void visit(VarArgsType *varArgsType); 50 virtual void visit(ZeroType *zeroType); 51 virtual void visit(OneType *oneType); 40 void previsit( BaseSyntaxNode * ) { visit_children = false; } 41 42 void postvisit( VoidType * voidType ); 43 void postvisit( BasicType * basicType ); 44 void postvisit( PointerType * pointerType ); 45 void postvisit( ArrayType * arrayType ); 46 void postvisit( ReferenceType * refType ); 47 void postvisit( FunctionType * functionType ); 48 void postvisit( StructInstType * aggregateUseType ); 49 void postvisit( UnionInstType * aggregateUseType ); 50 void postvisit( EnumInstType * aggregateUseType ); 51 void postvisit( TraitInstType * aggregateUseType ); 52 void postvisit( TypeInstType * aggregateUseType ); 53 void postvisit( TupleType * tupleType ); 54 void postvisit( VarArgsType * varArgsType ); 55 void postvisit( ZeroType * zeroType ); 56 void postvisit( OneType * oneType ); 52 57 protected: 53 58 Type *dest; … … 55 60 Cost cost; 56 61 const TypeEnvironment &env; 62 CostFunction costFunc; 57 63 }; 58 64 59 typedef std::function<int(Type *, Type *, const TypeEnvironment &, const SymTab::Indexer&)> PtrsFunction;65 typedef std::function<int(Type *, Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction; 60 66 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ); 61 67 } // namespace ResolvExpr -
src/ResolvExpr/Resolver.cc
r2b72090 rbee7f04 155 155 } // if 156 156 #endif 157 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end .");157 assertf( finder.get_alternatives().size() == 1, "findSingleExpression: must have exactly one alternative at the end: (%zd) %s", finder.get_alternatives().size(), toString( untyped ).c_str() ); 158 158 Alternative &choice = finder.get_alternatives().front(); 159 159 Expression *newExpr = choice.expr->clone(); … … 171 171 172 172 namespace { 173 /// resolve `untyped` to the expression whose type satisfies `pred` with the lowest cost; kindStr is used for providing better error messages 174 template<typename Pred> 175 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, Pred pred) { 176 TypeEnvironment env; 177 AlternativeFinder finder( indexer, env ); 178 finder.findWithAdjustment( untyped ); 179 180 AltList candidates; 181 for ( Alternative & alt : finder.get_alternatives() ) { 182 if ( pred( alt.expr->result ) ) { 183 candidates.push_back( std::move( alt ) ); 184 } 185 } 186 187 // choose the lowest cost expression among the candidates 188 AltList winners; 189 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 190 if ( winners.size() == 0 ) { 191 throw SemanticError( "No reasonable alternatives for " + kindStr + " expression: ", untyped ); 192 } else if ( winners.size() != 1 ) { 193 std::ostringstream stream; 194 stream << "Cannot choose between " << winners.size() << " alternatives for " + kindStr + " expression\n"; 195 untyped->print( stream ); 196 stream << "Alternatives are:\n"; 197 printAlts( winners, stream, 1 ); 198 throw SemanticError( stream.str() ); 199 } 200 201 // there is one unambiguous interpretation - move the expression into the with statement 202 Alternative & alt = winners.front(); 203 finishExpr( alt.expr, alt.env, untyped->env ); 204 delete untyped; 205 untyped = alt.expr; 206 alt.expr = nullptr; 207 } 208 173 209 bool isIntegralType( Type *type ) { 174 210 if ( dynamic_cast< EnumInstType * >( type ) ) { … … 184 220 185 221 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer &indexer ) { 186 TypeEnvironment env; 187 AlternativeFinder finder( indexer, env ); 188 finder.find( untyped ); 189 #if 0 190 if ( finder.get_alternatives().size() != 1 ) { 191 std::cout << "untyped expr is "; 192 untyped->print( std::cout ); 193 std::cout << std::endl << "alternatives are:"; 194 for ( std::list< Alternative >::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 195 i->print( std::cout ); 196 } // for 197 } // if 198 #endif 199 Expression *newExpr = 0; 200 const TypeEnvironment *newEnv = 0; 201 for ( AltList::const_iterator i = finder.get_alternatives().begin(); i != finder.get_alternatives().end(); ++i ) { 202 if ( i->expr->get_result()->size() == 1 && isIntegralType( i->expr->get_result() ) ) { 203 if ( newExpr ) { 204 throw SemanticError( "Too many interpretations for case control expression", untyped ); 205 } else { 206 newExpr = i->expr->clone(); 207 newEnv = &i->env; 208 } // if 209 } // if 210 } // for 211 if ( ! newExpr ) { 212 throw SemanticError( "No interpretations for case control expression", untyped ); 213 } // if 214 finishExpr( newExpr, *newEnv, untyped->env ); 215 delete untyped; 216 untyped = newExpr; 217 } 218 222 findKindExpression( untyped, indexer, "condition", isIntegralType ); 223 } 219 224 } 220 225 … … 311 316 312 317 void Resolver::previsit( IfStmt *ifStmt ) { 313 find SingleExpression( ifStmt->condition, indexer );318 findIntegralExpression( ifStmt->condition, indexer ); 314 319 } 315 320 316 321 void Resolver::previsit( WhileStmt *whileStmt ) { 317 find SingleExpression( whileStmt->condition, indexer );322 findIntegralExpression( whileStmt->condition, indexer ); 318 323 } 319 324 320 325 void Resolver::previsit( ForStmt *forStmt ) { 321 326 if ( forStmt->condition ) { 322 find SingleExpression( forStmt->condition, indexer );327 findIntegralExpression( forStmt->condition, indexer ); 323 328 } // if 324 329 … … 579 584 } 580 585 586 581 587 void Resolver::previsit( WithStmt * withStmt ) { 582 588 for ( Expression *& expr : withStmt->exprs ) { 583 TypeEnvironment env;584 AlternativeFinder finder( indexer, env );585 finder.findWithAdjustment( expr );586 587 589 // only struct- and union-typed expressions are viable candidates 588 AltList candidates; 589 for ( Alternative & alt : finder.get_alternatives() ) { 590 if ( isStructOrUnion( alt.expr->result ) ) { 591 candidates.push_back( std::move( alt ) ); 592 } 593 } 594 595 // choose the lowest cost expression among the candidates 596 AltList winners; 597 findMinCost( candidates.begin(), candidates.end(), back_inserter( winners ) ); 598 if ( winners.size() == 0 ) { 599 throw SemanticError( "No reasonable alternatives for with statement expression: ", expr ); 600 } else if ( winners.size() != 1 ) { 601 std::ostringstream stream; 602 stream << "Cannot choose between " << winners.size() << " alternatives for with statement expression\n"; 603 expr->print( stream ); 604 stream << "Alternatives are:\n"; 605 printAlts( winners, stream, 1 ); 606 throw SemanticError( stream.str() ); 607 } 608 609 // there is one unambiguous interpretation - move the expression into the with statement 610 Alternative & alt = winners.front(); 611 finishExpr( alt.expr, alt.env, expr->env ); 612 delete expr; 613 expr = alt.expr; 614 alt.expr = nullptr; 590 findKindExpression( expr, indexer, "with statement", isStructOrUnion ); 615 591 616 592 // if with expression might be impure, create a temporary so that it is evaluated once -
src/SynTree/AggregateDecl.cc
r2b72090 rbee7f04 92 92 } else if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) { 93 93 return constExpr->intValue(); 94 // can be -1, +1, etc. 95 // } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) { 96 // if ( untypedExpr-> ) 94 97 } else { 95 98 assertf( false, "Unhandled expression type in getConstValue for enumerators: %s", toString( expr ).c_str() ); -
src/SynTree/Expression.cc
r2b72090 rbee7f04 108 108 // assert( inst->baseEnum ); 109 109 // EnumDecl * decl = inst->baseEnum; 110 // for ( Declaration * member : decl->members ) { 111 // if ( member == _var ) { 112 // type->set_lvalue( false ); 113 // } 110 // long long int value; 111 // if ( decl->valueOf( var, value ) ) { 112 // type->set_lvalue( false ); 114 113 // } 115 114 // } … … 416 415 } else { 417 416 // references have been removed, in which case dereference returns an lvalue of the base type. 418 ret-> get_result()->set_lvalue( true );417 ret->result->set_lvalue( true ); 419 418 } 420 419 } -
src/SynTree/Label.h
r2b72090 rbee7f04 33 33 std::list< Attribute * >& get_attributes() { return attributes; } 34 34 35 operator std::string() { return name; }35 operator std::string() const { return name; } 36 36 bool empty() { return name.empty(); } 37 37 private: -
src/SynTree/TypeSubstitution.cc
r2b72090 rbee7f04 107 107 108 108 void TypeSubstitution::normalize() { 109 PassVisitor<Substituter> sub( *this, true ); 109 110 do { 110 sub Count = 0;111 freeOnly = true;111 sub.pass.subCount = 0; 112 sub.pass.freeOnly = true; 112 113 for ( TypeEnvType::iterator i = typeEnv.begin(); i != typeEnv.end(); ++i ) { 113 i->second = i->second->acceptMutator( *this);114 i->second = i->second->acceptMutator( sub ); 114 115 } 115 } while ( sub Count );116 } 117 118 Type * TypeSubstitution:: mutate( TypeInstType *inst ) {119 BoundVarsType::const_iterator bound = boundVars.find( inst-> get_name());116 } while ( sub.pass.subCount ); 117 } 118 119 Type * TypeSubstitution::Substituter::postmutate( TypeInstType *inst ) { 120 BoundVarsType::const_iterator bound = boundVars.find( inst->name ); 120 121 if ( bound != boundVars.end() ) return inst; 121 122 122 TypeEnvType::const_iterator i = typeEnv.find( inst->get_name() );123 if ( i == typeEnv.end() ) {123 TypeEnvType::const_iterator i = sub.typeEnv.find( inst->get_name() ); 124 if ( i == sub.typeEnv.end() ) { 124 125 return inst; 125 126 } else { 126 /// std::c out<< "found " << inst->get_name() << ", replacing with ";127 /// i->second->print( std::c out);128 /// std::c out<< std::endl;127 /// std::cerr << "found " << inst->get_name() << ", replacing with "; 128 /// i->second->print( std::cerr ); 129 /// std::cerr << std::endl; 129 130 subCount++; 130 Type * newtype = i->second->clone();131 Type * newtype = i->second->clone(); 131 132 newtype->get_qualifiers() |= inst->get_qualifiers(); 132 133 delete inst; … … 135 136 } 136 137 137 Expression * TypeSubstitution:: mutate( NameExpr *nameExpr ) {138 VarEnvType::const_iterator i = varEnv.find( nameExpr->get_name());139 if ( i == varEnv.end() ) {138 Expression * TypeSubstitution::Substituter::postmutate( NameExpr * nameExpr ) { 139 VarEnvType::const_iterator i = sub.varEnv.find( nameExpr->name ); 140 if ( i == sub.varEnv.end() ) { 140 141 return nameExpr; 141 142 } else { … … 146 147 } 147 148 148 template< typename TypeClass > 149 Type *TypeSubstitution::handleType( TypeClass *type ) { 150 ValueGuard<BoundVarsType> oldBoundVars( boundVars ); 149 void TypeSubstitution::Substituter::premutate( Type * type ) { 150 GuardValue( boundVars ); 151 151 // bind type variables from forall-qualifiers 152 152 if ( freeOnly ) { 153 for ( Type::ForallList::const_iterator tyvar = type-> get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {154 boundVars.insert( (*tyvar )->get_name());153 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) { 154 boundVars.insert( (*tyvar)->name ); 155 155 } // for 156 156 } // if 157 Type *ret = Mutator::mutate( type );158 return ret;159 157 } 160 158 161 159 template< typename TypeClass > 162 Type *TypeSubstitution::handleAggregateType( TypeClass *type ) {163 ValueGuard<BoundVarsType> oldBoundVars( boundVars );160 void TypeSubstitution::Substituter::handleAggregateType( TypeClass * type ) { 161 GuardValue( boundVars ); 164 162 // bind type variables from forall-qualifiers 165 163 if ( freeOnly ) { 166 for ( Type::ForallList::const_iterator tyvar = type-> get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {167 boundVars.insert( (*tyvar )->get_name());164 for ( Type::ForallList::const_iterator tyvar = type->forall.begin(); tyvar != type->forall.end(); ++tyvar ) { 165 boundVars.insert( (*tyvar)->name ); 168 166 } // for 169 167 // bind type variables from generic type instantiations 170 168 std::list< TypeDecl* > *baseParameters = type->get_baseParameters(); 171 if ( baseParameters && ! type-> get_parameters().empty() ) {169 if ( baseParameters && ! type->parameters.empty() ) { 172 170 for ( std::list< TypeDecl* >::const_iterator tyvar = baseParameters->begin(); tyvar != baseParameters->end(); ++tyvar ) { 173 boundVars.insert( (*tyvar)-> get_name());171 boundVars.insert( (*tyvar)->name ); 174 172 } // for 175 173 } // if 176 174 } // if 177 Type *ret = Mutator::mutate( type ); 178 return ret; 179 } 180 181 Type * TypeSubstitution::mutate( VoidType *voidType ) { 182 return handleType( voidType ); 183 } 184 185 Type * TypeSubstitution::mutate( BasicType *basicType ) { 186 return handleType( basicType ); 187 } 188 189 Type * TypeSubstitution::mutate( PointerType *pointerType ) { 190 return handleType( pointerType ); 191 } 192 193 Type * TypeSubstitution::mutate( ArrayType *arrayType ) { 194 return handleType( arrayType ); 195 } 196 197 Type * TypeSubstitution::mutate( FunctionType *functionType ) { 198 return handleType( functionType ); 199 } 200 201 Type * TypeSubstitution::mutate( StructInstType *aggregateUseType ) { 202 return handleAggregateType( aggregateUseType ); 203 } 204 205 Type * TypeSubstitution::mutate( UnionInstType *aggregateUseType ) { 206 return handleAggregateType( aggregateUseType ); 207 } 208 209 Type * TypeSubstitution::mutate( EnumInstType *aggregateUseType ) { 210 return handleType( aggregateUseType ); 211 } 212 213 Type * TypeSubstitution::mutate( TraitInstType *aggregateUseType ) { 214 return handleType( aggregateUseType ); 215 } 216 217 Type * TypeSubstitution::mutate( TupleType *tupleType ) { 218 return handleType( tupleType ); 219 } 220 221 Type * TypeSubstitution::mutate( VarArgsType *varArgsType ) { 222 return handleType( varArgsType ); 223 } 224 225 Type * TypeSubstitution::mutate( ZeroType *zeroType ) { 226 return handleType( zeroType ); 227 } 228 229 Type * TypeSubstitution::mutate( OneType *oneType ) { 230 return handleType( oneType ); 175 } 176 177 void TypeSubstitution::Substituter::premutate( StructInstType * aggregateUseType ) { 178 handleAggregateType( aggregateUseType ); 179 } 180 181 void TypeSubstitution::Substituter::premutate( UnionInstType *aggregateUseType ) { 182 handleAggregateType( aggregateUseType ); 231 183 } 232 184 -
src/SynTree/TypeSubstitution.h
r2b72090 rbee7f04 27 27 #include "SynTree/Declaration.h" // for TypeDecl, Declaration (ptr only) 28 28 #include "SynTree/Expression.h" // for Expression (ptr only), NameExpr (p... 29 #include "SynTree/Mutator.h" // for Mutator30 29 #include "SynTree/Type.h" // for Type, ArrayType (ptr only), BasicT... 31 30 32 class TypeSubstitution : public Mutator { 33 typedef Mutator Parent; 31 class TypeSubstitution { 34 32 public: 35 33 TypeSubstitution(); … … 64 62 TypeSubstitution *clone() const { return new TypeSubstitution( *this ); } 65 63 private: 66 virtual Type* mutate(TypeInstType *aggregateUseType);67 virtual Expression* mutate(NameExpr *nameExpr);68 64 69 /// Records type variable bindings from forall-statements 70 template< typename TypeClass > Type *handleType( TypeClass *type ); 71 /// Records type variable bindings from forall-statements and instantiations of generic types 72 template< typename TypeClass > Type *handleAggregateType( TypeClass *type ); 73 74 virtual Type* mutate(VoidType *basicType); 75 virtual Type* mutate(BasicType *basicType); 76 virtual Type* mutate(PointerType *pointerType); 77 virtual Type* mutate(ArrayType *arrayType); 78 virtual Type* mutate(FunctionType *functionType); 79 virtual Type* mutate(StructInstType *aggregateUseType); 80 virtual Type* mutate(UnionInstType *aggregateUseType); 81 virtual Type* mutate(EnumInstType *aggregateUseType); 82 virtual Type* mutate(TraitInstType *aggregateUseType); 83 virtual Type* mutate(TupleType *tupleType); 84 virtual Type* mutate(VarArgsType *varArgsType); 85 virtual Type* mutate(ZeroType *zeroType); 86 virtual Type* mutate(OneType *oneType); 65 // Mutator that performs the substitution 66 struct Substituter; 87 67 88 68 // TODO: worry about traversing into a forall-qualified function type or type decl with assertions … … 97 77 typedef std::map< std::string, Type* > TypeEnvType; 98 78 typedef std::map< std::string, Expression* > VarEnvType; 99 typedef std::set< std::string > BoundVarsType;100 79 TypeEnvType typeEnv; 101 80 VarEnvType varEnv; 102 BoundVarsType boundVars;103 int subCount;104 bool freeOnly;105 81 }; 106 82 … … 134 110 135 111 template< typename FormalIterator, typename ActualIterator > 136 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) 137 { 112 TypeSubstitution::TypeSubstitution( FormalIterator formalBegin, FormalIterator formalEnd, ActualIterator actualBegin ) { 138 113 add( formalBegin, formalEnd, actualBegin ); 139 114 } 115 116 // include needs to happen after TypeSubstitution is defined so that both TypeSubstitution and 117 // PassVisitor are defined before PassVisitor implementation accesses TypeSubstitution internals. 118 #include "Common/PassVisitor.h" 119 120 // definitition must happen after PassVisitor is included so that WithGuards can be used 121 struct TypeSubstitution::Substituter : public WithGuards { 122 Substituter( TypeSubstitution & sub, bool freeOnly ) : sub( sub ), freeOnly( freeOnly ) {} 123 124 Type * postmutate( TypeInstType * aggregateUseType ); 125 Expression * postmutate( NameExpr * nameExpr ); 126 127 /// Records type variable bindings from forall-statements 128 void premutate( Type * type ); 129 /// Records type variable bindings from forall-statements and instantiations of generic types 130 template< typename TypeClass > void handleAggregateType( TypeClass * type ); 131 132 void premutate( StructInstType * aggregateUseType ); 133 void premutate( UnionInstType * aggregateUseType ); 134 135 TypeSubstitution & sub; 136 int subCount = 0; 137 bool freeOnly; 138 typedef std::set< std::string > BoundVarsType; 139 BoundVarsType boundVars; 140 }; 140 141 141 142 template< typename SynTreeClass > 142 143 int TypeSubstitution::apply( SynTreeClass *&input ) { 143 144 assert( input ); 144 subCount = 0; 145 freeOnly = false; 146 input = dynamic_cast< SynTreeClass *>( input->acceptMutator( *this ) ); 145 PassVisitor<Substituter> sub( *this, false ); 146 input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) ); 147 147 assert( input ); 148 /// std::c out<< "substitution result is: ";149 /// newType->print( std::c out);150 /// std::c out<< std::endl;151 return sub Count;148 /// std::cerr << "substitution result is: "; 149 /// newType->print( std::cerr ); 150 /// std::cerr << std::endl; 151 return sub.pass.subCount; 152 152 } 153 153 … … 155 155 int TypeSubstitution::applyFree( SynTreeClass *&input ) { 156 156 assert( input ); 157 subCount = 0; 158 freeOnly = true; 159 input = dynamic_cast< SynTreeClass *>( input->acceptMutator( *this ) ); 157 PassVisitor<Substituter> sub( *this, true ); 158 input = dynamic_cast< SynTreeClass * >( input->acceptMutator( sub ) ); 160 159 assert( input ); 161 /// std::c out<< "substitution result is: ";162 /// newType->print( std::c out);163 /// std::c out<< std::endl;164 return sub Count;160 /// std::cerr << "substitution result is: "; 161 /// newType->print( std::cerr ); 162 /// std::cerr << std::endl; 163 return sub.pass.subCount; 165 164 } 166 165 -
src/Tuples/TupleExpansion.cc
r2b72090 rbee7f04 36 36 namespace Tuples { 37 37 namespace { 38 struct MemberTupleExpander final : public Mutator { 39 typedef Mutator Parent; 40 using Parent::mutate; 41 42 virtual Expression * mutate( UntypedMemberExpr * memberExpr ) override; 38 struct MemberTupleExpander final : public WithShortCircuiting, public WithVisitorRef<MemberTupleExpander> { 39 void premutate( UntypedMemberExpr * ) { visit_children = false; } 40 Expression * postmutate( UntypedMemberExpr * memberExpr ); 43 41 }; 44 42 … … 79 77 80 78 void expandMemberTuples( std::list< Declaration * > & translationUnit ) { 81 MemberTupleExpanderexpander;79 PassVisitor<MemberTupleExpander> expander; 82 80 mutateAll( translationUnit, expander ); 83 81 } … … 109 107 // construct a new UntypedMemberExpr with the correct structure , and recursively 110 108 // expand that member expression. 111 MemberTupleExpanderexpander;112 UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr-> get_aggregate(), aggr->clone() );113 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr-> get_member(), inner );109 PassVisitor<MemberTupleExpander> expander; 110 UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr->aggregate, aggr->clone() ); 111 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member, inner ); 114 112 inner->location = newMemberExpr->location = loc; 115 memberExpr-> set_member(nullptr);116 memberExpr-> set_aggregate(nullptr);113 memberExpr->member = nullptr; 114 memberExpr->aggregate = nullptr; 117 115 delete memberExpr; 118 116 return newMemberExpr->acceptMutator( expander ); … … 126 124 } 127 125 128 Expression * MemberTupleExpander:: mutate( UntypedMemberExpr * memberExpr ) {129 if ( UntypedTupleExpr * tupleExpr = dynamic_cast< UntypedTupleExpr * > ( memberExpr-> get_member()) ) {130 Expression * aggr = memberExpr-> get_aggregate()->clone()->acceptMutator( *this);126 Expression * MemberTupleExpander::postmutate( UntypedMemberExpr * memberExpr ) { 127 if ( UntypedTupleExpr * tupleExpr = dynamic_cast< UntypedTupleExpr * > ( memberExpr->member ) ) { 128 Expression * aggr = memberExpr->aggregate->clone()->acceptMutator( *visitor ); 131 129 // aggregate expressions which might be impure must be wrapped in unique expressions 132 130 // xxx - if there's a member-tuple expression nested in the aggregate, this currently generates the wrong code if a UniqueExpr is not used, and it's purely an optimization to remove the UniqueExpr 133 131 // if ( Tuples::maybeImpureIgnoreUnique( memberExpr->get_aggregate() ) ) aggr = new UniqueExpr( aggr ); 134 132 aggr = new UniqueExpr( aggr ); 135 for ( Expression *& expr : tupleExpr-> get_exprs()) {133 for ( Expression *& expr : tupleExpr->exprs ) { 136 134 expr = reconstructMemberExpr( expr, aggr, memberExpr->location ); 137 135 expr->location = memberExpr->location; … … 143 141 // there may be a tuple expr buried in the aggregate 144 142 // xxx - this is a memory leak 145 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr-> get_member()->clone(), memberExpr->get_aggregate()->acceptMutator( *this) );143 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member->clone(), memberExpr->aggregate->acceptMutator( *visitor ) ); 146 144 newMemberExpr->location = memberExpr->location; 147 145 return newMemberExpr; -
src/tests/Makefile.am
r2b72090 rbee7f04 77 77 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} -o ${@} 78 78 79 dtor-early-exit-ERR1: dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@80 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}81 82 dtor-early-exit-ERR2: dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@83 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR2 ${<} -o ${@}84 85 79 declarationSpecifier: declarationSpecifier.c @CFA_BINDIR@/@CFA_NAME@ 86 80 ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@} … … 110 104 ${CC} ${AM_CFLAGS} ${CFLAGS} -lgmp ${<} -o ${@} 111 105 112 memberCtors-ERR1: memberCtors.c @CFA_BINDIR@/@CFA_NAME@113 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}114 115 ctor-autogen-ERR1: ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@116 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}117 118 106 completeTypeError : completeTypeError.c @CFA_BINDIR@/@CFA_NAME@ 119 107 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} … … 124 112 alloc-ERROR: alloc.c @CFA_BINDIR@/@CFA_NAME@ 125 113 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 114 115 # Constructor/destructor tests 116 raii/dtor-early-exit-ERR1: raii/dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@ 117 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 118 119 raii/dtor-early-exit-ERR2: raii/dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@ 120 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR2 ${<} -o ${@} 121 122 raii/memberCtors-ERR1: raii/memberCtors.c @CFA_BINDIR@/@CFA_NAME@ 123 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 124 125 raii/ctor-autogen-ERR1: raii/ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@ 126 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 127 -
src/tests/Makefile.in
r2b72090 rbee7f04 827 827 ${CC} ${AM_CFLAGS} ${CFLAGS} ${<} -o ${@} 828 828 829 dtor-early-exit-ERR1: dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@830 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}831 832 dtor-early-exit-ERR2: dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@833 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR2 ${<} -o ${@}834 835 829 declarationSpecifier: declarationSpecifier.c @CFA_BINDIR@/@CFA_NAME@ 836 830 ${CC} ${AM_CFLAGS} ${CFLAGS} -CFA -XCFA -p ${<} -o ${@} … … 860 854 ${CC} ${AM_CFLAGS} ${CFLAGS} -lgmp ${<} -o ${@} 861 855 862 memberCtors-ERR1: memberCtors.c @CFA_BINDIR@/@CFA_NAME@863 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}864 865 ctor-autogen-ERR1: ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@866 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@}867 868 856 completeTypeError : completeTypeError.c @CFA_BINDIR@/@CFA_NAME@ 869 857 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} … … 873 861 874 862 alloc-ERROR: alloc.c @CFA_BINDIR@/@CFA_NAME@ 863 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 864 865 # Constructor/destructor tests 866 raii/dtor-early-exit-ERR1: raii/dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@ 867 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 868 869 raii/dtor-early-exit-ERR2: raii/dtor-early-exit.c @CFA_BINDIR@/@CFA_NAME@ 870 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR2 ${<} -o ${@} 871 872 raii/memberCtors-ERR1: raii/memberCtors.c @CFA_BINDIR@/@CFA_NAME@ 873 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 874 875 raii/ctor-autogen-ERR1: raii/ctor-autogen.c @CFA_BINDIR@/@CFA_NAME@ 875 876 ${CC} ${AM_CFLAGS} ${CFLAGS} -DERR1 ${<} -o ${@} 876 877
Note:
See TracChangeset
for help on using the changeset viewer.