Changes in src/InitTweak/FixInit.cc [79970ed:03b812d2]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r79970ed r03b812d2 33 33 #include "GenPoly/PolyMutator.h" 34 34 #include "SynTree/AddStmtVisitor.h" 35 #include "CodeGen/GenType.h" // for warnings36 35 37 36 bool ctordtorp = false; … … 175 174 virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr ); 176 175 }; 177 178 class WarnStructMembers : public Visitor {179 public:180 typedef Visitor Parent;181 /// warn if a user-defined constructor or destructor is missing calls for182 /// a struct member or if a member is used before constructed183 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 };197 176 } // namespace 198 177 … … 208 187 // FixCopyCtors must happen after FixInit, so that destructors are placed correctly 209 188 FixCopyCtors::fixCopyCtors( translationUnit ); 210 211 WarnStructMembers::warnings( translationUnit );212 189 } 213 190 … … 254 231 } 255 232 256 void WarnStructMembers::warnings( std::list< Declaration * > & translationUnit ) {257 if ( true ) { // fix this condition to skip this pass if warnings aren't enabled258 WarnStructMembers warner;259 acceptAll( translationUnit, warner );260 }261 }262 263 233 Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) { 264 234 appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) ); … … 272 242 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 273 243 assert( ftype ); 274 if ( ( isConstructor( funcDecl->get_name() )|| funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) {244 if ( (funcDecl->get_name() == "?{}" || funcDecl->get_name() == "?=?") && ftype->get_parameters().size() == 2 ) { 275 245 Type * t1 = ftype->get_parameters().front()->get_type(); 276 246 Type * t2 = ftype->get_parameters().back()->get_type(); … … 283 253 return appExpr; 284 254 } // if 285 } else if ( isDestructor( funcDecl->get_name() )) {255 } else if ( funcDecl->get_name() == "^?{}" ) { 286 256 // correctness: never copy construct arguments to a destructor 287 257 return appExpr; … … 700 670 } // switch 701 671 } 702 703 bool checkWarnings( FunctionDecl * funcDecl ) {704 // only check for warnings if the current function is a user-defined705 // constructor or destructor706 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 or727 // destructed by the end of the function728 unhandled.insert( field );729 }730 }731 }732 }733 Parent::visit( funcDecl );734 735 for ( DeclarationWithType * member : unhandled ) {736 // emit a warning for each unhandled member737 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 function749 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 handles753 // 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 then759 // 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 constructors764 // 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 constructed799 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 }807 672 } // namespace 808 673 } // namespace InitTweak
Note:
See TracChangeset
for help on using the changeset viewer.