Changeset d3e4d6c for src/InitTweak


Ignore:
Timestamp:
Aug 23, 2017, 6:22:07 PM (8 years ago)
Author:
Peter A. Buhr <pabuhr@…>
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:
87e08e24, cb811ac
Parents:
9f07232 (diff), bd37119 (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 plg2:software/cfa/cfa-cc

Location:
src/InitTweak
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/FixInit.cc

    r9f07232 rd3e4d6c  
    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                }
  • src/InitTweak/GenInit.cc

    r9f07232 rd3e4d6c  
    2121#include <list>                    // for _List_iterator, list
    2222
     23#include "CodeGen/OperatorTable.h"
    2324#include "Common/PassVisitor.h"    // for PassVisitor, WithGuards, WithShort...
    2425#include "Common/SemanticError.h"  // for SemanticError
     
    5758
    5859          protected:
    59                 FunctionType * ftype;
     60                FunctionType * ftype = nullptr;
    6061                std::string funcName;
    6162        };
     
    140141                std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
    141142                assert( returnVals.size() == 0 || returnVals.size() == 1 );
    142                 // hands off if the function returns an lvalue - we don't want to allocate a temporary if a variable's address
     143                // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    143144                // is being returned
    144                 if ( returnStmt->get_expr() && returnVals.size() == 1 && ! returnVals.front()->get_type()->get_lvalue() ) {
     145                if ( returnStmt->get_expr() && returnVals.size() == 1 && ! dynamic_cast< ReferenceType * >( returnVals.front()->get_type() ) ) {
    145146                        // explicitly construct the return value using the return expression and the retVal object
    146147                        assertf( returnVals.front()->get_name() != "", "Function %s has unnamed return value\n", funcName.c_str() );
    147                         UntypedExpr *construct = new UntypedExpr( new NameExpr( "?{}" ) );
    148                         construct->get_args().push_back( new AddressExpr( new VariableExpr( returnVals.front() ) ) );
    149                         construct->get_args().push_back( returnStmt->get_expr() );
    150                         stmtsToAddBefore.push_back(new ExprStmt(noLabels, construct));
     148
     149                        stmtsToAddBefore.push_back( genCtorDtor( "?{}", dynamic_cast< ObjectDecl *>( returnVals.front() ), returnStmt->get_expr() ) );
    151150
    152151                        // return the retVal object
     
    215214
    216215        bool CtorDtor::isManaged( Type * type ) const {
     216                // at least for now, references are never constructed
     217                if ( dynamic_cast< ReferenceType * >( type ) ) return false;
    217218                // need to clear and reset qualifiers when determining if a type is managed
    218219                ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
     
    238239        void CtorDtor::handleDWT( DeclarationWithType * dwt ) {
    239240                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
    240                 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && isCtorDtor( dwt->get_name() ) ) {
     241                if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
    241242                        std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
    242243                        assert( ! params.empty() );
    243                         PointerType * type = safe_dynamic_cast< PointerType * >( params.front()->get_type() );
    244                         managedTypes.insert( SymTab::Mangler::mangle( type->get_base() ) );
     244                        Type * type = InitTweak::getPointerBase( params.front()->get_type() );
     245                        assert( type );
     246                        managedTypes.insert( SymTab::Mangler::mangle( type ) );
    245247                }
    246248        }
  • src/InitTweak/InitTweak.cc

    r9f07232 rd3e4d6c  
    187187
    188188                        UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
    189                         increment->get_args().push_back( new AddressExpr( index->clone() ) );
     189                        increment->get_args().push_back( index->clone() );
    190190                        *out++ = new ExprStmt( noLabels, increment );
    191191                }
     
    397397                template<typename CallExpr>
    398398                Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
    399                         if ( pos >= callExpr->get_args().size() ) assertf( false, "asking for argument that doesn't exist. Return NULL/throw exception?" );
     399                        if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() );
    400400                        for ( Expression *& arg : callExpr->get_args() ) {
    401401                                if ( pos == 0 ) return arg;
     
    475475                } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    476476                        return arrayType->get_base();
     477                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
     478                        return refType->get_base();
    477479                } else {
    478480                        return NULL;
     
    560562                if ( ftype->get_parameters().size() != 2 ) return 0;
    561563
    562                 Type * t1 = ftype->get_parameters().front()->get_type();
     564                Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    563565                Type * t2 = ftype->get_parameters().back()->get_type();
    564                 PointerType * ptrType = dynamic_cast< PointerType * > ( t1 );
    565                 assert( ptrType );
    566 
    567                 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( ptrType->get_base(), t2, SymTab::Indexer() ) ) {
     566                assert( t1 );
     567
     568                if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) {
    568569                        return function;
    569570                } else {
  • src/InitTweak/InitTweak.h

    r9f07232 rd3e4d6c  
    2424// helper functions for initialization
    2525namespace InitTweak {
    26         bool isConstructor( const std::string & );
    27         bool isDestructor( const std::string & );
    28         bool isAssignment( const std::string & );
    29         bool isCtorDtor( const std::string & );
    30         bool isCtorDtorAssign( const std::string & );
    31 
    3226        FunctionDecl * isAssignment( Declaration * decl );
    3327        FunctionDecl * isDestructor( Declaration * decl );
Note: See TracChangeset for help on using the changeset viewer.