// // Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo // // The contents of this file are covered under the licence agreement in the // file "LICENCE" distributed with Cforall. // // TypeEquality.cc -- // // Author : Rob Schluntz // Created On : Tue Jul 07 16:28:29 2015 // Last Modified By : Rob Schluntz // Last Modified On : Mon Jul 20 14:16:11 2015 // Update Count : 37 // #include #include #include "Validate.h" #include "SynTree/Visitor.h" #include "SynTree/Type.h" #include "SynTree/Statement.h" #include "SynTree/TypeSubstitution.h" #include "Indexer.h" #include "TypeEquality.h" namespace SymTab { class TypeEquality : public Visitor { public: TypeEquality( Type * other, bool vlaErr ) : result( true ), other( other ), vlaErr( vlaErr ) {} bool result; private: virtual void visit( FunctionType *funcType ); virtual void visit( VoidType *voidType ); virtual void visit( BasicType *basicType ); virtual void visit( PointerType *pointerType ); virtual void visit( ArrayType *arrayType ); virtual void visit( StructInstType *structInst ); virtual void visit( UnionInstType *unionInst ); virtual void visit( EnumInstType *enumInst ); virtual void visit( TypeInstType *typeInst ); virtual void visit( VarArgsType *varArgsType ); virtual void visit( ZeroType *zeroType ); virtual void visit( OneType *oneType ); void handleQualifiers( Type * t ); Type * other; bool vlaErr; }; bool typeEquals( Type * t1, Type * t2, bool vlaErr ) { TypeEquality teq( t2, vlaErr ); t1->accept( teq ); return teq.result; } void TypeEquality::handleQualifiers( Type * t ) { result = result && t->get_qualifiers() == other->get_qualifiers(); } void TypeEquality::visit( VoidType *voidType ) { handleQualifiers( voidType ); if ( ! dynamic_cast< VoidType * >( other ) ) { result = false; } } void TypeEquality::visit( BasicType *basicType ) { handleQualifiers( basicType ); if ( BasicType * bt = dynamic_cast< BasicType * >( other ) ) { result = result && basicType->get_kind() == bt->get_kind(); } else { result = false; } } void TypeEquality::visit( PointerType *pointerType ) { handleQualifiers( pointerType ); if ( PointerType * pt = dynamic_cast< PointerType * >( other ) ) { other = pt->get_base(); pointerType->get_base()->accept( *this ); } else { result = false; } } void TypeEquality::visit( ArrayType *arrayType ) { handleQualifiers( arrayType ); if ( ArrayType * at = dynamic_cast< ArrayType * >( other ) ) { // to be equal, array types must both be VLA or both not VLA // and must both have a dimension expression or not have a dimension result = result && arrayType->get_isVarLen() == at->get_isVarLen() && ((arrayType->get_dimension() != 0 && at->get_dimension() != 0) || (arrayType->get_dimension() == 0 && at->get_dimension() == 0)); if ( vlaErr ) { // useful for comparing typedef types - in this case, we // want types to appear distinct if either is a VLA type if ( arrayType->get_isVarLen() || at->get_isVarLen() ) { result = false; } } if ( ! arrayType->get_isVarLen() && ! at->get_isVarLen() && arrayType->get_dimension() != 0 && at->get_dimension() != 0 ) { ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() ); ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( at->get_dimension() ); assert(ce1 && ce2); Constant * c1 = ce1->get_constant(); Constant * c2 = ce2->get_constant(); result = result && c1->get_value() == c2->get_value(); } other = at->get_base(); arrayType->get_base()->accept( *this ); } else { result = false; } } void TypeEquality::visit( FunctionType *funcType ) { handleQualifiers( funcType ); if ( FunctionType * ft = dynamic_cast< FunctionType * >( other ) ) { // function types must have the same number of return types // and parameters to be equivalent result = result && funcType->get_returnVals().size() == ft->get_returnVals().size() && funcType->get_parameters().size() == ft->get_parameters().size() && funcType->get_isVarArgs() == ft->get_isVarArgs(); std::list< DeclarationWithType * >::iterator it1, it2; // return types must be equivalent it1 = funcType->get_returnVals().begin(); it2 = ft->get_returnVals().begin(); for ( ; it1 != funcType->get_returnVals().end(); ++it1, ++it2 ) { if ( ! result ) return; other = (*it2)->get_type(); (*it1)->get_type()->accept( *this ); } // parameter types must be equivalent it1 = funcType->get_parameters().begin(); it2 = ft->get_parameters().begin(); for ( ; it1 != funcType->get_parameters().end(); ++it1, ++it2 ) { if ( ! result ) return; other = (*it2)->get_type(); (*it1)->get_type()->accept( *this ); } } else { result = false; } } // aggregate types only need to have the same name void TypeEquality::visit( StructInstType *structInst ) { handleQualifiers( structInst ); if ( StructInstType * st = dynamic_cast< StructInstType * >( other ) ) { result = result && structInst->get_name() == st->get_name(); } else { result = false; } } void TypeEquality::visit( UnionInstType *unionInst ) { handleQualifiers( unionInst ); if ( UnionInstType * ut = dynamic_cast< UnionInstType * >( other ) ) { result = result && unionInst->get_name() == ut->get_name(); } else { result = false; } } void TypeEquality::visit( EnumInstType *enumInst ) { handleQualifiers( enumInst ); if ( EnumInstType * et = dynamic_cast< EnumInstType * >( other ) ) { result = result && enumInst->get_name() == et->get_name(); } else { result = false; } } void TypeEquality::visit( TypeInstType *typeInst ) { handleQualifiers( typeInst ); if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( other ) ) { result = result && typeInst->get_name() == tt->get_name(); } else { result = false; } } void TypeEquality::visit( VarArgsType *varArgsType ) { handleQualifiers( varArgsType ); if ( ! dynamic_cast< VarArgsType * >( other ) ) { result = false; } } void TypeEquality::visit( ZeroType *zeroType ) { handleQualifiers( zeroType ); if ( ! dynamic_cast< ZeroType * >( other ) ) { result = false; } } void TypeEquality::visit( OneType *oneType ) { handleQualifiers( oneType ); if ( ! dynamic_cast< OneType * >( other ) ) { result = false; } } } // namespace SymTab