Changes in / [5b643ea:cef5bfc]
- Files:
-
- 6 deleted
- 3 edited
-
src/GenPoly/GenPoly.cpp (modified) (4 diffs)
-
src/ResolvExpr/CandidateFinder.cpp (modified) (5 diffs)
-
tests/.expect/poly-many-arsz.txt (deleted)
-
tests/array-collections/.expect/accordion.txt (deleted)
-
tests/array-collections/accordion.cfa (deleted)
-
tests/array-collections/dimexpr-match.hfa (modified) (1 diff)
-
tests/poly-many-arsz.cfa (deleted)
-
tests/raii/.expect/typeof-member.txt (deleted)
-
tests/raii/typeof-member.cfa (deleted)
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/GenPoly.cpp
r5b643ea rcef5bfc 27 27 #include "AST/Type.hpp" 28 28 #include "AST/TypeSubstitution.hpp" 29 #include "Common/Eval.hpp" // for eval30 29 #include "GenPoly/ErasableScopedMap.hpp" // for ErasableScopedMap<>::const_... 31 30 #include "ResolvExpr/Typeops.hpp" // for flatten … … 244 243 } // namespace 245 244 246 // This function, and its helpers following, have logic duplicated from247 // unification. The difference in context is that unification applies where248 // the types "must" match, while this variation applies to arbitrary type249 // pairs, when an optimization could apply if they happen to match. This250 // variation does not bind type variables. The helper functions support251 // the case for matching ArrayType.252 bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs );253 254 static bool exprsPolyCompatibleByStaticValue(255 const ast::Expr * e1, const ast::Expr * e2 ) {256 Evaluation r1 = eval(e1);257 Evaluation r2 = eval(e2);258 259 if ( !r1.hasKnownValue ) return false;260 if ( !r2.hasKnownValue ) return false;261 262 if ( r1.knownValue != r2.knownValue ) return false;263 264 return true;265 }266 267 static bool exprsPolyCompatible( ast::Expr const * lhs,268 ast::Expr const * rhs ) {269 type_index const lid = typeid(*lhs);270 type_index const rid = typeid(*rhs);271 if ( lid != rid ) return false;272 273 if ( exprsPolyCompatibleByStaticValue( lhs, rhs ) ) return true;274 275 if ( type_index(typeid(ast::CastExpr)) == lid ) {276 ast::CastExpr const * l = as<ast::CastExpr>(lhs);277 ast::CastExpr const * r = as<ast::CastExpr>(rhs);278 279 // inspect casts' target types280 if ( !typesPolyCompatible(281 l->result, r->result ) ) return false;282 283 // inspect casts' inner expressions284 return exprsPolyCompatible( l->arg, r->arg );285 286 } else if ( type_index(typeid(ast::VariableExpr)) == lid ) {287 ast::VariableExpr const * l = as<ast::VariableExpr>(lhs);288 ast::VariableExpr const * r = as<ast::VariableExpr>(rhs);289 290 assert(l->var);291 assert(r->var);292 293 // conservative: variable exprs match if their declarations are294 // represented by the same C++ AST object295 return (l->var == r->var);296 297 } else if ( type_index(typeid(ast::SizeofExpr)) == lid ) {298 ast::SizeofExpr const * l = as<ast::SizeofExpr>(lhs);299 ast::SizeofExpr const * r = as<ast::SizeofExpr>(rhs);300 301 assert((l->type != nullptr) ^ (l->expr != nullptr));302 assert((r->type != nullptr) ^ (r->expr != nullptr));303 if ( !(l->type && r->type) ) return false;304 305 // mutual recursion with type poly compatibility306 return typesPolyCompatible( l->type, r->type );307 308 } else {309 // All other forms compare on static value only, done earlier310 return false;311 }312 }313 314 245 bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs ) { 315 246 type_index const lid = typeid(*lhs); … … 325 256 326 257 // So remaining types can be examined case by case. 327 // Recurse through type structure (conditions duplicated from Unify.cpp).258 // Recurse through type structure (conditions borrowed from Unify.cpp). 328 259 329 260 if ( type_index(typeid(ast::BasicType)) == lid ) { … … 349 280 ast::ArrayType const * r = as<ast::ArrayType>(rhs); 350 281 351 if ( l->isVarLen != r->isVarLen ) return false;352 if ( (l->dimension != nullptr) != (r->dimension != nullptr) )353 return false;354 355 if ( l->dimension ) { 356 a ssert( r->dimension);357 // mutual recursion with expression poly compatibility358 if ( !exprsPolyCompatible(l->dimension, r->dimension) )282 if ( l->isVarLen ) { 283 if ( !r->isVarLen ) return false; 284 } else { 285 if ( r->isVarLen ) return false; 286 287 auto lc = l->dimension.as<ast::ConstantExpr>(); 288 auto rc = r->dimension.as<ast::ConstantExpr>(); 289 if ( lc && rc && lc->intValue() != rc->intValue() ) { 359 290 return false; 291 } 360 292 } 361 293 -
src/ResolvExpr/CandidateFinder.cpp
r5b643ea rcef5bfc 1241 1241 Cost minCastCost = Cost::infinity; 1242 1242 for ( CandidateRef & cand : finder.candidates ) { 1243 ast::ptr< ast::Type > fromType = cand->expr->result;1244 assert( fromType );1245 fromType = resolveTypeof( fromType, context );1246 fromType = adjustExprType( fromType, tenv, symtab );1247 1248 1243 ast::AssertionSet need( cand->need.begin(), cand->need.end() ), have; 1249 1244 ast::OpenVarSet open( cand->open ); … … 1255 1250 // subexpression results that are cast directly. The candidate is invalid if it 1256 1251 // has fewer results than there are types to cast to. 1257 int discardedValues = fromType->size() - toType->size();1252 int discardedValues = cand->expr->result->size() - toType->size(); 1258 1253 if ( discardedValues < 0 ) continue; 1259 1254 1260 1255 // unification run for side-effects 1261 unify( toType, fromType, cand->env, need, have, open );1256 unify( toType, cand->expr->result, cand->env, need, have, open ); 1262 1257 Cost thisCost = 1263 1258 (castExpr->isGenerated == ast::GeneratedFlag::GeneratedCast) 1264 ? conversionCost( fromType, toType, cand->expr->get_lvalue(), symtab, cand->env )1265 : castCost( fromType, toType, cand->expr->get_lvalue(), symtab, cand->env );1259 ? conversionCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ) 1260 : castCost( cand->expr->result, toType, cand->expr->get_lvalue(), symtab, cand->env ); 1266 1261 1267 1262 // Redefine enum cast 1268 auto argAsEnum = fromType.as<ast::EnumInstType>();1263 auto argAsEnum = cand->expr->result.as<ast::EnumInstType>(); 1269 1264 auto toAsEnum = toType.as<ast::EnumInstType>(); 1270 1265 if ( argAsEnum && toAsEnum && argAsEnum->name != toAsEnum->name ) { … … 1277 1272 PRINT( 1278 1273 std::cerr << "working on cast with result: " << toType << std::endl; 1279 std::cerr << "and expr type: " << fromType<< std::endl;1274 std::cerr << "and expr type: " << cand->expr->result << std::endl; 1280 1275 std::cerr << "env: " << cand->env << std::endl; 1281 1276 ) … … 1286 1281 // count one safe conversion for each value that is thrown away 1287 1282 thisCost.incSafe( discardedValues ); 1288 1289 // See Aaron Moss, page 47; this reasoning does not hold since implicit conversions1290 // can create the same resolution issue. The C intrinsic interpretations are pruned1291 // immediately for the lowest cost option regardless of result type. Related code in1292 // postvisit (UntypedExpr).1293 // Cast expression costs are updated now to use the general rules.1294 /*1295 1283 // select first on argument cost, then conversion cost 1296 1284 if ( cand->cost < minExprCost || ( cand->cost == minExprCost && thisCost < minCastCost ) ) { … … 1301 1289 // ambigious case, still output candidates to print in error message 1302 1290 if ( cand->cost == minExprCost && thisCost == minCastCost ) { 1303 */1304 cand->cost += thisCost;1305 if (cand->cost < minExprCost) {1306 minExprCost = cand->cost;1307 matches.clear();1308 }1309 if (cand->cost == minExprCost) {1310 1291 CandidateRef newCand = std::make_shared<Candidate>( 1311 1292 restructureCast( cand->expr, toType, castExpr->isGenerated ), 1312 copy( cand->env ), std::move( open ), std::move( need ), cand->cost );1293 copy( cand->env ), std::move( open ), std::move( need ), cand->cost + thisCost); 1313 1294 // currently assertions are always resolved immediately so this should have no effect. 1314 1295 // if this somehow changes in the future (e.g. delayed by indeterminate return type) -
tests/array-collections/dimexpr-match.hfa
r5b643ea rcef5bfc 15 15 // 16 16 // compiler=gcc -x c # pick one 17 // compiler=$ cfa17 // compiler=$fa 18 18 // 19 19 // test=dimexpr-match-c.cfa # pick one
Note:
See TracChangeset
for help on using the changeset viewer.