Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r79970ed r03b812d2  
    3333#include "GenPoly/PolyMutator.h"
    3434#include "SynTree/AddStmtVisitor.h"
    35 #include "CodeGen/GenType.h"  // for warnings
    3635
    3736bool ctordtorp = false;
     
    175174                        virtual Expression * mutate( ImplicitCopyCtorExpr * impCpCtorExpr );
    176175                };
    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                 };
    197176        } // namespace
    198177
     
    208187                // FixCopyCtors must happen after FixInit, so that destructors are placed correctly
    209188                FixCopyCtors::fixCopyCtors( translationUnit );
    210 
    211                 WarnStructMembers::warnings( translationUnit );
    212189        }
    213190
     
    254231                }
    255232
    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 
    263233                Expression * InsertImplicitCalls::mutate( ApplicationExpr * appExpr ) {
    264234                        appExpr = dynamic_cast< ApplicationExpr * >( Mutator::mutate( appExpr ) );
     
    272242                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    273243                                        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 ) {
    275245                                                Type * t1 = ftype->get_parameters().front()->get_type();
    276246                                                Type * t2 = ftype->get_parameters().back()->get_type();
     
    283253                                                        return appExpr;
    284254                                                } // if
    285                                         } else if ( isDestructor( funcDecl->get_name() ) ) {
     255                                        } else if ( funcDecl->get_name() == "^?{}" ) {
    286256                                                // correctness: never copy construct arguments to a destructor
    287257                                                return appExpr;
     
    700670                        } // switch
    701671                }
    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                 }
    807672        } // namespace
    808673} // namespace InitTweak
Note: See TracChangeset for help on using the changeset viewer.