/* * This file is part of the Cforall project * * $Id: CastCost.cc,v 1.11 2005/08/29 20:14:15 rcbilson Exp $ * */ #include "typeops.h" #include "Cost.h" #include "ConversionCost.h" #include "SynTree/Type.h" #include "SynTree/Visitor.h" #include "SymTab/Indexer.h" namespace ResolvExpr { class CastCost : public ConversionCost { public: CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ); virtual void visit(BasicType *basicType); virtual void visit(PointerType *pointerType); }; Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) { // std::cout << "casting" << std::endl; // src->print( std::cout, 8 ); // std::cout << std::endl << "to" << std::endl; // dest->print( std::cout, 8 ); if( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) { EqvClass eqvClass; NamedTypeDecl *namedType; if( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) { return castCost( src, eqvClass.type, indexer, env ); } else if( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) { TypeDecl *type = dynamic_cast< TypeDecl* >( namedType ); // all typedefs should be gone by this point assert( type ); if( type->get_base() ) { return castCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 ); } } } if( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) { // std::cout << "types are compatible" << std::endl; return Cost( 0, 0, 0 ); } else if( dynamic_cast< VoidType* >( dest ) ) { // std::cout << "destination is void" << std::endl; return Cost( 0, 0, 1 ); } else { CastCost converter( dest, indexer, env ); src->accept( converter ); // std::cout << "cost is " << converter.get_cost() << std::endl; if( converter.get_cost() == Cost::infinity ) { return Cost::infinity; } else { return converter.get_cost() + Cost( 0, 0, 0 ); } } } CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) : ConversionCost( dest, indexer, env ) { } void CastCost::visit(BasicType *basicType) { if( dynamic_cast< PointerType* >( dest ) ) { cost = Cost( 1, 0, 0 ); } else { ConversionCost::visit( basicType ); } } void CastCost::visit(PointerType *pointerType) { if( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) { if( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) { cost = Cost( 0, 0, 1 ); } else if( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) { if( destAsBasic->isInteger() ) { cost = Cost( 1, 0, 0 ); } } else { TypeEnvironment newEnv( env ); newEnv.add( pointerType->get_forall() ); newEnv.add( pointerType->get_base()->get_forall() ); int assignResult = ptrsCastable( pointerType->get_base(), destAsPtr->get_base(), newEnv, indexer ); if( assignResult > 0 ) { cost = Cost( 0, 0, 1 ); } else if( assignResult < 0 ) { cost = Cost( 1, 0, 0 ); } } } } } // namespace ResolvExpr