Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r4618319 r62423350  
    2626#include "FixGlobalInit.h"
    2727#include "CodeGen/GenType.h"  // for warning/error messages
    28 #include "CodeGen/OperatorTable.h"
    2928#include "Common/PassVisitor.h"
    3029#include "GenPoly/DeclMutator.h"
     
    239238                        SemanticError errors;
    240239                  private:
     240                        void handleFirstParam( Expression * firstParam );
    241241                        template< typename... Params >
    242242                        void emit( CodeLocation, const Params &... params );
     
    363363                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    364364                                        assert( ftype );
    365                                         if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    366                                                 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
     365                                        if ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
     366                                                Type * t1 = ftype->get_parameters().front()->get_type();
    367367                                                Type * t2 = ftype->get_parameters().back()->get_type();
    368                                                 assert( t1 );
    369 
    370                                                 if ( ResolvExpr::typesCompatible( t1, t2, SymTab::Indexer() ) ) {
     368                                                PointerType * ptrType = safe_dynamic_cast< PointerType * > ( t1 );
     369
     370                                                if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
    371371                                                        // optimization: don't need to copy construct in order to call a copy constructor
    372372                                                        return appExpr;
    373373                                                } // if
    374                                         } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) {
     374                                        } else if ( isDestructor( funcDecl->get_name() ) ) {
    375375                                                // correctness: never copy construct arguments to a destructor
    376376                                                return appExpr;
     
    401401
    402402                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    403                         return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
     403                        return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    404404                }
    405405
     
    489489                                impCpCtorExpr->get_returnDecls().push_back( ret );
    490490                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    491                                 if ( ! dynamic_cast< ReferenceType * >( result ) ) {
     491                                if ( ! result->get_lvalue() ) {
    492492                                        // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    493493                                        destructRet( ret, impCpCtorExpr );
     
    975975                        if ( ! funcDecl ) return false;
    976976                        if ( ! funcDecl->get_statements() ) return false;
    977                         return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
     977                        return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
    978978                }
    979979
     
    992992
    993993                        function = funcDecl;
    994                         isCtor = CodeGen::isConstructor( function->get_name() );
     994                        isCtor = isConstructor( function->get_name() );
    995995                        if ( checkWarnings( function ) ) {
    996996                                FunctionType * type = function->get_functionType();
    997997                                assert( ! type->get_parameters().empty() );
    998998                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
    999                                 Type * thisType = getPointerBase( thisParam->get_type() );
    1000                                 StructInstType * structType = dynamic_cast< StructInstType * >( thisType );
     999                                PointerType * ptrType = safe_dynamic_cast< PointerType * > ( thisParam->get_type() );
     1000                                StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() );
    10011001                                if ( structType ) {
    10021002                                        structDecl = structType->get_baseStruct();
     
    10311031
    10321032                        if ( ! unhandled.empty() ) {
    1033                                 // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors
     1033                                // need to explicitly re-add function parameters in order to resolve copy constructors
    10341034                                enterScope();
    10351035                                maybeAccept( function->get_functionType(), *this );
     
    10461046                                        // insert and resolve default/copy constructor call for each field that's unhandled
    10471047                                        std::list< Statement * > stmt;
     1048                                        UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );
     1049
    10481050                                        Expression * arg2 = 0;
    10491051                                        if ( isCopyConstructor( function ) ) {
     
    10541056                                        }
    10551057                                        InitExpander srcParam( arg2 );
    1056                                         // cast away reference type and construct field.
    1057                                         Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() );
    1058                                         Expression * memberDest = new MemberExpr( field, thisExpr );
    1059                                         SymTab::genImplicitCall( srcParam, memberDest, function->get_name(), back_inserter( stmt ), field, isCtor );
     1058                                        SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor );
    10601059
    10611060                                        assert( stmt.size() <= 1 );
     
    10841083                }
    10851084
    1086                 /// true if expr is effectively just the 'this' parameter
    1087                 bool isThisExpression( Expression * expr, DeclarationWithType * thisParam ) {
    1088                         // TODO: there are more complicated ways to pass 'this' to a constructor, e.g. &*, *&, etc.
    1089                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
    1090                                 return varExpr->get_var() == thisParam;
    1091                         } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) {
    1092                                 return isThisExpression( castExpr->get_arg(), thisParam );
    1093                         }
    1094                         return false;
    1095                 }
    1096 
    1097                 /// returns a MemberExpr if expr is effectively just member access on the 'this' parameter, else nullptr
    1098                 MemberExpr * isThisMemberExpr( Expression * expr, DeclarationWithType * thisParam ) {
    1099                         if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
    1100                                 if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
    1101                                         return memberExpr;
    1102                                 }
    1103                         } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    1104                                 return isThisMemberExpr( castExpr->get_arg(), thisParam );
    1105                         }
    1106                         return nullptr;
    1107                 }
    1108 
    11091085                void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
    11101086                        if ( ! checkWarnings( function ) ) return;
     
    11151091                                Expression * firstParam = appExpr->get_args().front();
    11161092
    1117                                 if ( isThisExpression( firstParam, thisParam ) ) {
     1093                                if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {
    11181094                                        // if calling another constructor on thisParam, assume that function handles
    11191095                                        // all members - if it doesn't a warning will appear in that function.
    1120                                         unhandled.clear();
    1121                                 } else if ( MemberExpr * memberExpr = isThisMemberExpr( firstParam, thisParam ) ) {
    1122                                         // if first parameter is a member expression on the this parameter,
    1123                                         // then remove the member from unhandled set.
    1124                                         if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
    1125                                                 unhandled.erase( memberExpr->get_member() );
     1096                                        if ( varExpr->get_var() == thisParam ) {
     1097                                                unhandled.clear();
     1098                                        }
     1099                                } else {
     1100                                        // if first parameter is a member expression then
     1101                                        // remove the member from unhandled set.
     1102                                        handleFirstParam( firstParam );
     1103                                }
     1104                        }
     1105
     1106                        Parent::visit( appExpr );
     1107                }
     1108
     1109                void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
     1110                        using namespace std;
     1111                        if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
     1112                                if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) {
     1113                                        if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
     1114                                                if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
     1115                                                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
     1116                                                                if ( varExpr->get_var() == thisParam ) {
     1117                                                                        unhandled.erase( memberExpr->get_member() );
     1118                                                                }
     1119                                                        }
     1120                                                }
    11261121                                        }
    11271122                                }
    11281123                        }
    1129                         Parent::visit( appExpr );
    11301124                }
    11311125
     
    11341128                        if ( ! isCtor ) return;
    11351129
    1136                         if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
    1137                                 if ( unhandled.count( memberExpr->get_member() ) ) {
    1138                                         // emit a warning because a member was used before it was constructed
    1139                                         usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
     1130                        if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
     1131                                if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
     1132                                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
     1133                                                if ( varExpr->get_var() == thisParam ) {
     1134                                                        if ( unhandled.count( memberExpr->get_member() ) ) {
     1135                                                                // emit a warning because a member was used before it was constructed
     1136                                                                usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
     1137                                                        }
     1138                                                }
     1139                                        }
    11401140                                }
    11411141                        }
     
    11831183                        ctorExpr->set_callExpr( nullptr );
    11841184                        ctorExpr->set_env( nullptr );
     1185
     1186                        Expression *& firstArg = callExpr->get_args().front();
     1187                        UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) );
     1188                        assign->get_args().push_back( new VariableExpr( tmp ) );
     1189                        assign->get_args().push_back( firstArg );
     1190                        assign->set_result( ctorExpr->get_result()->clone() );
     1191                        firstArg = assign;
     1192
     1193                        CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) );
     1194                        commaExpr->set_env( env );
    11851195                        delete ctorExpr;
    1186 
    1187                         Expression *& firstArg = callExpr->get_args().front();
    1188 
    1189                         // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away.
    1190 
    1191                         // generate the type of assignment operator using the type of tmp minus any reference types
    1192                         Type * type = tmp->get_type()->stripReferences();
    1193                         FunctionType * ftype = SymTab::genAssignType( type );
    1194 
    1195                         // generate fake assignment decl and call it using &tmp and &firstArg
    1196                         // since tmp is guaranteed to be a reference and we want to assign pointers
    1197                         FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
    1198                         ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
    1199                         assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
    1200                         Expression * addrArg = new AddressExpr( firstArg );
    1201                         // if firstArg has type T&&, then &firstArg has type T*&.
    1202                         // Cast away the reference to a value type so that the argument
    1203                         // matches the assignment's parameter types
    1204                         if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
    1205                                 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
    1206                         }
    1207                         assign->get_args().push_back( addrArg );
    1208                         firstArg = new VariableExpr( tmp );
    1209 
    1210                         // for constructor expr:
    1211                         //   T x;
    1212                         //   x{};
    1213                         // results in:
    1214                         //   T x;
    1215                         //   T & tmp;
    1216                         //   &tmp = &x, ?{}(tmp), tmp
    1217                         CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    1218                         commaExpr->set_env( env );
    12191196                        return commaExpr;
    12201197                }
Note: See TracChangeset for help on using the changeset viewer.