Changes in src/InitTweak/FixInit.cc [b16898e:486341f]
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (15 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
rb16898e r486341f 31 31 #include "SynTree/Mutator.h" 32 32 #include "SymTab/Indexer.h" 33 #include "SymTab/Autogen.h"34 33 #include "GenPoly/PolyMutator.h" 35 34 #include "SynTree/AddStmtVisitor.h" … … 177 176 }; 178 177 179 class GenStructMemberCalls : public SymTab::Indexer {178 class WarnStructMembers : public Visitor { 180 179 public: 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 ); 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 ); 186 184 187 185 virtual void visit( FunctionDecl * funcDecl ); … … 190 188 virtual void visit( ApplicationExpr * appExpr ); 191 189 192 SemanticError errors;193 190 private: 194 191 void handleFirstParam( Expression * firstParam ); 195 template< typename... Params >196 void emit( const Params &... params );197 192 198 193 FunctionDecl * function = 0; 199 std::set< DeclarationWithType * > unhandled , usedUninit;194 std::set< DeclarationWithType * > unhandled; 200 195 ObjectDecl * thisParam = 0; 201 bool isCtor = false; // true if current function is a constructor202 StructDecl * structDecl = 0;203 };204 205 // very simple resolver-like mutator class - used to206 // resolve UntypedExprs that are found within newly207 // generated constructor/destructor calls208 class MutatingResolver : public Mutator {209 public:210 MutatingResolver( SymTab::Indexer & indexer ) : indexer( indexer ) {}211 212 virtual DeclarationWithType* mutate( ObjectDecl *objectDecl );213 214 virtual Expression* mutate( UntypedExpr *untypedExpr );215 private:216 SymTab::Indexer & indexer;217 196 }; 218 197 } // namespace … … 230 209 FixCopyCtors::fixCopyCtors( translationUnit ); 231 210 232 GenStructMemberCalls::generate( translationUnit );211 WarnStructMembers::warnings( translationUnit ); 233 212 } 234 213 … … 275 254 } 276 255 277 void GenStructMemberCalls::generate( std::list< Declaration * > & translationUnit ) { 278 GenStructMemberCalls warner; 279 acceptAll( translationUnit, warner ); 280 281 // visitor doesn't throw so that it can collect all errors 282 if ( ! warner.errors.isEmpty() ) { 283 throw warner.errors; 256 void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) { 257 if ( true ) { // fix this condition to skip this pass if warnings aren't enabled 258 WarnStructMembers warner; 259 acceptAll( translationUnit, warner ); 284 260 } 285 261 } … … 552 528 FunctionDecl * dtorCaller = new FunctionDecl( objDecl->get_mangleName() + dtorCallerNamer.newName(), DeclarationNode::Static, LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt( noLabels ), false, false ); 553 529 dtorCaller->fixUniqueId(); 554 dtorCaller->get_statements()-> push_back( dtorStmt );530 dtorCaller->get_statements()->get_kids().push_back( dtorStmt ); 555 531 556 532 // atexit(dtor_atexit); … … 567 543 // at global scope and there could be multiple function-scoped 568 544 // static variables with the same name in different functions. 569 // Note: it isn't sufficient to modify only the mangleName, because570 // then subsequent Indexer passes can choke on seeing the object's name571 // if another object has the same name and type. An unfortunate side-effect572 // of renaming the object is that subsequent NameExprs may fail to resolve,573 // but there shouldn't be any remaining past this point.574 545 static UniqueName staticNamer( "_static_var" ); 575 objDecl->set_name( objDecl->get_name() + staticNamer.newName() ); 576 objDecl->set_mangleName( SymTab::Mangler::mangle( objDecl ) ); 546 objDecl->set_mangleName( objDecl->get_mangleName() + staticNamer.newName() ); 577 547 578 548 objDecl->set_init( NULL ); … … 739 709 } 740 710 741 void GenStructMemberCalls::visit( FunctionDecl * funcDecl ) { 742 ValueGuard< FunctionDecl * > oldFunction( funcDecl ); 743 ValueGuard< std::set< DeclarationWithType * > > oldUnhandled( unhandled ); 744 ValueGuard< std::set< DeclarationWithType * > > oldUsedUninit( usedUninit ); 745 ValueGuard< ObjectDecl * > oldThisParam( thisParam ); 746 ValueGuard< bool > oldIsCtor( isCtor ); 747 ValueGuard< StructDecl * > oldStructDecl( structDecl ); 748 749 // need to start with fresh sets 750 unhandled.clear(); 751 usedUninit.clear(); 711 void WarnStructMembers::visit( FunctionDecl * funcDecl ) { 712 WarnStructMembers old = *this; 713 *this = WarnStructMembers(); 752 714 753 715 function = funcDecl; 754 isCtor = isConstructor( function->get_name() ); 755 if ( checkWarnings( function ) ) { 756 FunctionType * type = function->get_functionType(); 716 if ( checkWarnings( funcDecl ) ) { 717 FunctionType * type = funcDecl->get_functionType(); 757 718 assert( ! type->get_parameters().empty() ); 758 719 thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() ); … … 760 721 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() ); 761 722 if ( structType ) { 762 structDecl = structType->get_baseStruct();723 StructDecl * structDecl = structType->get_baseStruct(); 763 724 for ( Declaration * member : structDecl->get_members() ) { 764 725 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { … … 770 731 } 771 732 } 772 Parent::visit( function ); 773 774 // remove the unhandled objects from usedUninit, because a call is inserted 775 // to handle them - only objects that are later constructed are used uninitialized. 776 std::set< DeclarationWithType * > diff; 777 std::set_difference( usedUninit.begin(), usedUninit.end(), unhandled.begin(), unhandled.end(), std::inserter( diff, diff.begin() ) ); 778 for ( DeclarationWithType * member : diff ) { 779 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", field ", member->get_name(), " used before being constructed" ); 733 Parent::visit( funcDecl ); 734 735 for ( DeclarationWithType * member : unhandled ) { 736 // emit a warning for each unhandled member 737 warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" ); 780 738 } 781 739 782 if ( ! unhandled.empty() ) { 783 // need to explicitly re-add function parameters in order to resolve copy constructors 784 enterScope(); 785 maybeAccept( function->get_functionType(), *this ); 786 787 // need to iterate through members in reverse in order for 788 // ctor/dtor statements to come out in the right order 789 for ( Declaration * member : reverseIterate( structDecl->get_members() ) ) { 790 DeclarationWithType * field = dynamic_cast< DeclarationWithType * >( member ); 791 // skip non-DWT members 792 if ( ! field ) continue; 793 // skip handled members 794 if ( ! unhandled.count( field ) ) continue; 795 796 // insert and resolve default/copy constructor call for each field that's unhandled 797 std::list< Statement * > stmt; 798 UntypedExpr * deref = new UntypedExpr( new NameExpr( "*?" ) ); 799 deref->get_args().push_back( new VariableExpr( thisParam ) ); 800 801 Expression * arg2 = 0; 802 if ( isCopyConstructor( function ) ) { 803 // if copy ctor, need to pass second-param-of-this-function.field 804 std::list< DeclarationWithType * > & params = function->get_functionType()->get_parameters(); 805 assert( params.size() == 2 ); 806 arg2 = new MemberExpr( field, new VariableExpr( params.back() ) ); 807 } 808 InitExpander srcParam( arg2 ); 809 SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor ); 810 811 assert( stmt.size() <= 1 ); 812 if ( stmt.size() == 1 ) { 813 Statement * callStmt = stmt.front(); 814 815 MutatingResolver resolver( *this ); 816 try { 817 callStmt->acceptMutator( resolver ); 818 if ( isCtor ) { 819 function->get_statements()->push_front( callStmt ); 820 } else { 821 // destructor statements should be added at the end 822 function->get_statements()->push_back( callStmt ); 823 } 824 } catch ( SemanticError & error ) { 825 emit( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", field ", field->get_name(), " not explicitly ", isCtor ? "constructed" : "destructed", " and no ", isCtor ? "default constructor" : "destructor", " found" ); 826 } 827 } 828 } 829 leaveScope(); 830 } 831 } 832 833 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 740 *this = old; 741 } 742 743 void WarnStructMembers::visit( ApplicationExpr * appExpr ) { 834 744 if ( ! checkWarnings( function ) ) return; 835 745 … … 850 760 handleFirstParam( firstParam ); 851 761 } 762 } else if ( fname == "?=?" && isIntrinsicCallExpr( appExpr ) ) { 763 // forgive use of intrinsic assignment to construct, since instrinsic constructors 764 // codegen as assignment anyway. 765 assert( appExpr->get_args().size() == 2 ); 766 handleFirstParam( appExpr->get_args().front() ); 852 767 } 853 768 … … 855 770 } 856 771 857 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {772 void WarnStructMembers::handleFirstParam( Expression * firstParam ) { 858 773 using namespace std; 859 774 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) { … … 872 787 } 873 788 874 void GenStructMemberCalls::visit( MemberExpr * memberExpr ) {789 void WarnStructMembers::visit( MemberExpr * memberExpr ) { 875 790 if ( ! checkWarnings( function ) ) return; 876 if ( ! isC tor) return;791 if ( ! isConstructor( function->get_name() ) ) return; 877 792 878 793 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { … … 882 797 if ( unhandled.count( memberExpr->get_member() ) ) { 883 798 // emit a warning because a member was used before it was constructed 884 usedUninit.insert( memberExpr->get_member());799 warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name(), false ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" ); 885 800 } 886 801 } … … 890 805 Parent::visit( memberExpr ); 891 806 } 892 893 template< typename Visitor, typename... Params >894 void error( Visitor & v, const Params &... params ) {895 v.errors.append( toString( params... ) );896 }897 898 template< typename... Params >899 void GenStructMemberCalls::emit( const Params &... params ) {900 // toggle warnings vs. errors here.901 // warn( params... );902 error( *this, params... );903 }904 905 DeclarationWithType * MutatingResolver::mutate( ObjectDecl *objectDecl ) {906 // add object to the indexer assumes that there will be no name collisions907 // in generated code. If this changes, add mutate methods for entities with908 // scope and call {enter,leave}Scope explicitly.909 objectDecl->accept( indexer );910 return objectDecl;911 }912 913 Expression* MutatingResolver::mutate( UntypedExpr *untypedExpr ) {914 return safe_dynamic_cast< ApplicationExpr * >( ResolvExpr::findVoidExpression( untypedExpr, indexer ) );915 }916 807 } // namespace 917 808 } // namespace InitTweak
Note:
See TracChangeset
for help on using the changeset viewer.