Changes in src/InitTweak/FixInit.cc [03b812d2:79970ed]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r03b812d2 r79970ed 33 33 #include "GenPoly/PolyMutator.h" 34 34 #include "SynTree/AddStmtVisitor.h" 35 #include "CodeGen/GenType.h" // for warnings 35 36 36 37 bool ctordtorp = false; … … 174 175 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 175 176 }; 177 178 class WarnStructMembers : public Visitor { 179 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 ); 184 185 virtual void visit( FunctionDecl * funcDecl ); 186 187 virtual void visit( MemberExpr * memberExpr ); 188 virtual void visit( ApplicationExpr * appExpr ); 189 190 private: 191 void handleFirstParam( Expression * firstParam ); 192 193 FunctionDecl * function = 0; 194 std::set< DeclarationWithType * > unhandled; 195 ObjectDecl * thisParam = 0; 196 }; 176 197 } // namespace 177 198 … … 187 208 // FixCopyCtors must happen after FixInit, so that destructors are placed correctly 188 209 FixCopyCtors::fixCopyCtors( translationUnit ); 210 211 WarnStructMembers::warnings( translationUnit ); 189 212 } 190 213 … … 231 254 } 232 255 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 ); 260 } 261 } 262 233 263 Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) { 234 264 appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) ); … … 242 272 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 243 273 assert( ftype ); 244 if ( ( funcDecl->get_name() == "?{}"|| funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) {274 if ( (isConstructor( funcDecl->get_name() ) || funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) { 245 275 Type * t1 = ftype->get_parameters().front()->get_type(); 246 276 Type * t2 = ftype->get_parameters().back()->get_type(); … … 253 283 return appExpr; 254 284 } // if 255 } else if ( funcDecl->get_name() == "^?{}") {285 } else if ( isDestructor( funcDecl->get_name() ) ) { 256 286 // correctness: never copy construct arguments to a destructor 257 287 return appExpr; … … 670 700 } // switch 671 701 } 702 703 bool checkWarnings( FunctionDecl * funcDecl ) { 704 // only check for warnings if the current function is a user-defined 705 // constructor or destructor 706 if ( ! funcDecl ) return false; 707 if ( ! funcDecl->get_statements() ) return false; 708 return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() ); 709 } 710 711 void WarnStructMembers::visit( FunctionDecl * funcDecl ) { 712 WarnStructMembers old = *this; 713 *this = WarnStructMembers(); 714 715 function = funcDecl; 716 if ( checkWarnings( funcDecl ) ) { 717 FunctionType * type = funcDecl->get_functionType(); 718 assert( ! type->get_parameters().empty() ); 719 thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() ); 720 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( thisParam->get_type() ); 721 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() ); 722 if ( structType ) { 723 StructDecl * structDecl = structType->get_baseStruct(); 724 for ( Declaration * member : structDecl->get_members() ) { 725 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) { 726 // record all of the struct type's members that need to be constructed or 727 // destructed by the end of the function 728 unhandled.insert( field ); 729 } 730 } 731 } 732 } 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() ), ", member ", member->get_name(), " may not have been ", isConstructor( funcDecl->get_name() ) ? "constructed" : "destructed" ); 738 } 739 740 *this = old; 741 } 742 743 void WarnStructMembers::visit( ApplicationExpr * appExpr ) { 744 if ( ! checkWarnings( function ) ) return; 745 746 std::string fname = getFunctionName( appExpr ); 747 if ( fname == function->get_name() ) { 748 // call to same kind of function 749 Expression * firstParam = appExpr->get_args().front(); 750 751 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) { 752 // if calling another constructor on thisParam, assume that function handles 753 // all members - if it doesn't a warning will appear in that function. 754 if ( varExpr->get_var() == thisParam ) { 755 unhandled.clear(); 756 } 757 } else { 758 // if first parameter is a member expression then 759 // remove the member from unhandled set. 760 handleFirstParam( firstParam ); 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() ); 767 } 768 769 Parent::visit( appExpr ); 770 } 771 772 void WarnStructMembers::handleFirstParam( Expression * firstParam ) { 773 using namespace std; 774 if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) { 775 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) { 776 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 777 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 778 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 779 if ( varExpr->get_var() == thisParam ) { 780 unhandled.erase( memberExpr->get_member() ); 781 } 782 } 783 } 784 } 785 } 786 } 787 } 788 789 void WarnStructMembers::visit( MemberExpr * memberExpr ) { 790 if ( ! checkWarnings( function ) ) return; 791 if ( ! isConstructor( function->get_name() ) ); 792 793 if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) { 794 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) { 795 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) { 796 if ( varExpr->get_var() == thisParam ) { 797 if ( unhandled.count( memberExpr->get_member() ) ) { 798 // emit a warning because a member was used before it was constructed 799 warn( "in ", CodeGen::genType( function->get_functionType(), function->get_name() ), ", member ", memberExpr->get_member()->get_name(), " used before being constructed" ); 800 } 801 } 802 } 803 } 804 } 805 Parent::visit( memberExpr ); 806 } 672 807 } // namespace 673 808 } // namespace InitTweak
Note:
See TracChangeset
for help on using the changeset viewer.