Changeset d3e4d6c for src/InitTweak/FixInit.cc
- Timestamp:
- Aug 23, 2017, 6:22:07 PM (7 years ago)
- 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. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/FixInit.cc
r9f07232 rd3e4d6c 29 29 30 30 #include "CodeGen/GenType.h" // for genPrettyType 31 #include "CodeGen/OperatorTable.h" 31 32 #include "Common/PassVisitor.h" // for PassVisitor, WithStmtsToAdd 32 33 #include "Common/SemanticError.h" // for SemanticError … … 254 255 SemanticError errors; 255 256 private: 256 void handleFirstParam( Expression * firstParam );257 257 template< typename... Params > 258 258 void emit( CodeLocation, const Params &... params ); … … 379 379 FunctionType * ftype = dynamic_cast< FunctionType * >( GenPoly::getFunctionType( funcDecl->get_type() ) ); 380 380 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() ); 383 383 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() ) ) { 387 387 // optimization: don't need to copy construct in order to call a copy constructor 388 388 return appExpr; 389 389 } // if 390 } else if ( isDestructor( funcDecl->get_name() ) ) {390 } else if ( CodeGen::isDestructor( funcDecl->get_name() ) ) { 391 391 // correctness: never copy construct arguments to a destructor 392 392 return appExpr; … … 417 417 418 418 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 ); 420 420 } 421 421 … … 505 505 impCpCtorExpr->get_returnDecls().push_back( ret ); 506 506 CP_CTOR_PRINT( std::cerr << "makeCtorDtor for a return" << std::endl; ) 507 if ( ! result->get_lvalue() ) {507 if ( ! dynamic_cast< ReferenceType * >( result ) ) { 508 508 // destructing lvalue returns is bad because it can cause multiple destructor calls to the same object - the returned object is not a temporary 509 509 destructRet( ret, impCpCtorExpr ); … … 607 607 608 608 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 returning611 // non-intrinsic function. Add an AddressExpr to the call to negate the derefence and change the612 // type of the return temporary from T to T* to properly capture the return value. Then dereference613 // the result of the comma expression, since the lvalue returning call was originally wrapped with614 // an AddressExpr. Effectively, this turns615 // lvalue T f();616 // &*f();617 // into618 // T * f();619 // T * tmp_cp_retN;620 // &*(tmp_cp_retN = &*f(), tmp_cp_retN); // the first * and second & are generated here621 // 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 } // if628 609 // move env from callExpr to retExpr 629 610 retExpr->set_env( callExpr->get_env() ); … … 991 972 if ( ! funcDecl ) return false; 992 973 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() ); 994 975 } 995 976 … … 1008 989 1009 990 function = funcDecl; 1010 isCtor = isConstructor( function->get_name() );991 isCtor = CodeGen::isConstructor( function->get_name() ); 1011 992 if ( checkWarnings( function ) ) { 1012 993 FunctionType * type = function->get_functionType(); 1013 994 assert( ! type->get_parameters().empty() ); 1014 995 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 ); 1017 998 if ( structType ) { 1018 999 structDecl = structType->get_baseStruct(); … … 1047 1028 1048 1029 if ( ! unhandled.empty() ) { 1049 // need to explicitly re-add function parameters in order to resolve copy constructors1030 // need to explicitly re-add function parameters to the indexer in order to resolve copy constructors 1050 1031 enterScope(); 1051 1032 maybeAccept( function->get_functionType(), *this ); … … 1062 1043 // insert and resolve default/copy constructor call for each field that's unhandled 1063 1044 std::list< Statement * > stmt; 1064 UntypedExpr * deref = UntypedExpr::createDeref( new VariableExpr( thisParam ) );1065 1066 1045 Expression * arg2 = 0; 1067 1046 if ( isCopyConstructor( function ) ) { … … 1072 1051 } 1073 1052 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 ); 1075 1057 1076 1058 assert( stmt.size() <= 1 ); … … 1099 1081 } 1100 1082 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 1101 1106 void GenStructMemberCalls::visit( ApplicationExpr * appExpr ) { 1102 1107 if ( ! checkWarnings( function ) ) return; … … 1107 1112 Expression * firstParam = appExpr->get_args().front(); 1108 1113 1109 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( firstParam ) ) {1114 if ( isThisExpression( firstParam, thisParam ) ) { 1110 1115 // if calling another constructor on thisParam, assume that function handles 1111 1116 // 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() ); 1137 1123 } 1138 1124 } 1139 1125 } 1126 Parent::visit( appExpr ); 1140 1127 } 1141 1128 … … 1144 1131 if ( ! isCtor ) return; 1145 1132 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 } ); 1156 1137 } 1157 1138 } … … 1199 1180 ctorExpr->set_callExpr( nullptr ); 1200 1181 ctorExpr->set_env( nullptr ); 1182 delete ctorExpr; 1201 1183 1202 1184 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 ) ) ); 1210 1215 commaExpr->set_env( env ); 1211 delete ctorExpr;1212 1216 return commaExpr; 1213 1217 }
Note: See TracChangeset
for help on using the changeset viewer.