Changeset c8dfcd3 for src/InitTweak
- Timestamp:
- Aug 30, 2016, 5:15:34 PM (8 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, ctor, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- fba44f8
- Parents:
- fa463f1
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
rfa463f1 rc8dfcd3 31 31 #include "SynTree/Mutator.h" 32 32 #include "SymTab/Indexer.h" 33 #include "SymTab/Autogen.h" 33 34 #include "GenPoly/PolyMutator.h" 34 35 #include "SynTree/AddStmtVisitor.h" … … 176 177 }; 177 178 178 class WarnStructMembers : public Visitor {179 class GenStructMemberCalls : public SymTab::Indexer { 179 180 public: 180 typedef Visitor Parent; 181 /// warn if a user-defined constructor or destructor is missing calls for 182 /// a struct member or if a member is used before constructed 183 static void warnings( std::list< Declaration * > & translationUnit ); 181 typedef Indexer Parent; 182 /// generate default/copy ctor and dtor calls for user-defined struct ctor/dtors 183 /// for any member that is missing a corresponding ctor/dtor call. 184 /// error if a member is used before constructed 185 static void generate( std::list< Declaration * > & translationUnit ); 184 186 185 187 virtual void visit( FunctionDecl * funcDecl ); … … 195 197 196 198 FunctionDecl * function = 0; 197 std::set< DeclarationWithType * > unhandled ;199 std::set< DeclarationWithType * > unhandled, usedUninit; 198 200 ObjectDecl * thisParam = 0; 201 bool isCtor = false; // true if current function is a constructor 202 }; 203 204 // very simple resolver-like mutator class - used to 205 // resolve UntypedExprs that are found within newly 206 // generated constructor/destructor calls 207 class MutatingResolver : public Mutator { 208 public: 209 MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {} 210 211 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl ); 212 213 virtual Expression* mutate( UntypedExpr *untypedExpr ); 214 private: 215 SymTab::Indexer & indexer; 199 216 }; 200 217 } // namespace … … 212 229 FixCopyCtors::fixCopyCtors( translationUnit ); 213 230 214 WarnStructMembers::warnings( translationUnit );231 GenStructMemberCalls::generate( translationUnit ); 215 232 } 216 233 … … 257 274 } 258 275 259 void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) { 260 if ( true ) { // fix this condition to skip this pass if warnings aren't enabled 261 WarnStructMembers warner; 262 acceptAll( translationUnit, warner ); 263 264 // visitor doesn't throw so that it can collect all errors 265 if ( ! warner.errors.isEmpty() ) { 266 throw warner.errors; 267 } 276 void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) { 277 GenStructMemberCalls warner; 278 acceptAll( translationUnit, warner ); 279 280 // visitor doesn't throw so that it can collect all errors 281 if ( ! warner.errors.isEmpty() ) { 282 throw warner.errors; 268 283 } 269 284 } … … 536 551 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false ); 537 552 dtorCaller->fixUniqueId(); 538 dtorCaller->get_statements()-> get_kids().push_back( dtorStmt );553 dtorCaller->get_statements()->push_back( dtorStmt ); 539 554 540 555 // atexit(dtor_atexit); … … 551 566 // at global scope and there could be multiple function-scoped 552 567 // static variables with the same name in different functions. 568 // Note: it isn't sufficient to modify only the mangleName, because 569 // then subsequent Indexer passes can choke on seeing the object's name 570 // if another object has the same name and type. An unfortunate side-effect 571 // of renaming the object is that subsequent NameExprs may fail to resolve, 572 // but there shouldn't be any remaining past this point. 553 573 static UniqueName staticNamer( "_static_var" ); 554 objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() ); 574 objDecl->set_name( objDecl->get_name() + staticNamer.newName() ); 575 objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) ); 555 576 556 577 objDecl->set_init( NULL ); … … 717 738 } 718 739 719 void WarnStructMembers::visit( FunctionDecl * funcDecl ) { 720 WarnStructMembers old = *this; 721 *this = WarnStructMembers(); 740 void GenStructMemberCalls::visit( FunctionDecl * funcDecl ) { 741 ValueGuard< FunctionDecl * > oldFunction( funcDecl ); 742 ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled ); 743 ValueGuard< std::set< DeclarationWithType * > > oldUsedUninit( usedUninit ); 744 ValueGuard< ObjectDecl * > oldThisParam( thisParam ); 745 ValueGuard< bool > oldIsCtor( isCtor ); 746 747 // need to start with fresh sets 748 unhandled.clear(); 749 usedUninit.clear(); 722 750 723 751 function = funcDecl; 724 if ( checkWarnings( funcDecl ) ) { 725 FunctionType * type = funcDecl->get_functionType(); 752 isCtor = isConstructor( function->get_name() ); 753 if ( checkWarnings( function ) ) { 754 FunctionType * type = function->get_functionType(); 726 755 assert( ! type->get_parameters().empty() ); 727 756 thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() ); … … 739 768 } 740 769 } 741 Parent::visit( funcDecl ); 742 743 for ( DeclarationWithType * member : unhandled ) { 744 // emit a warning for each unhandled member 745 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" ); 770 Parent::visit( function ); 771 772 // remove the unhandled objects from usedUninit, because a call is inserted 773 // to handle them - only objects that are later constructed are used uninitialized. 774 std::set< DeclarationWithType * > diff; 775 std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ) ); 776 for ( DeclarationWithType * member : diff ) { 777 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " used before being constructed" ); 746 778 } 747 779 748 // need to steal the errors before they're lost 749 old.errors.append( errors ); 750 *this = old; 751 } 752 753 void WarnStructMembers::visit( ApplicationExpr * appExpr ) { 780 if ( ! unhandled.empty() ) { 781 // need to explicitly re-add function parameters in order to resolve copy constructors 782 enterScope(); 783 // maybeAccept( function->get_functionType(), *this ); 784 for ( DeclarationWithType * member : unhandled ) { 785 // insert and resolve default/copy constructor call for each member that's unhandled 786 std::list< Statement * > stmt; 787 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 788 deref->get_args().push_back( new VariableExpr( thisParam ) ); 789 InitExpander srcParam( (Initializer *)NULL ); // xxx - if copy ctor, need to pass appropriate argument - second param of this function dot member 790 SymTab::genImplicitCall( srcParam, new MemberExpr( member, deref ), function->get_name(), back_inserter( stmt ), member, isCtor ); 791 792 assert( stmt.size() <= 1 ); 793 if ( stmt.size() == 1 ) { 794 Statement * callStmt = stmt.front(); 795 796 MutatingResolver resolver( *this ); 797 try { 798 // xxx - these should be in field declaration order 799 callStmt->acceptMutator( resolver ); 800 if ( isCtor ) { 801 function->get_statements()->push_front( callStmt ); 802 } else { 803 // destructor statements should be added at the end 804 function->get_statements()->push_back( callStmt ); 805 } 806 } catch ( SemanticError & error ) { 807 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed", " and no ", isCtor ? "default constructor" : "destructor", " found" ); 808 } 809 } 810 } 811 leaveScope(); 812 } 813 } 814 815 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 754 816 if ( ! checkWarnings( function ) ) return; 755 817 … … 780 842 } 781 843 782 void WarnStructMembers::handleFirstParam( Expression * firstParam ) {844 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) { 783 845 using namespace std; 784 846 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) { … … 797 859 } 798 860 799 void WarnStructMembers::visit( MemberExpr * memberExpr ) {861 void GenStructMemberCalls::visit( MemberExpr * memberExpr ) { 800 862 if ( ! checkWarnings( function ) ) return; 801 if ( ! isC onstructor( function->get_name() )) return;863 if ( ! isCtor ) return; 802 864 803 865 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { … … 807 869 if ( unhandled.count( memberExpr->get_member() ) ) { 808 870 // emit a warning because a member was used before it was constructed 809 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed");871 usedUninit.insert( memberExpr->get_member() ); 810 872 } 811 873 } … … 822 884 823 885 template< typename... Params > 824 void WarnStructMembers::emit( const Params &... params ) {886 void GenStructMemberCalls::emit( const Params &... params ) { 825 887 // toggle warnings vs. errors here. 826 888 // warn( params... ); 827 889 error( *this, params... ); 890 } 891 892 DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) { 893 // add object to the indexer assumes that there will be no name collisions 894 // in generated code. If this changes, add mutate methods for entities with 895 // scope and call {enter,leave}Scope explicitly. 896 objectDecl->accept( indexer ); 897 return objectDecl; 898 } 899 900 Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) { 901 return safe_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) ); 828 902 } 829 903 } // namespace
Note: See TracChangeset
for help on using the changeset viewer.