Ignore:
Timestamp:
Aug 25, 2017, 10:38:34 AM (7 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
Children:
800d275
Parents:
af08051 (diff), 3eab308c (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    raf08051 r28e58fd  
    2929
    3030#include "CodeGen/GenType.h"           // for genPrettyType
     31#include "CodeGen/OperatorTable.h"
    3132#include "Common/PassVisitor.h"        // for PassVisitor, WithStmtsToAdd
    3233#include "Common/SemanticError.h"      // for SemanticError
     
    254255                        SemanticError errors;
    255256                  private:
    256                         void handleFirstParam( Expression * firstParam );
    257257                        template< typename... Params >
    258258                        void emit( CodeLocation, const Params &... params );
     
    379379                                        FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) );
    380380                                        assert( ftype );
    381                                         if ( isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
    382                                                 Type * t1 = ftype->get_parameters().front()->get_type();
     381                                        if ( CodeGen::isConstructor( funcDecl->get_name() ) && ftype->get_parameters().size() == 2 ) {
     382                                                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    383383                                                Type * t2 = ftype->get_parameters().back()->get_type();
    384                                                 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( t1 );
    385 
    386                                                 if ( ResolvExpr::typesCompatible( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     384                                                assert( t1 );
     385
     386                                                if ( ResolvExpr::typesCompatible( t1, t2, SymTab::Indexer() ) ) {
    387387                                                        // optimization: don't need to copy construct in order to call a copy constructor
    388388                                                        return appExpr;
    389389                                                } // if
    390                                         } else if ( isDestructor( funcDecl->get_name() ) ) {
     390                                        } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) {
    391391                                                // correctness: never copy construct arguments to a destructor
    392392                                                return appExpr;
     
    417417
    418418                bool ResolveCopyCtors::skipCopyConstruct( Type * type ) {
    419                         return dynamic_cast< VarArgsType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
     419                        return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( type ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );
    420420                }
    421421
     
    505505                                impCpCtorExpr->get_returnDecls().push_back( ret );
    506506                                CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; )
    507                                 if ( ! result->get_lvalue() ) {
     507                                if ( ! dynamic_cast< ReferenceType * >( result ) ) {
    508508                                        // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary
    509509                                        destructRet( ret, impCpCtorExpr );
     
    607607
    608608                                Expression * retExpr = new CommaExpr( assign, new VariableExpr( returnDecl ) );
    609                                 if ( callExpr->get_result()->get_lvalue() ) {
    610                                         // lvalue returning functions are funny. Lvalue.cc inserts a *? in front of any lvalue returning
    611                                         // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the
    612                                         // type of the return temporary from T to T* to properly capture the return value. Then dereference
    613                                         // the result of the comma expression, since the lvalue returning call was originally wrapped with
    614                                         // an AddressExpr.  Effectively, this turns
    615                                         //   lvalue T f();
    616                                         //   &*f();
    617                                         // into
    618                                         //   T * f();
    619                                         //   T * tmp_cp_retN;
    620                                         //   &*(tmp_cp_retN = &*f(), tmp_cp_retN);              // the first * and second & are generated here
    621                                         // which work out in terms of types, but is pretty messy. It would be nice to find a better way.
    622                                         assign->get_args().back() = new AddressExpr( assign->get_args().back() );
    623 
    624                                         returnDecl->set_type( new PointerType( Type::Qualifiers(), returnDecl->get_type() ) );
    625                                         retExpr->set_result( new PointerType( Type::Qualifiers(), retExpr->get_result() ) );
    626                                         retExpr = UntypedExpr::createDeref( retExpr );
    627                                 } // if
    628609                                // move env from callExpr to retExpr
    629610                                retExpr->set_env( callExpr->get_env() );
     
    991972                        if ( ! funcDecl ) return false;
    992973                        if ( ! funcDecl->get_statements() ) return false;
    993                         return isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
     974                        return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );
    994975                }
    995976
     
    1008989
    1009990                        function = funcDecl;
    1010                         isCtor = isConstructor( function->get_name() );
     991                        isCtor = CodeGen::isConstructor( function->get_name() );
    1011992                        if ( checkWarnings( function ) ) {
    1012993                                FunctionType * type = function->get_functionType();
    1013994                                assert( ! type->get_parameters().empty() );
    1014995                                thisParam = safe_dynamic_cast< ObjectDecl * >( type->get_parameters().front() );
    1015                                 PointerType * ptrType = safe_dynamic_cast< PointerType * > ( thisParam->get_type() );
    1016                                 StructInstType * structType = dynamic_cast< StructInstType * >( ptrType->get_base() );
     996                                Type * thisType = getPointerBase( thisParam->get_type() );
     997                                StructInstType * structType = dynamic_cast< StructInstType * >( thisType );
    1017998                                if ( structType ) {
    1018999                                        structDecl = structType->get_baseStruct();
     
    10471028
    10481029                        if ( ! unhandled.empty() ) {
    1049                                 // need to explicitly re-add function parameters in order to resolve copy constructors
     1030                                // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors
    10501031                                enterScope();
    10511032                                maybeAccept( function->get_functionType(), *this );
     
    10621043                                        // insert and resolve default/copy constructor call for each field that's unhandled
    10631044                                        std::list< Statement * > stmt;
    1064                                         UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );
    1065 
    10661045                                        Expression * arg2 = 0;
    10671046                                        if ( isCopyConstructor( function ) ) {
     
    10721051                                        }
    10731052                                        InitExpander srcParam( arg2 );
    1074                                         SymTab::genImplicitCall( srcParam, new MemberExpr( field, deref ), function->get_name(), back_inserter( stmt ), field, isCtor );
     1053                                        // cast away reference type and construct field.
     1054                                        Expression * thisExpr = new CastExpr( new VariableExpr( thisParam ), thisParam->get_type()->stripReferences()->clone() );
     1055                                        Expression * memberDest = new MemberExpr( field, thisExpr );
     1056                                        SymTab::genImplicitCall( srcParam, memberDest, function->get_name(), back_inserter( stmt ), field, isCtor );
    10751057
    10761058                                        assert( stmt.size() <= 1 );
     
    10991081                }
    11001082
     1083                /// true if expr is effectively just the 'this' parameter
     1084                bool isThisExpression( Expression * expr, DeclarationWithType * thisParam ) {
     1085                        // TODO: there are more complicated ways to pass 'this' to a constructor, e.g. &*, *&, etc.
     1086                        if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
     1087                                return varExpr->get_var() == thisParam;
     1088                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * > ( expr ) ) {
     1089                                return isThisExpression( castExpr->get_arg(), thisParam );
     1090                        }
     1091                        return false;
     1092                }
     1093
     1094                /// returns a MemberExpr if expr is effectively just member access on the 'this' parameter, else nullptr
     1095                MemberExpr * isThisMemberExpr( Expression * expr, DeclarationWithType * thisParam ) {
     1096                        if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
     1097                                if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     1098                                        return memberExpr;
     1099                                }
     1100                        } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
     1101                                return isThisMemberExpr( castExpr->get_arg(), thisParam );
     1102                        }
     1103                        return nullptr;
     1104                }
     1105
    11011106                void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) {
    11021107                        if ( ! checkWarnings( function ) ) return;
     
    11071112                                Expression * firstParam = appExpr->get_args().front();
    11081113
    1109                                 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {
     1114                                if ( isThisExpression( firstParam, thisParam ) ) {
    11101115                                        // if calling another constructor on thisParam, assume that function handles
    11111116                                        // all members - if it doesn't a warning will appear in that function.
    1112                                         if ( varExpr->get_var() == thisParam ) {
    1113                                                 unhandled.clear();
    1114                                         }
    1115                                 } else {
    1116                                         // if first parameter is a member expression then
    1117                                         // remove the member from unhandled set.
    1118                                         handleFirstParam( firstParam );
    1119                                 }
    1120                         }
    1121 
    1122                         Parent::visit( appExpr );
    1123                 }
    1124 
    1125                 void GenStructMemberCalls::handleFirstParam( Expression * firstParam ) {
    1126                         using namespace std;
    1127                         if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( firstParam ) ) {
    1128                                 if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( addrExpr->get_arg() ) ) {
    1129                                         if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
    1130                                                 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
    1131                                                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
    1132                                                                 if ( varExpr->get_var() == thisParam ) {
    1133                                                                         unhandled.erase( memberExpr->get_member() );
    1134                                                                 }
    1135                                                         }
    1136                                                 }
     1117                                        unhandled.clear();
     1118                                } else if ( MemberExpr * memberExpr = isThisMemberExpr( firstParam, thisParam ) ) {
     1119                                        // if first parameter is a member expression on the this parameter,
     1120                                        // then remove the member from unhandled set.
     1121                                        if ( isThisExpression( memberExpr->get_aggregate(), thisParam ) ) {
     1122                                                unhandled.erase( memberExpr->get_member() );
    11371123                                        }
    11381124                                }
    11391125                        }
     1126                        Parent::visit( appExpr );
    11401127                }
    11411128
     
    11441131                        if ( ! isCtor ) return;
    11451132
    1146                         if ( ApplicationExpr * deref = dynamic_cast< ApplicationExpr * >( memberExpr->get_aggregate() ) ) {
    1147                                 if ( getFunctionName( deref ) == "*?" && deref->get_args().size() == 1 ) {
    1148                                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( deref->get_args().front() ) ) {
    1149                                                 if ( varExpr->get_var() == thisParam ) {
    1150                                                         if ( unhandled.count( memberExpr->get_member() ) ) {
    1151                                                                 // emit a warning because a member was used before it was constructed
    1152                                                                 usedUninit.insert( { memberExpr->get_member(), memberExpr->location } );
    1153                                                         }
    1154                                                 }
    1155                                         }
     1133                        if ( isThisExpression( memberExpr->get_aggregate(), 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 } );
    11561137                                }
    11571138                        }
     
    11991180                        ctorExpr->set_callExpr( nullptr );
    12001181                        ctorExpr->set_env( nullptr );
     1182                        delete ctorExpr;
    12011183
    12021184                        Expression *& firstArg = callExpr->get_args().front();
    1203                         UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) );
    1204                         assign->get_args().push_back( new VariableExpr( tmp ) );
    1205                         assign->get_args().push_back( firstArg );
    1206                         assign->set_result( ctorExpr->get_result()->clone() );
    1207                         firstArg = assign;
    1208 
    1209                         CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) );
     1185
     1186                        // 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.
     1187
     1188                        // generate the type of assignment operator using the type of tmp minus any reference types
     1189                        Type * type = tmp->get_type()->stripReferences();
     1190                        FunctionType * ftype = SymTab::genAssignType( type );
     1191
     1192                        // generate fake assignment decl and call it using &tmp and &firstArg
     1193                        // since tmp is guaranteed to be a reference and we want to assign pointers
     1194                        FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr );
     1195                        ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) );
     1196                        assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) );
     1197                        Expression * addrArg = new AddressExpr( firstArg );
     1198                        // if firstArg has type T&&, then &firstArg has type T*&.
     1199                        // Cast away the reference to a value type so that the argument
     1200                        // matches the assignment's parameter types
     1201                        if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) {
     1202                                addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() );
     1203                        }
     1204                        assign->get_args().push_back( addrArg );
     1205                        firstArg = new VariableExpr( tmp );
     1206
     1207                        // for constructor expr:
     1208                        //   T x;
     1209                        //   x{};
     1210                        // results in:
     1211                        //   T x;
     1212                        //   T & tmp;
     1213                        //   &tmp = &x, ?{}(tmp), tmp
     1214                        CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );
    12101215                        commaExpr->set_env( env );
    1211                         delete ctorExpr;
    12121216                        return commaExpr;
    12131217                }
Note: See TracChangeset for help on using the changeset viewer.