Changes in src/InitTweak/FixInit.cc [4618319:62423350]
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r4618319 r62423350 26 26 #include "FixGlobalInit.h" 27 27 #include "CodeGen/GenType.h" // for warning/error messages 28 #include "CodeGen/OperatorTable.h"29 28 #include "Common/PassVisitor.h" 30 29 #include "GenPoly/DeclMutator.h" … … 239 238 SemanticError errors; 240 239 private: 240 void handleFirstParam( Expression * firstParam ); 241 241 template< typename... Params > 242 242 void emit( CodeLocation, const Params &... params ); … … 363 363 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 364 364 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(); 367 367 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() ) ) { 371 371 // optimization: don't need to copy construct in order to call a copy constructor 372 372 return appExpr; 373 373 } // if 374 } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) {374 } else if ( isDestructor( funcDecl->get_name() ) ) { 375 375 // correctness: never copy construct arguments to a destructor 376 376 return appExpr; … … 401 401 402 402 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 ); 404 404 } 405 405 … … 489 489 impCpCtorExpr->get_returnDecls().push_back( ret ); 490 490 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 491 if ( ! dynamic_cast< ReferenceType * >( result) ) {491 if ( ! result->get_lvalue() ) { 492 492 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 493 493 destructRet( ret, impCpCtorExpr ); … … 975 975 if ( ! funcDecl ) return false; 976 976 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() ); 978 978 } 979 979 … … 992 992 993 993 function = funcDecl; 994 isCtor = CodeGen::isConstructor( function->get_name() );994 isCtor = isConstructor( function->get_name() ); 995 995 if ( checkWarnings( function ) ) { 996 996 FunctionType * type = function->get_functionType(); 997 997 assert( ! type->get_parameters().empty() ); 998 998 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() ); 1001 1001 if ( structType ) { 1002 1002 structDecl = structType->get_baseStruct(); … … 1031 1031 1032 1032 if ( ! unhandled.empty() ) { 1033 // need to explicitly re-add function parameters to the indexerin order to resolve copy constructors1033 // need to explicitly re-add function parameters in order to resolve copy constructors 1034 1034 enterScope(); 1035 1035 maybeAccept( function->get_functionType(), *this ); … … 1046 1046 // insert and resolve default/copy constructor call for each field that's unhandled 1047 1047 std::list< Statement * > stmt; 1048 UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) ); 1049 1048 1050 Expression * arg2 = 0; 1049 1051 if ( isCopyConstructor( function ) ) { … … 1054 1056 } 1055 1057 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 ); 1060 1059 1061 1060 assert( stmt.size() <= 1 ); … … 1084 1083 } 1085 1084 1086 /// true if expr is effectively just the 'this' parameter1087 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 nullptr1098 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 1109 1085 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 1110 1086 if ( ! checkWarnings( function ) ) return; … … 1115 1091 Expression * firstParam = appExpr->get_args().front(); 1116 1092 1117 if ( isThisExpression( firstParam, thisParam ) ) {1093 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) { 1118 1094 // if calling another constructor on thisParam, assume that function handles 1119 1095 // 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 } 1126 1121 } 1127 1122 } 1128 1123 } 1129 Parent::visit( appExpr );1130 1124 } 1131 1125 … … 1134 1128 if ( ! isCtor ) return; 1135 1129 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 } 1140 1140 } 1141 1141 } … … 1183 1183 ctorExpr->set_callExpr( nullptr ); 1184 1184 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 ); 1185 1195 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 types1192 Type * type = tmp->get_type()->stripReferences();1193 FunctionType * ftype = SymTab::genAssignType( type );1194 1195 // generate fake assignment decl and call it using &tmp and &firstArg1196 // since tmp is guaranteed to be a reference and we want to assign pointers1197 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 argument1203 // matches the assignment's parameter types1204 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), tmp1217 CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) );1218 commaExpr->set_env( env );1219 1196 return commaExpr; 1220 1197 }
Note:
See TracChangeset
for help on using the changeset viewer.