Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r62423350 r4618319  
    2626#include "FixGlobalInit.h"
    2727#include "CodeGen/GenType.h"  // for warning/error messages
     28#include "CodeGen/OperatorTable.h"
    2829#include "Common/PassVisitor.h"
    2930#include "GenPoly/DeclMutator.h"
     
    238239                        SemanticError errors;
    239240                  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 ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    366                                                 Type * t1 = ftype->get_parameters().front()->get_type();
     365                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
     366                                                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    367367                                                Type * t2 = ftype->get_parameters().back()->get_type();
    368                                                 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( t1 );
    369 
    370                                                 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     368                                                assert( t1 );
     369
     370                                                if ( ResolvExpr::typesCompatible( t1, 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 ( isDestructor( funcDecl->get_name() ) ) {
     374                                        } else if ( CodeGen::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 ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
     403                        return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( 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 ( ! result->get_lvalue() ) {
     491                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    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 isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
     977                        return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
    978978                }
    979979
     
    992992
    993993                        function = funcDecl;
    994                         isCtor = isConstructor( function->get_name() );
     994                        isCtor = CodeGen::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                                 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( thisParam->get_type() );
    1000                                 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() );
     999                                Type * thisType = getPointerBase( thisParam->get_type() );
     1000                                StructInstType * structType = dynamic_cast< StructInstType * >( thisType );
    10011001                                if ( structType ) {
    10021002                                        structDecl = structType->get_baseStruct();
     
    10311031
    10321032                        if ( ! unhandled.empty() ) {
    1033                                 // need to explicitly re-add function parameters in order to resolve copy constructors
     1033                                // need to explicitly re-add function parameters to the indexer 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 
    10501048                                        Expression * arg2 = 0;
    10511049                                        if ( isCopyConstructor( function ) ) {
     
    10561054                                        }
    10571055                                        InitExpander srcParam( arg2 );
    1058                                         SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor );
     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 );
    10591060
    10601061                                        assert( stmt.size() <= 1 );
     
    10831084                }
    10841085
     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
    10851109                void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
    10861110                        if ( ! checkWarnings( function ) ) return;
     
    10911115                                Expression * firstParam = appExpr->get_args().front();
    10921116
    1093                                 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {
     1117                                if ( isThisExpression( firstParam, thisParam ) ) {
    10941118                                        // if calling another constructor on thisParam, assume that function handles
    10951119                                        // all members - if it doesn't a warning will appear in that function.
    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                                                 }
     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() );
    11211126                                        }
    11221127                                }
    11231128                        }
     1129                        Parent::visit( appExpr );
    11241130                }
    11251131
     
    11281134                        if ( ! isCtor ) return;
    11291135
    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                                         }
     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 } );
    11401140                                }
    11411141                        }
     
    11831183                        ctorExpr->set_callExpr( nullptr );
    11841184                        ctorExpr->set_env( nullptr );
     1185                        delete ctorExpr;
    11851186
    11861187                        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 ) );
     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 ) ) );
    11941218                        commaExpr->set_env( env );
    1195                         delete ctorExpr;
    11961219                        return commaExpr;
    11971220                }
Note: See TracChangeset for help on using the changeset viewer.