Changes in src/ResolvExpr/Resolver.cc [99d4584:2b59f55]
- File:
-
- 1 edited
-
src/ResolvExpr/Resolver.cc (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/ResolvExpr/Resolver.cc
r99d4584 r2b59f55 29 29 #include "typeops.h" // for extractResultType 30 30 #include "Unify.h" // for unify 31 #include "AST/Chain.hpp" 31 32 #include "AST/Decl.hpp" 32 33 #include "AST/Init.hpp" … … 164 165 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) { 165 166 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 166 if ( ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {167 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) { 167 168 // cast is to the same type as its argument, so it's unnecessary -- remove it 168 169 expr = castExpr->arg; … … 410 411 411 412 void Resolver_old::previsit( ObjectDecl * objectDecl ) { 412 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 413 // class-variable initContext is changed multiple time because the LHS is analysed twice. 414 // The second analysis changes initContext because of a function type can contain object 415 // declarations in the return and parameter types. So each value of initContext is 413 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that 414 // class-variable initContext is changed multiple time because the LHS is analysed twice. 415 // The second analysis changes initContext because of a function type can contain object 416 // declarations in the return and parameter types. So each value of initContext is 416 417 // retained, so the type on the first analysis is preserved and used for selecting the RHS. 417 418 GuardValue( currentObject ); … … 450 451 451 452 void Resolver_old::postvisit( FunctionDecl * functionDecl ) { 452 // default value expressions have an environment which shouldn't be there and trips up 453 // default value expressions have an environment which shouldn't be there and trips up 453 454 // later passes. 454 455 // xxx - it might be necessary to somehow keep the information from this environment, but I … … 964 965 } 965 966 967 /// always-accept candidate filter 968 bool anyCandidate( const Candidate & ) { return true; } 969 966 970 /// Calls the CandidateFinder and finds the single best candidate 967 971 CandidateRef findUnfinishedKindExpression( 968 972 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 969 std::function<bool(const Candidate &)> pred , ResolvMode mode = {}973 std::function<bool(const Candidate &)> pred = anyCandidate, ResolvMode mode = {} 970 974 ) { 971 975 if ( ! untyped ) return nullptr; … … 1055 1059 ) { 1056 1060 // generated cast is the same type as its argument, remove it after keeping env 1057 ast::ptr<ast::Expr> arg = castExpr->arg; 1058 arg.get_and_mutate()->env = castExpr->env; 1059 return arg; 1061 return ast::mutate_field( 1062 castExpr->arg.get(), &ast::Expr::env, castExpr->env ); 1060 1063 } 1061 1064 return castExpr; … … 1067 1070 } 1068 1071 }; 1072 1073 /// Removes cast to type of argument (unlike StripCasts, also handles non-generated casts) 1074 void removeExtraneousCast( ast::ptr<ast::Expr> & expr, const ast::SymbolTable & symtab ) { 1075 if ( const ast::CastExpr * castExpr = expr.as< ast::CastExpr >() ) { 1076 if ( typesCompatible( castExpr->arg->result, castExpr->result, symtab ) ) { 1077 // cast is to the same type as its argument, remove it 1078 ast::ptr< ast::TypeSubstitution > env = castExpr->env; 1079 expr.set_and_mutate( castExpr->arg )->env = env; 1080 } 1081 } 1082 } 1069 1083 1070 1084 /// Establish post-resolver invariants for expressions … … 1081 1095 StripCasts_new::strip( expr ); 1082 1096 } 1083 1097 1098 /// Find the expression candidate that is the unique best match for `untyped` in a `void` 1099 /// context. 1100 ast::ptr< ast::Expr > resolveInVoidContext( 1101 const ast::Expr * expr, const ast::SymbolTable & symtab, ast::TypeEnvironment & env 1102 ) { 1103 assertf( expr, "expected a non-null expression" ); 1104 1105 // set up and resolve expression cast to void 1106 ast::CastExpr * untyped = new ast::CastExpr{ expr->location, expr }; 1107 CandidateRef choice = findUnfinishedKindExpression( 1108 untyped, symtab, "", anyCandidate, ResolvMode::withAdjustment() ); 1109 1110 // a cast expression has either 0 or 1 interpretations (by language rules); 1111 // if 0, an exception has already been thrown, and this code will not run 1112 const ast::CastExpr * castExpr = choice->expr.strict_as< ast::CastExpr >(); 1113 env = std::move( choice->env ); 1114 1115 return castExpr->arg; 1116 } 1117 1118 /// Resolve `untyped` to the expression whose candidate is the best match for a `void` 1119 /// context. 1120 ast::ptr< ast::Expr > findVoidExpression( 1121 const ast::Expr * untyped, const ast::SymbolTable & symtab 1122 ) { 1123 resetTyVarRenaming(); 1124 ast::TypeEnvironment env; 1125 ast::ptr< ast::Expr > newExpr = resolveInVoidContext( untyped, symtab, env ); 1126 finishExpr( newExpr, env, untyped->env ); 1127 return newExpr; 1128 } 1129 1084 1130 /// resolve `untyped` to the expression whose candidate satisfies `pred` with the 1085 1131 /// lowest cost, returning the resolved version 1086 1132 ast::ptr< ast::Expr > findKindExpression( 1087 const ast::Expr * untyped, const ast::SymbolTable & symtab, const std::string & kind, 1088 std::function<bool(const Candidate &)> pred, ResolvMode mode = {} 1133 const ast::Expr * untyped, const ast::SymbolTable & symtab, 1134 std::function<bool(const Candidate &)> pred = anyCandidate, 1135 const std::string & kind = "", ResolvMode mode = {} 1089 1136 ) { 1090 1137 if ( ! untyped ) return {}; … … 1093 1140 finishExpr( choice->expr, choice->env, untyped->env ); 1094 1141 return std::move( choice->expr ); 1142 } 1143 1144 /// Resolve `untyped` to the single expression whose candidate is the best match for the 1145 /// given type. 1146 ast::ptr< ast::Expr > findSingleExpression( 1147 const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab 1148 ) { 1149 assert( untyped && type ); 1150 const ast::Expr * castExpr = new ast::CastExpr{ untyped->location, untyped, type }; 1151 ast::ptr< ast::Expr > newExpr = findKindExpression( castExpr, symtab ); 1152 removeExtraneousCast( newExpr, symtab ); 1153 return newExpr; 1095 1154 } 1096 1155 … … 1114 1173 const ast::Expr * untyped, const ast::SymbolTable & symtab 1115 1174 ) { 1116 return findKindExpression( untyped, symtab, "condition", hasIntegralType);1117 } 1118 } 1119 1120 class Resolver_new final 1121 : public ast::WithSymbolTable, public ast::WithGuards, 1122 public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting, 1175 return findKindExpression( untyped, symtab, hasIntegralType, "condition" ); 1176 } 1177 } 1178 1179 class Resolver_new final 1180 : public ast::WithSymbolTable, public ast::WithGuards, 1181 public ast::WithVisitorRef<Resolver_new>, public ast::WithShortCircuiting, 1123 1182 public ast::WithStmtsToAdd<> { 1124 1183 1125 1184 ast::ptr< ast::Type > functionReturn = nullptr; 1126 // ast::CurrentObject currentObject = nullptr;1185 ast::CurrentObject currentObject; 1127 1186 bool inEnumDecl = false; 1128 1187 1129 public: 1188 public: 1130 1189 Resolver_new() = default; 1131 1190 Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; } … … 1140 1199 void previsit( const ast::PointerType * ); 1141 1200 1142 voidprevisit( const ast::ExprStmt * );1143 voidprevisit( const ast::AsmExpr * );1144 voidprevisit( const ast::AsmStmt * );1145 voidprevisit( const ast::IfStmt * );1146 voidprevisit( const ast::WhileStmt * );1147 voidprevisit( const ast::ForStmt * );1148 voidprevisit( const ast::SwitchStmt * );1149 voidprevisit( const ast::CaseStmt * );1150 voidprevisit( const ast::BranchStmt * );1151 voidprevisit( const ast::ReturnStmt * );1152 voidprevisit( const ast::ThrowStmt * );1153 voidprevisit( const ast::CatchStmt * );1201 const ast::ExprStmt * previsit( const ast::ExprStmt * ); 1202 const ast::AsmExpr * previsit( const ast::AsmExpr * ); 1203 const ast::AsmStmt * previsit( const ast::AsmStmt * ); 1204 const ast::IfStmt * previsit( const ast::IfStmt * ); 1205 const ast::WhileStmt * previsit( const ast::WhileStmt * ); 1206 const ast::ForStmt * previsit( const ast::ForStmt * ); 1207 const ast::SwitchStmt * previsit( const ast::SwitchStmt * ); 1208 const ast::CaseStmt * previsit( const ast::CaseStmt * ); 1209 const ast::BranchStmt * previsit( const ast::BranchStmt * ); 1210 const ast::ReturnStmt * previsit( const ast::ReturnStmt * ); 1211 const ast::ThrowStmt * previsit( const ast::ThrowStmt * ); 1212 const ast::CatchStmt * previsit( const ast::CatchStmt * ); 1154 1213 void previsit( const ast::WaitForStmt * ); 1155 1214 … … 1170 1229 1171 1230 const ast::FunctionDecl * Resolver_new::postvisit( const ast::FunctionDecl * functionDecl ) { 1172 // default value expressions have an environment which shouldn't be there and trips up 1231 // default value expressions have an environment which shouldn't be there and trips up 1173 1232 // later passes. 1174 1233 ast::ptr< ast::FunctionDecl > ret = functionDecl; 1175 1234 for ( unsigned i = 0; i < functionDecl->type->params.size(); ++i ) { 1176 1235 const ast::ptr<ast::DeclWithType> & d = functionDecl->type->params[i]; 1177 1236 1178 1237 if ( const ast::ObjectDecl * obj = d.as< ast::ObjectDecl >() ) { 1179 1238 if ( const ast::SingleInit * init = obj->init.as< ast::SingleInit >() ) { 1180 1239 if ( init->value->env == nullptr ) continue; 1181 1240 // clone initializer minus the initializer environment 1182 strict_dynamic_cast< ast::SingleInit * >( 1183 strict_dynamic_cast< ast::ObjectDecl * >( 1184 ret.get_and_mutate()->type.get_and_mutate()->params[i].get_and_mutate() 1185 )->init.get_and_mutate() 1186 )->value.get_and_mutate()->env = nullptr; 1241 ast::chain_mutate( ret ) 1242 ( &ast::FunctionDecl::type ) 1243 ( &ast::FunctionType::params )[i] 1244 ( &ast::ObjectDecl::init ) 1245 ( &ast::SingleInit::value )->env = nullptr; 1246 1247 assert( functionDecl != ret.get() || functionDecl->unique() ); 1248 assert( ! ret->type->params[i].strict_as< ast::ObjectDecl >()->init.strict_as< ast::SingleInit >()->value->env ); 1187 1249 } 1188 1250 } … … 1192 1254 1193 1255 void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) { 1194 #warning unimplemented; Resolver port in progress 1195 (void)objectDecl; 1196 assert(false); 1256 // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()], 1257 // class-variable `initContext` is changed multiple times because the LHS is analyzed 1258 // twice. The second analysis changes `initContext` because a function type can contain 1259 // object declarations in the return and parameter types. Therefore each value of 1260 // `initContext` is retained so the type on the first analysis is preserved and used for 1261 // selecting the RHS. 1262 GuardValue( currentObject ); 1263 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() }; 1264 if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) { 1265 // enumerator initializers should not use the enum type to initialize, since the 1266 // enum type is still incomplete at this point. Use `int` instead. 1267 currentObject = ast::CurrentObject{ 1268 objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } }; 1269 } 1197 1270 } 1198 1271 … … 1206 1279 const ast::StaticAssertDecl * assertDecl 1207 1280 ) { 1208 ast::ptr< ast::Expr > cond = findIntegralExpression( assertDecl->cond, symtab ); 1209 if ( cond == assertDecl->cond ) return assertDecl; 1281 return ast::mutate_field( 1282 assertDecl, &ast::StaticAssertDecl::cond, 1283 findIntegralExpression( assertDecl->cond, symtab ) ); 1284 } 1285 1286 template< typename PtrType > 1287 void handlePtrType( const PtrType * type, const ast::SymbolTable & symtab ) { 1288 #warning unimplemented; needs support for new Validate::SizeType global 1289 (void)type; (void)symtab; 1290 assert( false ); 1291 } 1292 1293 void Resolver_new::previsit( const ast::ArrayType * at ) { 1294 handlePtrType( at, symtab ); 1295 } 1296 1297 void Resolver_new::previsit( const ast::PointerType * pt ) { 1298 handlePtrType( pt, symtab ); 1299 } 1300 1301 const ast::ExprStmt * Resolver_new::previsit( const ast::ExprStmt * exprStmt ) { 1302 visit_children = false; 1303 assertf( exprStmt->expr, "ExprStmt has null expression in resolver" ); 1210 1304 1211 ast::StaticAssertDecl * ret = mutate( assertDecl ); 1212 ret->cond = cond; 1213 return ret; 1214 } 1215 1216 void Resolver_new::previsit( const ast::ArrayType * at ) { 1217 #warning unimplemented; Resolver port in progress 1218 (void)at; 1219 assert(false); 1220 } 1221 1222 void Resolver_new::previsit( const ast::PointerType * pt ) { 1223 #warning unimplemented; Resolver port in progress 1224 (void)pt; 1225 assert(false); 1226 } 1227 1228 void Resolver_new::previsit( const ast::ExprStmt * exprStmt ) { 1229 #warning unimplemented; Resolver port in progress 1230 (void)exprStmt; 1231 assert(false); 1232 } 1233 1234 void Resolver_new::previsit( const ast::AsmExpr * asmExpr ) { 1235 #warning unimplemented; Resolver port in progress 1236 (void)asmExpr; 1237 assert(false); 1238 } 1239 1240 void Resolver_new::previsit( const ast::AsmStmt * asmStmt ) { 1241 #warning unimplemented; Resolver port in progress 1242 (void)asmStmt; 1243 assert(false); 1244 } 1245 1246 void Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1247 #warning unimplemented; Resolver port in progress 1248 (void)ifStmt; 1249 assert(false); 1250 } 1251 1252 void Resolver_new::previsit( const ast::WhileStmt * whileStmt ) { 1253 #warning unimplemented; Resolver port in progress 1254 (void)whileStmt; 1255 assert(false); 1256 } 1257 1258 void Resolver_new::previsit( const ast::ForStmt * forStmt ) { 1259 #warning unimplemented; Resolver port in progress 1260 (void)forStmt; 1261 assert(false); 1262 } 1263 1264 void Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) { 1265 #warning unimplemented; Resolver port in progress 1266 (void)switchStmt; 1267 assert(false); 1268 } 1269 1270 void Resolver_new::previsit( const ast::CaseStmt * caseStmt ) { 1271 #warning unimplemented; Resolver port in progress 1272 (void)caseStmt; 1273 assert(false); 1274 } 1275 1276 void Resolver_new::previsit( const ast::BranchStmt * branchStmt ) { 1277 #warning unimplemented; Resolver port in progress 1278 (void)branchStmt; 1279 assert(false); 1280 } 1281 1282 void Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) { 1283 #warning unimplemented; Resolver port in progress 1284 (void)returnStmt; 1285 assert(false); 1286 } 1287 1288 void Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) { 1289 #warning unimplemented; Resolver port in progress 1290 (void)throwStmt; 1291 assert(false); 1292 } 1293 1294 void Resolver_new::previsit( const ast::CatchStmt * catchStmt ) { 1295 #warning unimplemented; Resolver port in progress 1296 (void)catchStmt; 1297 assert(false); 1305 return ast::mutate_field( 1306 exprStmt, &ast::ExprStmt::expr, findVoidExpression( exprStmt->expr, symtab ) ); 1307 } 1308 1309 const ast::AsmExpr * Resolver_new::previsit( const ast::AsmExpr * asmExpr ) { 1310 visit_children = false; 1311 1312 asmExpr = ast::mutate_field( 1313 asmExpr, &ast::AsmExpr::operand, findVoidExpression( asmExpr->operand, symtab ) ); 1314 1315 if ( asmExpr->inout ) { 1316 asmExpr = ast::mutate_field( 1317 asmExpr, &ast::AsmExpr::inout, findVoidExpression( asmExpr->inout, symtab ) ); 1318 } 1319 1320 return asmExpr; 1321 } 1322 1323 const ast::AsmStmt * Resolver_new::previsit( const ast::AsmStmt * asmStmt ) { 1324 visitor->maybe_accept( asmStmt, &ast::AsmStmt::input ); 1325 visitor->maybe_accept( asmStmt, &ast::AsmStmt::output ); 1326 visit_children = false; 1327 return asmStmt; 1328 } 1329 1330 const ast::IfStmt * Resolver_new::previsit( const ast::IfStmt * ifStmt ) { 1331 return ast::mutate_field( 1332 ifStmt, &ast::IfStmt::cond, findIntegralExpression( ifStmt->cond, symtab ) ); 1333 } 1334 1335 const ast::WhileStmt * Resolver_new::previsit( const ast::WhileStmt * whileStmt ) { 1336 return ast::mutate_field( 1337 whileStmt, &ast::WhileStmt::cond, findIntegralExpression( whileStmt->cond, symtab ) ); 1338 } 1339 1340 const ast::ForStmt * Resolver_new::previsit( const ast::ForStmt * forStmt ) { 1341 if ( forStmt->cond ) { 1342 forStmt = ast::mutate_field( 1343 forStmt, &ast::ForStmt::cond, findIntegralExpression( forStmt->cond, symtab ) ); 1344 } 1345 1346 if ( forStmt->inc ) { 1347 forStmt = ast::mutate_field( 1348 forStmt, &ast::ForStmt::inc, findVoidExpression( forStmt->inc, symtab ) ); 1349 } 1350 1351 return forStmt; 1352 } 1353 1354 const ast::SwitchStmt * Resolver_new::previsit( const ast::SwitchStmt * switchStmt ) { 1355 GuardValue( currentObject ); 1356 switchStmt = ast::mutate_field( 1357 switchStmt, &ast::SwitchStmt::cond, 1358 findIntegralExpression( switchStmt->cond, symtab ) ); 1359 currentObject = ast::CurrentObject{ switchStmt->location, switchStmt->cond->result }; 1360 return switchStmt; 1361 } 1362 1363 const ast::CaseStmt * Resolver_new::previsit( const ast::CaseStmt * caseStmt ) { 1364 if ( caseStmt->cond ) { 1365 std::vector< ast::InitAlternative > initAlts = currentObject.getOptions(); 1366 assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral " 1367 "expression." ); 1368 1369 const ast::Expr * untyped = 1370 new ast::CastExpr{ caseStmt->location, caseStmt->cond, initAlts.front().type }; 1371 ast::ptr< ast::Expr > newExpr = findKindExpression( untyped, symtab ); 1372 1373 // case condition cannot have a cast in C, so it must be removed here, regardless of 1374 // whether it would perform a conversion. 1375 if ( const ast::CastExpr * castExpr = newExpr.as< ast::CastExpr >() ) { 1376 ast::ptr< ast::TypeSubstitution > env = castExpr->env; 1377 newExpr.set_and_mutate( castExpr->arg )->env = env; 1378 } 1379 1380 caseStmt = ast::mutate_field( caseStmt, &ast::CaseStmt::cond, newExpr ); 1381 } 1382 return caseStmt; 1383 } 1384 1385 const ast::BranchStmt * Resolver_new::previsit( const ast::BranchStmt * branchStmt ) { 1386 visit_children = false; 1387 // must resolve the argument of a computed goto 1388 if ( branchStmt->kind == ast::BranchStmt::Goto && branchStmt->computedTarget ) { 1389 // computed goto argument is void* 1390 branchStmt = ast::mutate_field( 1391 branchStmt, &ast::BranchStmt::computedTarget, 1392 findSingleExpression( 1393 branchStmt->computedTarget, new ast::PointerType{ new ast::VoidType{} }, 1394 symtab ) ); 1395 } 1396 return branchStmt; 1397 } 1398 1399 const ast::ReturnStmt * Resolver_new::previsit( const ast::ReturnStmt * returnStmt ) { 1400 visit_children = false; 1401 if ( returnStmt->expr ) { 1402 returnStmt = ast::mutate_field( 1403 returnStmt, &ast::ReturnStmt::expr, 1404 findSingleExpression( returnStmt->expr, functionReturn, symtab ) ); 1405 } 1406 return returnStmt; 1407 } 1408 1409 const ast::ThrowStmt * Resolver_new::previsit( const ast::ThrowStmt * throwStmt ) { 1410 visit_children = false; 1411 if ( throwStmt->expr ) { 1412 const ast::StructDecl * exceptionDecl = 1413 symtab.lookupStruct( "__cfaabi_ehm__base_exception_t" ); 1414 assert( exceptionDecl ); 1415 ast::ptr< ast::Type > exceptType = 1416 new ast::PointerType{ new ast::StructInstType{ exceptionDecl } }; 1417 throwStmt = ast::mutate_field( 1418 throwStmt, &ast::ThrowStmt::expr, 1419 findSingleExpression( throwStmt->expr, exceptType, symtab ) ); 1420 } 1421 return throwStmt; 1422 } 1423 1424 const ast::CatchStmt * Resolver_new::previsit( const ast::CatchStmt * catchStmt ) { 1425 if ( catchStmt->cond ) { 1426 ast::ptr< ast::Type > boolType = new ast::BasicType{ ast::BasicType::Bool }; 1427 catchStmt = ast::mutate_field( 1428 catchStmt, &ast::CatchStmt::cond, 1429 findSingleExpression( catchStmt->cond, boolType, symtab ) ); 1430 } 1431 return catchStmt; 1298 1432 } 1299 1433
Note:
See TracChangeset
for help on using the changeset viewer.