Changes in src/InitTweak/FixInit.cc [62423350:4618319]
- File:
-
- 1 edited
-
src/InitTweak/FixInit.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r62423350 r4618319 26 26 #include "FixGlobalInit.h" 27 27 #include "CodeGen/GenType.h" // for warning/error messages 28 #include "CodeGen/OperatorTable.h" 28 29 #include "Common/PassVisitor.h" 29 30 #include "GenPoly/DeclMutator.h" … … 238 239 SemanticError errors; 239 240 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 ( 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() ); 367 367 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() ) ) { 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 ( isDestructor( funcDecl->get_name() ) ) {374 } else if ( CodeGen::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 ) || GenPoly::getFunctionType( type ) || Tuples::isTtype( type );403 return dynamic_cast< VarArgsType * >( type ) || dynamic_cast< ReferenceType * >( 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 ( ! result->get_lvalue() ) {491 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 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 isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() );977 return CodeGen::isCtorDtor( funcDecl->get_name() ) && ! LinkageSpec::isOverridable( funcDecl->get_linkage() ); 978 978 } 979 979 … … 992 992 993 993 function = funcDecl; 994 isCtor = isConstructor( function->get_name() );994 isCtor = CodeGen::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 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 ); 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 in order to resolve copy constructors1033 // need to explicitly re-add function parameters to the indexer 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 1050 1048 Expression * arg2 = 0; 1051 1049 if ( isCopyConstructor( function ) ) { … … 1056 1054 } 1057 1055 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 ); 1059 1060 1060 1061 assert( stmt.size() <= 1 ); … … 1083 1084 } 1084 1085 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 1085 1109 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 1086 1110 if ( ! checkWarnings( function ) ) return; … … 1091 1115 Expression * firstParam = appExpr->get_args().front(); 1092 1116 1093 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {1117 if ( isThisExpression( firstParam, thisParam ) ) { 1094 1118 // if calling another constructor on thisParam, assume that function handles 1095 1119 // 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() ); 1121 1126 } 1122 1127 } 1123 1128 } 1129 Parent::visit( appExpr ); 1124 1130 } 1125 1131 … … 1128 1134 if ( ! isCtor ) return; 1129 1135 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 } ); 1140 1140 } 1141 1141 } … … 1183 1183 ctorExpr->set_callExpr( nullptr ); 1184 1184 ctorExpr->set_env( nullptr ); 1185 delete ctorExpr; 1185 1186 1186 1187 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 ) ) ); 1194 1218 commaExpr->set_env( env ); 1195 delete ctorExpr;1196 1219 return commaExpr; 1197 1220 }
Note:
See TracChangeset
for help on using the changeset viewer.