def is_same_return_type( f1, f2 ): #covariant returns #The return type of an overriding function shall be either identical to the #return type of the overridden function or covariant with the classes of the #functions. If a function D::f overrides a function B::f, the return types #of the functions are covariant if they satisfy the following criteria: #* both are pointers to classes or references to classes #* the class in the return type of B::f is the same class as the class in # the return type of D::f or, is an unambiguous direct or indirect base # class of the class in the return type of D::f and is accessible in D #* both pointers or references have the same cv-qualification and the class # type in the return type of D::f has the same cv-qualification as or less # cv-qualification than the class type in the return type of B::f. if not f1.__class__ is f2.__class__: #it should be assert return False #2 different calldef types if not isinstance( f1, calldef.member_calldef_t ): #for free functions we compare return types as usual return type_traits.is_same( f1.return_type, f2.return_type) if f1.virtuality == calldef.VIRTUALITY_TYPES.NOT_VIRTUAL \ or f2.virtuality == calldef.VIRTUALITY_TYPES.NOT_VIRTUAL: #for non-virtual member functions we compare types as usual return type_traits.is_same( f1.return_type, f2.return_type) rt1 = f1.return_type rt2 = f2.return_type if type_traits.is_pointer( rt1 ) and type_traits.is_pointer( rt2 ): rt1 = type_traits.remove_pointer( rt1 ) rt2 = type_traits.remove_pointer( rt2 ) elif type_traits.is_reference( rt1 ) and type_traits.is_reference( rt2 ): rt1 = type_traits.remove_reference( rt1 ) rt2 = type_traits.remove_reference( rt2 ) else: return type_traits.is_same( f1.return_type, f2.return_type) if ( type_traits.is_const( rt1 ) and type_traits.is_const( rt2 ) ) \ or ( False == type_traits.is_const( rt1 ) and False == type_traits.is_const( rt2 ) ): rt1 = type_traits.remove_const( rt1 ) rt2 = type_traits.remove_const( rt2 ) else: return False if not type_traits.is_class( rt1 ) or not type_traits.is_class( rt2 ): return type_traits.is_same( rt1, rt2 ) c1 = type_traits.class_traits.get_declaration( rt1 ) c2 = type_traits.class_traits.get_declaration( rt2 ) if c1.class_type == class_declaration.CLASS_TYPES.UNION \ or c2.class_type == class_declaration.CLASS_TYPES.UNION: return type_traits.is_same( rt1, rt2 ) return type_traits.is_same( c1, c2 ) \ or type_traits.is_base_and_derived( c1, c2 ) \ or type_traits.is_base_and_derived( c2, c1 )
def is_same_return_type(f1, f2): #covariant returns #The return type of an overriding function shall be either identical to the #return type of the overridden function or covariant with the classes of the #functions. If a function D::f overrides a function B::f, the return types #of the functions are covariant if they satisfy the following criteria: #* both are pointers to classes or references to classes #* the class in the return type of B::f is the same class as the class in # the return type of D::f or, is an unambiguous direct or indirect base # class of the class in the return type of D::f and is accessible in D #* both pointers or references have the same cv-qualification and the class # type in the return type of D::f has the same cv-qualification as or less # cv-qualification than the class type in the return type of B::f. if not f1.__class__ is f2.__class__: #it should be assert return False #2 different calldef types if not isinstance(f1, calldef.member_calldef_t): #for free functions we compare return types as usual return type_traits.is_same(f1.return_type, f2.return_type) if f1.virtuality == calldef.VIRTUALITY_TYPES.NOT_VIRTUAL \ or f2.virtuality == calldef.VIRTUALITY_TYPES.NOT_VIRTUAL: #for non-virtual member functions we compare types as usual return type_traits.is_same(f1.return_type, f2.return_type) rt1 = f1.return_type rt2 = f2.return_type if type_traits.is_pointer(rt1) and type_traits.is_pointer(rt2): rt1 = type_traits.remove_pointer(rt1) rt2 = type_traits.remove_pointer(rt2) elif type_traits.is_reference(rt1) and type_traits.is_reference(rt2): rt1 = type_traits.remove_reference(rt1) rt2 = type_traits.remove_reference(rt2) else: return type_traits.is_same(f1.return_type, f2.return_type) if ( type_traits.is_const( rt1 ) and type_traits.is_const( rt2 ) ) \ or ( False == type_traits.is_const( rt1 ) and False == type_traits.is_const( rt2 ) ): rt1 = type_traits.remove_const(rt1) rt2 = type_traits.remove_const(rt2) else: return False if not type_traits.is_class(rt1) or not type_traits.is_class(rt2): return type_traits.is_same(rt1, rt2) c1 = type_traits.class_traits.get_declaration(rt1) c2 = type_traits.class_traits.get_declaration(rt2) if c1.class_type == class_declaration.CLASS_TYPES.UNION \ or c2.class_type == class_declaration.CLASS_TYPES.UNION: return type_traits.is_same(rt1, rt2) return type_traits.is_same( c1, c2 ) \ or type_traits.is_base_and_derived( c1, c2 ) \ or type_traits.is_base_and_derived( c2, c1 )
def find_noncopyable_vars( self ): """returns list of all `noncopyable` variables""" import type_traits as tt#prevent cyclic dependencies logger = utils.loggers.cxx_parser mvars = self.vars( lambda v: not v.type_qualifiers.has_static, recursive=False, allow_empty=True ) noncopyable_vars = [] for mvar in mvars: type_ = tt.remove_reference( mvar.type ) if tt.is_const( type_ ): no_const = tt.remove_const( type_ ) if tt.is_fundamental( no_const ) or tt.is_enum( no_const): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - fundamental or enum" % self.decl_string ) noncopyable_vars.append( mvar ) if tt.is_class( no_const ): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - class" % self.decl_string ) noncopyable_vars.append( mvar ) if tt.is_array( no_const ): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - array" % self.decl_string ) noncopyable_vars.append( mvar ) if tt.class_traits.is_my_case( type_ ): cls = tt.class_traits.get_declaration( type_ ) if tt.is_noncopyable( cls ): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes member variable - class that is not copyable" % self.decl_string ) noncopyable_vars.append( mvar ) logger.debug( "__contains_noncopyable_mem_var - %s - false - doesn't contains noncopyable members" % self.decl_string ) return noncopyable_vars
def find_noncopyable_vars(self): """returns list of all noncopyable variables""" import type_traits as tt #prevent cyclic dependencies logger = utils.loggers.cxx_parser mvars = self.vars(lambda v: not v.type_qualifiers.has_static, recursive=False, allow_empty=True) noncopyable_vars = [] for mvar in mvars: type_ = tt.remove_reference(mvar.type) if tt.is_const(type_): no_const = tt.remove_const(type_) if tt.is_fundamental(no_const) or tt.is_enum(no_const): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - fundamental or enum" % self.decl_string) noncopyable_vars.append(mvar) if tt.is_class(no_const): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - class" % self.decl_string) noncopyable_vars.append(mvar) if tt.is_array(no_const): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - array" % self.decl_string) noncopyable_vars.append(mvar) if tt.class_traits.is_my_case(type_): cls = tt.class_traits.get_declaration(type_) if tt.is_noncopyable(cls): logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes member variable - class that is not copyable" % self.decl_string) noncopyable_vars.append(mvar) logger.debug( "__contains_noncopyable_mem_var - %s - false - doesn't contains noncopyable members" % self.decl_string) return noncopyable_vars