Changeset 58fe85a for src/Concurrency/Keywords.cc
- Timestamp:
- Jan 7, 2021, 3:27:00 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 2b4daf2, 64aeca0
- Parents:
- 3c64c668 (diff), eef8dfb (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Concurrency/Keywords.cc
r3c64c668 r58fe85a 16 16 #include "Concurrency/Keywords.h" 17 17 18 #include <cassert> // for assert 19 #include <string> // for string, operator== 20 21 #include "Common/PassVisitor.h" // for PassVisitor 22 #include "Common/SemanticError.h" // for SemanticError 23 #include "Common/utility.h" // for deleteAll, map_range 24 #include "CodeGen/OperatorTable.h" // for isConstructor 25 #include "InitTweak/InitTweak.h" // for getPointerBase 26 #include "SynTree/LinkageSpec.h" // for Cforall 27 #include "SynTree/Constant.h" // for Constant 28 #include "SynTree/Declaration.h" // for StructDecl, FunctionDecl, ObjectDecl 29 #include "SynTree/Expression.h" // for VariableExpr, ConstantExpr, Untype... 30 #include "SynTree/Initializer.h" // for SingleInit, ListInit, Initializer ... 31 #include "SynTree/Label.h" // for Label 32 #include "SynTree/Statement.h" // for CompoundStmt, DeclStmt, ExprStmt 33 #include "SynTree/Type.h" // for StructInstType, Type, PointerType 34 #include "SynTree/Visitor.h" // for Visitor, acceptAll 18 #include <cassert> // for assert 19 #include <string> // for string, operator== 20 21 #include <iostream> 22 23 #include "Common/Examine.h" // for isMainFor 24 #include "Common/PassVisitor.h" // for PassVisitor 25 #include "Common/SemanticError.h" // for SemanticError 26 #include "Common/utility.h" // for deleteAll, map_range 27 #include "CodeGen/OperatorTable.h" // for isConstructor 28 #include "ControlStruct/LabelGenerator.h" // for LebelGenerator 29 #include "InitTweak/InitTweak.h" // for getPointerBase 30 #include "SynTree/LinkageSpec.h" // for Cforall 31 #include "SynTree/Constant.h" // for Constant 32 #include "SynTree/Declaration.h" // for StructDecl, FunctionDecl, ObjectDecl 33 #include "SynTree/Expression.h" // for VariableExpr, ConstantExpr, Untype... 34 #include "SynTree/Initializer.h" // for SingleInit, ListInit, Initializer ... 35 #include "SynTree/Label.h" // for Label 36 #include "SynTree/Statement.h" // for CompoundStmt, DeclStmt, ExprStmt 37 #include "SynTree/Type.h" // for StructInstType, Type, PointerType 38 #include "SynTree/Visitor.h" // for Visitor, acceptAll 39 #include "Virtual/Tables.h" 35 40 36 41 class Attribute; 37 42 38 43 namespace Concurrency { 44 inline static std::string getVTableName( std::string const & exception_name ) { 45 return exception_name.empty() ? std::string() : Virtual::vtableTypeName(exception_name); 46 } 47 48 // Only detects threads constructed with the keyword thread. 49 inline static bool isThread( DeclarationWithType * decl ) { 50 Type * baseType = decl->get_type()->stripDeclarator(); 51 StructInstType * instType = dynamic_cast<StructInstType *>( baseType ); 52 if ( nullptr == instType ) { return false; } 53 return instType->baseStruct->is_thread(); 54 } 55 39 56 //============================================================================================= 40 57 // Pass declarations … … 53 70 public: 54 71 55 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, std::string&& getter_name, std::string&& context_error, bool needs_main, AggregateDecl::Aggregate cast_target ) : 56 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), context_error( context_error ), needs_main( needs_main ), cast_target( cast_target ) {} 72 ConcurrentSueKeyword( std::string&& type_name, std::string&& field_name, 73 std::string&& getter_name, std::string&& context_error, std::string&& exception_name, 74 bool needs_main, AggregateDecl::Aggregate cast_target ) : 75 type_name( type_name ), field_name( field_name ), getter_name( getter_name ), 76 context_error( context_error ), exception_name( exception_name ), 77 vtable_name( getVTableName( exception_name ) ), 78 needs_main( needs_main ), cast_target( cast_target ) {} 57 79 58 80 virtual ~ConcurrentSueKeyword() {} … … 62 84 63 85 void handle( StructDecl * ); 86 void addVtableForward( StructDecl * ); 64 87 FunctionDecl * forwardDeclare( StructDecl * ); 65 88 ObjectDecl * addField( StructDecl * ); … … 75 98 const std::string getter_name; 76 99 const std::string context_error; 100 const std::string exception_name; 101 const std::string vtable_name; 77 102 bool needs_main; 78 103 AggregateDecl::Aggregate cast_target; … … 80 105 StructDecl * type_decl = nullptr; 81 106 FunctionDecl * dtor_decl = nullptr; 107 StructDecl * except_decl = nullptr; 108 StructDecl * vtable_decl = nullptr; 82 109 }; 83 110 … … 100 127 "get_thread", 101 128 "thread keyword requires threads to be in scope, add #include <thread.hfa>\n", 129 "ThreadCancelled", 102 130 true, 103 131 AggregateDecl::Thread … … 132 160 "get_coroutine", 133 161 "coroutine keyword requires coroutines to be in scope, add #include <coroutine.hfa>\n", 162 "CoroutineCancelled", 134 163 true, 135 164 AggregateDecl::Coroutine … … 146 175 } 147 176 }; 177 178 148 179 149 180 //----------------------------------------------------------------------------- … … 164 195 "get_monitor", 165 196 "monitor keyword requires monitors to be in scope, add #include <monitor.hfa>\n", 197 "", 166 198 false, 167 199 AggregateDecl::Monitor … … 177 209 mutateAll( translationUnit, impl ); 178 210 } 211 }; 212 213 //----------------------------------------------------------------------------- 214 //Handles generator type declarations : 215 // generator MyGenerator { struct MyGenerator { 216 // int data; int data; 217 // a_struct_t more_data; a_struct_t more_data; 218 // => int __gen_next; 219 // }; }; 220 // 221 class GeneratorKeyword final : public ConcurrentSueKeyword { 222 public: 223 224 GeneratorKeyword() : ConcurrentSueKeyword( 225 "$generator", 226 "__generator_state", 227 "get_generator", 228 "Unable to find builtin type $generator\n", 229 "", 230 true, 231 AggregateDecl::Generator 232 ) 233 {} 234 235 virtual ~GeneratorKeyword() {} 236 237 virtual bool is_target( StructDecl * decl ) override final { return decl->is_generator(); } 238 239 static void implement( std::list< Declaration * > & translationUnit ) { 240 PassVisitor< GeneratorKeyword > impl; 241 mutateAll( translationUnit, impl ); 242 } 243 }; 244 245 246 //----------------------------------------------------------------------------- 247 class SuspendKeyword final : public WithStmtsToAdd, public WithGuards { 248 public: 249 SuspendKeyword() = default; 250 virtual ~SuspendKeyword() = default; 251 252 void premutate( FunctionDecl * ); 253 DeclarationWithType * postmutate( FunctionDecl * ); 254 255 Statement * postmutate( SuspendStmt * ); 256 257 static void implement( std::list< Declaration * > & translationUnit ) { 258 PassVisitor< SuspendKeyword > impl; 259 mutateAll( translationUnit, impl ); 260 } 261 262 private: 263 bool is_real_suspend( FunctionDecl * ); 264 265 Statement * make_generator_suspend( SuspendStmt * ); 266 Statement * make_coroutine_suspend( SuspendStmt * ); 267 268 struct LabelPair { 269 Label obj; 270 int idx; 271 }; 272 273 LabelPair make_label() { 274 labels.push_back( gen.newLabel("generator") ); 275 return { labels.back(), int(labels.size()) }; 276 } 277 278 DeclarationWithType * in_generator = nullptr; 279 FunctionDecl * decl_suspend = nullptr; 280 std::vector<Label> labels; 281 ControlStruct::LabelGenerator & gen = *ControlStruct::LabelGenerator::getGenerator(); 179 282 }; 180 283 … … 195 298 std::list<DeclarationWithType*> findMutexArgs( FunctionDecl*, bool & first ); 196 299 void validate( DeclarationWithType * ); 197 void addDtorStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &); 198 void addStatments( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &); 300 void addDtorStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &); 301 void addStatements( FunctionDecl* func, CompoundStmt *, const std::list<DeclarationWithType * > &); 302 void addThreadDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ); 199 303 200 304 static void implement( std::list< Declaration * > & translationUnit ) { … … 207 311 StructDecl* guard_decl = nullptr; 208 312 StructDecl* dtor_guard_decl = nullptr; 313 StructDecl* thread_guard_decl = nullptr; 209 314 210 315 static std::unique_ptr< Type > generic_func; … … 251 356 CoroutineKeyword ::implement( translationUnit ); 252 357 MonitorKeyword ::implement( translationUnit ); 358 GeneratorKeyword ::implement( translationUnit ); 359 SuspendKeyword ::implement( translationUnit ); 253 360 } 254 361 … … 283 390 handle( decl ); 284 391 } 392 else if ( !except_decl && exception_name == decl->name && decl->body ) { 393 except_decl = decl; 394 } 395 else if ( !vtable_decl && vtable_name == decl->name && decl->body ) { 396 vtable_decl = decl; 397 } 398 // Might be able to get ride of is target. 399 assert( is_target(decl) == (cast_target == decl->kind) ); 285 400 return decl; 286 401 } 287 402 288 403 DeclarationWithType * ConcurrentSueKeyword::postmutate( FunctionDecl * decl ) { 289 if( !type_decl ) return decl; 290 if( !CodeGen::isDestructor( decl->name ) ) return decl; 291 292 auto params = decl->type->parameters; 293 if( params.size() != 1 ) return decl; 294 295 auto type = dynamic_cast<ReferenceType*>( params.front()->get_type() ); 296 if( !type ) return decl; 297 298 auto stype = dynamic_cast<StructInstType*>( type->base ); 299 if( !stype ) return decl; 300 if( stype->baseStruct != type_decl ) return decl; 301 302 if( !dtor_decl ) dtor_decl = decl; 404 if ( type_decl && isDestructorFor( decl, type_decl ) ) 405 dtor_decl = decl; 406 else if ( vtable_name.empty() ) 407 ; 408 else if( !decl->has_body() ) 409 ; 410 else if ( auto param = isMainFor( decl, cast_target ) ) { 411 // This should never trigger. 412 assert( vtable_decl ); 413 // Should be safe because of isMainFor. 414 StructInstType * struct_type = static_cast<StructInstType *>( 415 static_cast<ReferenceType *>( param->get_type() )->base ); 416 assert( struct_type ); 417 418 std::list< Expression * > poly_args = { new TypeExpr( struct_type->clone() ) }; 419 ObjectDecl * vtable_object = Virtual::makeVtableInstance( 420 vtable_decl->makeInst( poly_args ), struct_type, nullptr ); 421 declsToAddAfter.push_back( vtable_object ); 422 declsToAddAfter.push_back( Virtual::makeGetExceptionFunction( 423 vtable_object, except_decl->makeInst( std::move( poly_args ) ) 424 ) ); 425 } 426 303 427 return decl; 304 428 } … … 324 448 if( !dtor_decl ) SemanticError( decl, context_error ); 325 449 450 addVtableForward( decl ); 326 451 FunctionDecl * func = forwardDeclare( decl ); 327 452 ObjectDecl * field = addField( decl ); 328 453 addRoutines( field, func ); 454 } 455 456 void ConcurrentSueKeyword::addVtableForward( StructDecl * decl ) { 457 if ( vtable_decl ) { 458 std::list< Expression * > poly_args = { 459 new TypeExpr( new StructInstType( noQualifiers, decl ) ), 460 }; 461 declsToAddBefore.push_back( Virtual::makeGetExceptionForward( 462 vtable_decl->makeInst( poly_args ), 463 except_decl->makeInst( poly_args ) 464 ) ); 465 declsToAddBefore.push_back( Virtual::makeVtableForward( 466 vtable_decl->makeInst( move( poly_args ) ) ) ); 467 // Its only an error if we want a vtable and don't have one. 468 } else if ( ! vtable_name.empty() ) { 469 SemanticError( decl, context_error ); 470 } 329 471 } 330 472 … … 434 576 new CastExpr( 435 577 new VariableExpr( func->get_functionType()->get_parameters().front() ), 436 func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone() 578 func->get_functionType()->get_parameters().front()->get_type()->stripReferences()->clone(), 579 false 437 580 ) 438 581 ) … … 446 589 447 590 declsToAddAfter.push_back( get_decl ); 448 449 // get_decl->fixUniqueId(); 450 } 591 } 592 593 //============================================================================================= 594 // Suspend keyword implementation 595 //============================================================================================= 596 bool SuspendKeyword::is_real_suspend( FunctionDecl * func ) { 597 if(isMangled(func->linkage)) return false; // the real suspend isn't mangled 598 if(func->name != "__cfactx_suspend") return false; // the real suspend has a specific name 599 if(func->type->parameters.size() != 0) return false; // Too many parameters 600 if(func->type->returnVals.size() != 0) return false; // Too many return values 601 602 return true; 603 } 604 605 void SuspendKeyword::premutate( FunctionDecl * func ) { 606 GuardValue(in_generator); 607 in_generator = nullptr; 608 609 // Is this the real suspend? 610 if(is_real_suspend(func)) { 611 decl_suspend = decl_suspend ? decl_suspend : func; 612 return; 613 } 614 615 // Is this the main of a generator? 616 auto param = isMainFor( func, AggregateDecl::Aggregate::Generator ); 617 if(!param) return; 618 619 if(func->type->returnVals.size() != 0) SemanticError(func->location, "Generator main must return void"); 620 621 in_generator = param; 622 GuardValue(labels); 623 labels.clear(); 624 } 625 626 DeclarationWithType * SuspendKeyword::postmutate( FunctionDecl * func ) { 627 if( !func->statements ) return func; // Not the actual definition, don't do anything 628 if( !in_generator ) return func; // Not in a generator, don't do anything 629 if( labels.empty() ) return func; // Generator has no states, nothing to do, could throw a warning 630 631 // This is a generator main, we need to add the following code to the top 632 // static void * __generator_labels[] = {&&s0, &&s1, ...}; 633 // goto * __generator_labels[gen.__generator_state]; 634 const auto & loc = func->location; 635 636 const auto first_label = gen.newLabel("generator"); 637 638 // for each label add to declaration 639 std::list<Initializer*> inits = { new SingleInit( new LabelAddressExpr( first_label ) ) }; 640 for(const auto & label : labels) { 641 inits.push_back( 642 new SingleInit( 643 new LabelAddressExpr( label ) 644 ) 645 ); 646 } 647 auto init = new ListInit(std::move(inits), noDesignators, true); 648 labels.clear(); 649 650 // create decl 651 auto decl = new ObjectDecl( 652 "__generator_labels", 653 Type::StorageClasses( Type::Static ), 654 LinkageSpec::AutoGen, 655 nullptr, 656 new ArrayType( 657 Type::Qualifiers(), 658 new PointerType( 659 Type::Qualifiers(), 660 new VoidType( Type::Qualifiers() ) 661 ), 662 nullptr, 663 false, false 664 ), 665 init 666 ); 667 668 // create the goto 669 assert(in_generator); 670 671 auto go_decl = new ObjectDecl( 672 "__generator_label", 673 noStorageClasses, 674 LinkageSpec::AutoGen, 675 nullptr, 676 new PointerType( 677 Type::Qualifiers(), 678 new VoidType( Type::Qualifiers() ) 679 ), 680 new SingleInit( 681 new UntypedExpr( 682 new NameExpr("?[?]"), 683 { 684 new NameExpr("__generator_labels"), 685 new UntypedMemberExpr( 686 new NameExpr("__generator_state"), 687 new VariableExpr( in_generator ) 688 ) 689 } 690 ) 691 ) 692 ); 693 go_decl->location = loc; 694 695 auto go = new BranchStmt( 696 new VariableExpr( go_decl ), 697 BranchStmt::Goto 698 ); 699 go->location = loc; 700 go->computedTarget->location = loc; 701 702 auto noop = new NullStmt({ first_label }); 703 noop->location = loc; 704 705 // wrap everything in a nice compound 706 auto body = new CompoundStmt({ 707 new DeclStmt( decl ), 708 new DeclStmt( go_decl ), 709 go, 710 noop, 711 func->statements 712 }); 713 body->location = loc; 714 func->statements = body; 715 716 return func; 717 } 718 719 Statement * SuspendKeyword::postmutate( SuspendStmt * stmt ) { 720 SuspendStmt::Type type = stmt->type; 721 if(type == SuspendStmt::None) { 722 // This suspend has a implicit target, find it 723 type = in_generator ? SuspendStmt::Generator : SuspendStmt::Coroutine; 724 } 725 726 // Check that the target makes sense 727 if(!in_generator && type == SuspendStmt::Generator) SemanticError( stmt->location, "'suspend generator' must be used inside main of generator type."); 728 729 // Act appropriately 730 switch(type) { 731 case SuspendStmt::Generator: return make_generator_suspend(stmt); 732 case SuspendStmt::Coroutine: return make_coroutine_suspend(stmt); 733 default: abort(); 734 } 735 } 736 737 Statement * SuspendKeyword::make_generator_suspend( SuspendStmt * stmt ) { 738 assert(in_generator); 739 // Target code is : 740 // gen.__generator_state = X; 741 // { THEN } 742 // return; 743 // __gen_X:; 744 745 // Save the location and delete the old statement, we only need the location from this point on 746 auto loc = stmt->location; 747 748 // Build the label and get its index 749 auto label = make_label(); 750 751 // Create the context saving statement 752 auto save = new ExprStmt( new UntypedExpr( 753 new NameExpr( "?=?" ), 754 { 755 new UntypedMemberExpr( 756 new NameExpr("__generator_state"), 757 new VariableExpr( in_generator ) 758 ), 759 new ConstantExpr( 760 Constant::from_int( label.idx ) 761 ) 762 } 763 )); 764 assert(save->expr); 765 save->location = loc; 766 stmtsToAddBefore.push_back( save ); 767 768 // if we have a then add it here 769 auto then = stmt->then; 770 stmt->then = nullptr; 771 delete stmt; 772 if(then) stmtsToAddBefore.push_back( then ); 773 774 // Create the return statement 775 auto ret = new ReturnStmt( nullptr ); 776 ret->location = loc; 777 stmtsToAddBefore.push_back( ret ); 778 779 // Create the null statement with the created label 780 auto noop = new NullStmt({ label.obj }); 781 noop->location = loc; 782 783 // Return the null statement to take the place of the previous statement 784 return noop; 785 } 786 787 Statement * SuspendKeyword::make_coroutine_suspend( SuspendStmt * stmt ) { 788 if(stmt->then) SemanticError( stmt->location, "Compound statement following coroutines is not implemented."); 789 790 // Save the location and delete the old statement, we only need the location from this point on 791 auto loc = stmt->location; 792 delete stmt; 793 794 // Create the call expression 795 if(!decl_suspend) SemanticError( loc, "suspend keyword applied to coroutines requires coroutines to be in scope, add #include <coroutine.hfa>\n"); 796 auto expr = new UntypedExpr( VariableExpr::functionPointer( decl_suspend ) ); 797 expr->location = loc; 798 799 // Change this statement into a regular expr 800 assert(expr); 801 auto nstmt = new ExprStmt( expr ); 802 nstmt->location = loc; 803 return nstmt; 804 } 805 451 806 452 807 //============================================================================================= … … 458 813 bool first = false; 459 814 std::list<DeclarationWithType*> mutexArgs = findMutexArgs( decl, first ); 460 bool isDtor = CodeGen::isDestructor( decl->name );815 bool const isDtor = CodeGen::isDestructor( decl->name ); 461 816 462 817 // Is this function relevant to monitors … … 506 861 507 862 // Instrument the body 508 if( isDtor ) { 509 addDtorStatments( decl, body, mutexArgs ); 863 if ( isDtor && isThread( mutexArgs.front() ) ) { 864 if( !thread_guard_decl ) { 865 SemanticError( decl, "thread destructor requires threads to be in scope, add #include <thread.hfa>\n" ); 866 } 867 addThreadDtorStatements( decl, body, mutexArgs ); 868 } 869 else if ( isDtor ) { 870 addDtorStatements( decl, body, mutexArgs ); 510 871 } 511 872 else { 512 addStat ments( decl, body, mutexArgs );873 addStatements( decl, body, mutexArgs ); 513 874 } 514 875 } … … 527 888 assert( !dtor_guard_decl ); 528 889 dtor_guard_decl = decl; 890 } 891 else if( decl->name == "thread_dtor_guard_t" && decl->body ) { 892 assert( !thread_guard_decl ); 893 thread_guard_decl = decl; 529 894 } 530 895 } … … 565 930 } 566 931 567 void MutexKeyword::addDtorStat ments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) {932 void MutexKeyword::addDtorStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) { 568 933 Type * arg_type = args.front()->get_type()->clone(); 569 934 arg_type->set_mutex( false ); … … 583 948 new SingleInit( new UntypedExpr( 584 949 new NameExpr( "get_monitor" ), 585 { new CastExpr( new VariableExpr( args.front() ), arg_type ) }950 { new CastExpr( new VariableExpr( args.front() ), arg_type, false ) } 586 951 )) 587 952 ); … … 604 969 { 605 970 new SingleInit( new AddressExpr( new VariableExpr( monitors ) ) ), 606 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) ) 971 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ), 972 new SingleInit( new ConstantExpr( Constant::from_bool( false ) ) ) 607 973 }, 608 974 noDesignators, … … 613 979 614 980 //$monitor * __monitors[] = { get_monitor(a), get_monitor(b) }; 615 body->push_front( new DeclStmt( monitors) ); 616 } 617 618 void MutexKeyword::addStatments( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) { 981 body->push_front( new DeclStmt( monitors ) ); 982 } 983 984 void MutexKeyword::addThreadDtorStatements( 985 FunctionDecl*, CompoundStmt * body, 986 const std::list<DeclarationWithType * > & args ) { 987 assert( args.size() == 1 ); 988 DeclarationWithType * arg = args.front(); 989 Type * arg_type = arg->get_type()->clone(); 990 assert( arg_type->get_mutex() ); 991 arg_type->set_mutex( false ); 992 993 // thread_dtor_guard_t __guard = { this, intptr( 0 ) }; 994 body->push_front( 995 new DeclStmt( new ObjectDecl( 996 "__guard", 997 noStorageClasses, 998 LinkageSpec::Cforall, 999 nullptr, 1000 new StructInstType( 1001 noQualifiers, 1002 thread_guard_decl 1003 ), 1004 new ListInit( 1005 { 1006 new SingleInit( new CastExpr( new VariableExpr( arg ), arg_type ) ), 1007 new SingleInit( new UntypedExpr( 1008 new NameExpr( "intptr" ), { 1009 new ConstantExpr( Constant::from_int( 0 ) ), 1010 } 1011 ) ), 1012 }, 1013 noDesignators, 1014 true 1015 ) 1016 )) 1017 ); 1018 } 1019 1020 void MutexKeyword::addStatements( FunctionDecl* func, CompoundStmt * body, const std::list<DeclarationWithType * > & args ) { 619 1021 ObjectDecl * monitors = new ObjectDecl( 620 1022 "__monitors", … … 641 1043 return new SingleInit( new UntypedExpr( 642 1044 new NameExpr( "get_monitor" ), 643 { new CastExpr( new VariableExpr( var ), type ) }1045 { new CastExpr( new VariableExpr( var ), type, false ) } 644 1046 ) ); 645 1047 }) … … 665 1067 new SingleInit( new VariableExpr( monitors ) ), 666 1068 new SingleInit( new ConstantExpr( Constant::from_ulong( args.size() ) ) ), 667 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone() ) )1069 new SingleInit( new CastExpr( new VariableExpr( func ), generic_func->clone(), false ) ) 668 1070 }, 669 1071 noDesignators, … … 727 1129 // tab-width: 4 // 728 1130 // End: // 1131
Note:
See TracChangeset
for help on using the changeset viewer.