Trees | Indices | Help |
|
---|
|
1 # Copyright 2004-2008 Roman Yakovenko. 2 # Distributed under the Boost Software License, Version 1.0. (See 3 # accompanying file LICENSE_1_0.txt or copy at 4 # http://www.boost.org/LICENSE_1_0.txt) 5 6 """ 7 defines few algorithms, that deals with different properties of C++ types 8 9 Do you aware of boost::type_traits library? pygccxml has functionality similar to 10 it. Using functions defined in this module you can 11 - find out some properties of the type 12 - modify type 13 14 Those functions are very valuable for code generation. Almost all functions 15 within this module works on L{type_t} class hierarchy and\\or L{class_t}. 16 """ 17 18 import os 19 import types 20 import matchers 21 import typedef 22 import calldef 23 import cpptypes 24 import variable 25 import algorithm 26 import namespace 27 import templates 28 import enumeration 29 import class_declaration 30 from pygccxml import utils 31 import types as build_in_types34 """implementation details""" 35 if isinstance( type_, typedef.typedef_t ): 36 return __remove_alias( type_.type ) 37 if isinstance( type_, cpptypes.declarated_t ) and isinstance( type_.declaration, typedef.typedef_t ): 38 return __remove_alias( type_.declaration.type ) 39 if isinstance( type_, cpptypes.compound_t ): 40 type_.base = __remove_alias( type_.base ) 41 return type_ 42 return type_4345 """returns type without typedefs""" 46 type_ref = None 47 if isinstance( type_, cpptypes.type_t ): 48 type_ref = type_ 49 elif isinstance( type_, typedef.typedef_t ): 50 type_ref = type_.type 51 else: 52 pass #not a valid input, just return it 53 if not type_ref: 54 return type_ 55 if type_ref.cache.remove_alias: 56 return type_ref.cache.remove_alias 57 no_alias = __remove_alias( type_ref.clone() ) 58 type_ref.cache.remove_alias = no_alias 59 return no_alias6062 """implementation details""" 63 return [ base 64 , cpptypes.const_t( base ) 65 , cpptypes.volatile_t( base ) 66 , cpptypes.volatile_t( cpptypes.const_t( base ) ) ]6769 """implementation details""" 70 #implementation of this function is important 71 if isinstance( tp, cpptypes.compound_t ): 72 return [tp] + decompose_type( tp.base ) 73 elif isinstance( tp, typedef.typedef_t ): 74 return decompose_type( tp.type ) 75 elif isinstance( tp, cpptypes.declarated_t ) and isinstance( tp.declaration, typedef.typedef_t ): 76 return decompose_type( tp.declaration.type ) 77 else: 78 return [tp]7981 """implementation details""" 82 types = decompose_type( type ) 83 return [ tp.__class__ for tp in types ]8486 """returns base type. 87 88 For C{const int} will return C{int} 89 """ 90 types = decompose_type( type ) 91 return types[-1]9294 """implementation details""" 95 assert isinstance( secondary, build_in_types.TupleType ) 96 assert 2 == len( secondary ) #general solution could be provided 97 types = decompose_type( given ) 98 if isinstance( types[0], main ): 99 return True 100 elif 2 <= len( types ) and \ 101 ( ( isinstance( types[0], main ) and isinstance( types[1], secondary ) ) \ 102 or ( isinstance( types[1], main ) and isinstance( types[0], secondary ) ) ): 103 return True 104 elif 3 <= len( types ): 105 classes = set( [tp.__class__ for tp in types[:3]] ) 106 desired = set( [main] + list( secondary ) ) 107 return classes == desired 108 else: 109 return False110112 """returns True, if type represents C{bool}, False otherwise""" 113 return remove_alias( type_ ) in create_cv_types( cpptypes.bool_t() )114116 """returns True, if type represents C{void}, False otherwise""" 117 return remove_alias( type ) in create_cv_types( cpptypes.void_t() )118120 """returns True, if type represents C{void*}, False otherwise""" 121 return is_same( type, cpptypes.pointer_t( cpptypes.void_t() ) )122124 """returns True, if type represents C++ integral type, False otherwise""" 125 integral_def = create_cv_types( cpptypes.char_t() ) \ 126 + create_cv_types( cpptypes.unsigned_char_t() ) \ 127 + create_cv_types( cpptypes.signed_char_t() ) \ 128 + create_cv_types( cpptypes.wchar_t() ) \ 129 + create_cv_types( cpptypes.short_int_t() ) \ 130 + create_cv_types( cpptypes.short_unsigned_int_t() ) \ 131 + create_cv_types( cpptypes.bool_t() ) \ 132 + create_cv_types( cpptypes.int_t() ) \ 133 + create_cv_types( cpptypes.unsigned_int_t() ) \ 134 + create_cv_types( cpptypes.long_int_t() ) \ 135 + create_cv_types( cpptypes.long_unsigned_int_t() ) \ 136 + create_cv_types( cpptypes.long_long_int_t() ) \ 137 + create_cv_types( cpptypes.long_long_unsigned_int_t() ) 138 139 return remove_alias( type ) in integral_def140142 """returns True, if type represents C++ floating point type, False otherwise""" 143 float_def = create_cv_types( cpptypes.float_t() ) \ 144 + create_cv_types( cpptypes.double_t() ) \ 145 + create_cv_types( cpptypes.long_double_t() ) 146 147 return remove_alias( type ) in float_def148150 """returns True, if type represents C++ integral or floating point type, False otherwise""" 151 return is_integral( type ) or is_floating_point( type )152154 """returns True, if type represents C++ pointer type, False otherwise""" 155 return does_match_definition( type 156 , cpptypes.pointer_t 157 , (cpptypes.const_t, cpptypes.volatile_t) )158160 """returns True, if type represents pointer to free/member function, False otherwise""" 161 if not is_pointer(type): 162 return False 163 nake_type = remove_alias( type ) 164 nake_type = remove_const( nake_type ) 165 nake_type = remove_volatile( nake_type ) 166 return isinstance( nake_type, cpptypes.compound_t ) \ 167 and isinstance( nake_type.base, cpptypes.calldef_type_t )168170 """removes pointer from the type definition 171 172 If type is not pointer type, it will be returned as is. 173 """ 174 nake_type = remove_alias( type ) 175 if not is_pointer( nake_type ): 176 return type 177 elif isinstance( nake_type, cpptypes.volatile_t ) and isinstance( nake_type.base, cpptypes.pointer_t ): 178 return cpptypes.volatile_t( nake_type.base.base ) 179 elif isinstance( nake_type, cpptypes.const_t ) and isinstance( nake_type.base, cpptypes.pointer_t ): 180 return cpptypes.const_t( nake_type.base.base ) 181 elif isinstance( nake_type.base, cpptypes.calldef_type_t ): 182 return type 183 else: 184 return nake_type.base185187 """returns True, if type represents C++ reference type, False otherwise""" 188 nake_type = remove_alias( type ) 189 return isinstance( nake_type, cpptypes.reference_t )190192 """returns True, if type represents C++ array type, False otherwise""" 193 nake_type = remove_alias( type ) 194 nake_type = remove_reference( nake_type ) 195 nake_type = remove_cv( nake_type ) 196 return isinstance( nake_type, cpptypes.array_t )197199 """returns array size""" 200 nake_type = remove_alias( type ) 201 nake_type = remove_reference( nake_type ) 202 nake_type = remove_cv( nake_type ) 203 assert isinstance( nake_type, cpptypes.array_t ) 204 return nake_type.size205207 """returns array item type""" 208 if is_array(type_): 209 type_ = remove_alias( type_ ) 210 type_ = remove_cv( type_ ) 211 return type_.base 212 elif is_pointer( type_ ): 213 return remove_pointer( type_ ) 214 else: 215 assert 0216218 """removes reference from the type definition 219 220 If type is not reference type, it will be returned as is. 221 """ 222 nake_type = remove_alias( type ) 223 if not is_reference( nake_type ): 224 return type 225 else: 226 return nake_type.base227229 """returns True, if type represents C++ const type, False otherwise""" 230 nake_type = remove_alias( type ) 231 return isinstance( nake_type, cpptypes.const_t )232234 """removes const from the type definition 235 236 If type is not const type, it will be returned as is 237 """ 238 239 nake_type = remove_alias( type ) 240 if not is_const( nake_type ): 241 return type 242 else: 243 return nake_type.base244246 """removes type-declaration class-binder L{declarated_t} from the type 247 248 If type is not L{declarated_t}, it will be returned as is 249 """ 250 type = remove_alias( type ) 251 if isinstance( type, cpptypes.declarated_t ): 252 type = type.declaration 253 return type254256 """returns True, if type1 and type2 are same types""" 257 nake_type1 = remove_declarated( type1 ) 258 nake_type2 = remove_declarated( type2 ) 259 return nake_type1 == nake_type2260262 """returns True, if type represents C++ volatile type, False otherwise""" 263 nake_type = remove_alias( type ) 264 return isinstance( nake_type, cpptypes.volatile_t )265267 """removes volatile from the type definition 268 269 If type is not volatile type, it will be returned as is 270 """ 271 nake_type = remove_alias( type ) 272 if not is_volatile( nake_type ): 273 return type 274 else: 275 return nake_type.base276278 """removes const and volatile from the type definition""" 279 280 nake_type = remove_alias(type) 281 if not is_const( nake_type ) and not is_volatile( nake_type ): 282 return type 283 result = nake_type 284 if is_const( nake_type ): 285 result = nake_type.base 286 if is_volatile( result ): 287 result = result.base 288 return result289291 """returns True, if type represents C++ fundamental type""" 292 return does_match_definition( type 293 , cpptypes.fundamental_t 294 , (cpptypes.const_t, cpptypes.volatile_t) )295297 """this class implements the functionality needed for convinient work with 298 declaration classes 299 300 Implemented functionality: 301 - find out whether a declaration is a desired one 302 - get reference to the declaration 303 """ 304 sequence = [ remove_alias, remove_cv, remove_declarated ] 307 312324 325 enum_traits = declaration_xxx_traits( enumeration.enumeration_t ) 326 """implements functionality, needed for convinient work with C++ enums""" 327 328 is_enum = enum_traits.is_my_case 329 """returns True, if type represents C++ enumeration declaration, False otherwise""" 330 331 enum_declaration = enum_traits.get_declaration 332 """returns reference to enum declaration""" 333 334 class_traits = declaration_xxx_traits( class_declaration.class_t ) 335 """implements functionality, needed for convinient work with C++ classes""" 336 337 is_class = class_traits.is_my_case 338 """returns True, if type represents C++ class definition, False otherwise""" 339 340 class_declaration_traits = declaration_xxx_traits( class_declaration.class_declaration_t ) 341 """implements functionality, needed for convinient work with C++ class declarations""" 342 343 is_class_declaration = class_declaration_traits.is_my_case 344 """returns True, if type represents C++ class declaration, False otherwise"""314 """returns True, if type represents the desired declaration, False otherwise""" 315 return isinstance( self.__apply_sequence( type ), self.declaration_class )316318 """returns reference to the declaration 319 320 Precondition: self.is_my_case( type ) == True 321 """ 322 assert self.is_my_case( type ) 323 return self.__apply_sequence( type )347 """returns reference to trivial constructor or None""" 348 assert isinstance( type, class_declaration.class_t ) 349 return type.find_trivial_constructor()350352 """if class has public trivial constructor, this function will return reference to it, None otherwise""" 353 class_ = class_traits.get_declaration( class_ ) 354 trivial = class_.find_trivial_constructor() 355 if trivial and trivial.access_type == 'public': 356 return trivial357359 """if class has public copy constructor, this function will return reference to it, None otherwise""" 360 class_ = class_traits.get_declaration( class_ ) 361 copy_constructor = class_.find_copy_constructor() 362 if copy_constructor and copy_constructor.access_type == 'public': 363 return copy_constructor364366 """if class has destructor, this function will return reference to it, None otherwise""" 367 class_ = class_traits.get_declaration( class_ ) 368 destructor = class_.decls( decl_type=calldef.destructor_t, recursive=False, allow_empty=True ) 369 if destructor: 370 return destructor[0]371373 """if class has any public constructor, this function will return list of them, otherwise None""" 374 class_ = class_traits.get_declaration(class_) 375 decls = class_.constructors( lambda c: not c.is_copy_constructor and c.access_type == 'public' 376 , recursive=False, allow_empty=True ) 377 if decls: 378 return decls379381 """returns True, if class has public assign operator, False otherwise""" 382 class_ = class_traits.get_declaration( class_ ) 383 decls = class_.mem_opers( lambda o: o.symbol == '=' and o.access_type == 'public' 384 , recursive=False, allow_empty=True ) 385 return bool( decls )386388 """returns True, if class has public destructor, False otherwise""" 389 d = has_destructor( type ) 390 return d and d.access_type == 'public'391393 """returns True, if there is "base and derived" relationship between classes, False otherwise""" 394 assert isinstance( based, class_declaration.class_t ) 395 assert isinstance( derived, ( class_declaration.class_t, tuple ) ) 396 397 all_derived = None 398 if isinstance( derived, class_declaration.class_t ): 399 all_derived = ( [derived] ) 400 else: #tuple 401 all_derived = derived 402 403 for derived_cls in all_derived: 404 for base_desc in derived_cls.recursive_bases: 405 if base_desc.related_class == based: 406 return True 407 return False408410 """if class has any public constructor, which is not copy constructor, this function will return list of them, otherwise None""" 411 class_ = class_traits.get_declaration( type ) 412 decls = class_.constructors( lambda c: not c.is_copy_constructor and c.access_type == 'public' 413 , recursive=False, allow_empty=True ) 414 if decls: 415 return decls416418 """returns True, if type has public binary operator, otherwise False""" 419 not_artificial = lambda decl: decl.is_artificial == False 420 type = remove_alias( type ) 421 type = remove_cv( type ) 422 type = remove_declarated( type ) 423 assert isinstance( type, class_declaration.class_t ) 424 425 if is_std_string( type ) or is_std_wstring( type ): 426 #In some case compare operators of std::basic_string are not instantiated 427 return True 428 429 operators = type.member_operators( function=matchers.custom_matcher_t( not_artificial ) \ 430 & matchers.access_type_matcher_t( 'public' ) 431 , symbol=operator_symbol 432 , allow_empty=True 433 , recursive=False ) 434 if operators: 435 return True 436 437 t = cpptypes.declarated_t( type ) 438 t = cpptypes.const_t( t ) 439 t = cpptypes.reference_t( t ) 440 operators = type.top_parent.operators( function=not_artificial 441 , arg_types=[t, None] 442 , symbol=operator_symbol 443 , allow_empty=True 444 , recursive=True ) 445 if operators: 446 return True 447 for bi in type.recursive_bases: 448 assert isinstance( bi, class_declaration.hierarchy_info_t ) 449 if bi.access_type != class_declaration.ACCESS_TYPES.PUBLIC: 450 continue 451 operators = bi.related_class.member_operators( function=matchers.custom_matcher_t( not_artificial ) \ 452 & matchers.access_type_matcher_t( 'public' ) 453 , symbol=operator_symbol 454 , allow_empty=True 455 , recursive=False ) 456 if operators: 457 return True 458 return False459461 """returns True, if class has public operator==, otherwise False""" 462 return has_public_binary_operator( type, '==' )463465 """returns True, if class has public operator<, otherwise False""" 466 return has_public_binary_operator( type, '<' )467469 """returns True, if operator is unary operator, otherwise False""" 470 #~ definition: 471 #~ memeber in class 472 #~ ret-type operator symbol() 473 #~ ret-type operator [++ --](int) 474 #~ globally 475 #~ ret-type operator symbol( arg ) 476 #~ ret-type operator [++ --](X&, int) 477 symbols = [ '!', '&', '~', '*', '+', '++', '-', '--' ] 478 if not isinstance( oper, calldef.operator_t ): 479 return False 480 if oper.symbol not in symbols: 481 return False 482 if isinstance( oper, calldef.member_operator_t ): 483 if 0 == len( oper.arguments ): 484 return True 485 elif oper.symbol in [ '++', '--' ] and isinstance( oper.arguments[0].type, cpptypes.int_t ): 486 return True 487 else: 488 return False 489 else: 490 if 1 == len( oper.arguments ): 491 return True 492 elif oper.symbol in [ '++', '--' ] \ 493 and 2 == len( oper.arguments ) \ 494 and isinstance( oper.arguments[1].type, cpptypes.int_t ): 495 #may be I need to add additional check whether first argument is reference or not? 496 return True 497 else: 498 return False499501 """returns True, if operator is binary operator, otherwise False""" 502 #~ definition: 503 #~ memeber in class 504 #~ ret-type operator symbol(arg) 505 #~ globally 506 #~ ret-type operator symbol( arg1, arg2 ) 507 symbols = [ ',', '()', '[]', '!=', '%', '%=', '&', '&&', '&=', '*', '*=', '+', '+=' 508 , '-', '-=', '->', '->*', '/', '/=', '<', '<<', '<<=', '<=' 509 , '=', '==', '>', '>=', '>>', '>>=', '^', '^=', '|', '|=', '||' 510 ] 511 if not isinstance( oper, calldef.operator_t ): 512 return False 513 if oper.symbol not in symbols: 514 return False 515 if isinstance( oper, calldef.member_operator_t ): 516 if 1 == len( oper.arguments ): 517 return True 518 else: 519 return False 520 else: 521 if 2 == len( oper.arguments ): 522 return True 523 else: 524 return False525527 """implementation details""" 531798533 found = algorithm.find_declaration( class_decl.parent.declarations 534 , name=class_decl.name 535 , type=class_declaration.class_t ) 536 return found537539 type_ = remove_alias( type_ ) 540 bt_of_type = base_type( type_ ) 541 if isinstance( bt_of_type, cpptypes.declarated_t ) \ 542 and isinstance( bt_of_type.declaration, class_declaration.class_declaration_t ): 543 type_ = type_.clone() 544 bt_of_type = base_type( type_ ) 545 bt_of_type.declaration = self.__find_class_by_class_declaration( bt_of_type.declaration ) 546 return type_547549 if not ( source and target ): 550 return False 551 if is_same( source, target ): 552 return True #X => X 553 if is_const( target ) and is_same( source, target.base ): 554 return True #X => const X 555 if is_reference( target ) and is_same( source, target.base ): 556 return True #X => X& 557 if is_reference( target ) and is_const( target.base ) and is_same( source, target.base.base ): 558 return True #X => const X& 559 if is_same( target, cpptypes.pointer_t( cpptypes.void_t() ) ): 560 if is_integral( source ) or is_enum( source ): 561 return False 562 else: 563 return True #X => void* 564 if is_pointer( source ) and is_pointer( target ): 565 if is_const( target.base ) and is_same( source.base, target.base.base ): 566 return True#X* => const X* 567 if is_reference( source ) and is_reference( target ): 568 if is_const( target.base ) and is_same( source.base, target.base.base ): 569 return True#X& => const X& 570 if not is_const( source ) and is_array( source ) and is_pointer( target ): 571 if is_same( base_type(source), target.base ): 572 return True#X[2] => X* 573 if is_array( source ) and is_pointer( target ) and is_const( target.base ): 574 if is_same( base_type(source), target.base.base ): 575 return True576578 if is_pointer( source ) \ 579 and is_reference( target ) \ 580 and isinstance( target.base 581 , ( cpptypes.free_function_type_t 582 , cpptypes.member_function_type_t 583 , cpptypes.member_variable_type_t ) ) \ 584 and is_same( source.base, target.base ): 585 return True 586 587 if is_pointer( source ) \ 588 and isinstance( target 589 , ( cpptypes.free_function_type_t 590 , cpptypes.member_function_type_t 591 , cpptypes.member_variable_type_t ) ) \ 592 and is_same( source.base, target ): 593 return True 594 595 if is_pointer( target ) \ 596 and is_reference( source ) \ 597 and isinstance( source.base 598 , ( cpptypes.free_function_type_t 599 , cpptypes.member_function_type_t 600 , cpptypes.member_variable_type_t ) ) \ 601 and is_same( source.base, target.base ): 602 return True 603 604 if is_pointer( target ) \ 605 and isinstance( source 606 , ( cpptypes.free_function_type_t 607 , cpptypes.member_function_type_t 608 , cpptypes.member_variable_type_t ) ) \ 609 and is_same( target.base, source ): 610 return True611 612614 if not is_reference( source ) \ 615 or not is_const( source.base ) \ 616 or not is_same( source.base.base, target ): 617 return False 618 if is_fundamental( target ): 619 return True 620 if is_enum( target ): 621 return True 622 if isinstance( target, cpptypes.declarated_t ): 623 assert isinstance( target.declaration, class_declaration.class_t ) 624 if has_copy_constructor( target.declaration ): 625 return True #we have copy constructor 626 return False627629 if not is_reference( source ) or not is_const( source.base ): 630 return False 631 if is_fundamental( source.base.base ) and is_fundamental( target ): 632 return True 633 if is_convertible( source.base.base, cpptypes.int_t() ) and is_enum( target ): 634 return True 635 if isinstance( target, cpptypes.declarated_t ): 636 assert isinstance( target.declaration, class_declaration.class_t ) 637 if has_copy_constructor( target.declaration ): 638 return True #we have copy constructor 639 return False640642 if not is_reference( source ) or not is_same( source.base, target ): 643 return False 644 if is_fundamental( target ): 645 return True 646 if is_enum( target ): 647 return True 648 if isinstance( target, cpptypes.declarated_t ): 649 assert isinstance( target.declaration, class_declaration.class_t ) 650 if has_copy_constructor( target.declaration ): 651 return True #we have copy constructor 652 return False653655 if not is_reference( source ): 656 return False 657 if is_fundamental( source.base ) and is_fundamental( target ): 658 return True 659 if is_convertible( source.base, cpptypes.int_t() ) and is_enum( target ): 660 return True 661 if isinstance( target, cpptypes.declarated_t ): 662 assert isinstance( target.declaration, class_declaration.class_t ) 663 if has_copy_constructor( target.declaration ): 664 return True #we have copy constructor 665 return False666668 if not is_fundamental( base_type( source ) ) or not is_fundamental( base_type( target ) ): 669 return False 670 if is_void( base_type( source ) ) or is_void( base_type( target ) ): 671 return False 672 if is_fundamental( source ) and is_fundamental( target ): 673 return True 674 if not is_pointer( source ) and is_fundamental( target ): 675 return True 676 if not is_pointer( source ) and is_const( target ) and is_fundamental( target.base ): 677 return True 678 if is_fundamental( source ) \ 679 and is_reference( target ) \ 680 and is_const( target.base ) \ 681 and is_fundamental( target.base.base ): 682 return True #X => const Y& 683 return False684686 derived = base_type( source ) 687 base = base_type( target ) 688 if not ( isinstance( derived, cpptypes.declarated_t ) \ 689 and isinstance( derived.declaration, class_declaration.class_t ) ): 690 return False 691 if not ( isinstance( base, cpptypes.declarated_t ) \ 692 and isinstance( base.declaration, class_declaration.class_t ) ): 693 return False 694 base = base.declaration 695 derived = derived.declaration 696 if not is_base_and_derived( base, derived ): 697 return False 698 for b in derived.recursive_bases: 699 if ( b.related_class is base ) and b.access_type != class_declaration.ACCESS_TYPES.PRIVATE: 700 break 701 else: 702 return False 703 704 base = target 705 derived = source 706 is_both_declarated = lambda x, y: isinstance( x, cpptypes.declarated_t ) \ 707 and isinstance( y, cpptypes.declarated_t ) 708 #d => b 709 if is_both_declarated( base, derived ): 710 return True 711 #d* => b* 712 if is_pointer( derived ) and is_pointer( base ) \ 713 and is_both_declarated( base.base, derived.base ): 714 return True 715 #const d* => const b* 716 if is_pointer( derived ) and is_pointer( base ) \ 717 and is_const( derived.base ) and is_const( base.base ) \ 718 and is_both_declarated( base.base.base, derived.base.base ): 719 return True 720 #d* => const b* 721 if is_pointer( derived ) and is_pointer( base ) \ 722 and is_const( derived.base )\ 723 and is_both_declarated( base.base.base, derived.base ): 724 return True 725 726 #d& => b& 727 if is_reference( derived ) and is_reference( base ) \ 728 and is_both_declarated( base.base, derived.base ): 729 return True 730 #const d& => const b& 731 if is_reference( derived ) and is_reference( base ) \ 732 and is_const( derived.base ) and is_const( base.base ) \ 733 and is_both_declarated( base.base.base, derived.base.base ): 734 return True 735 #d& => const b& 736 if is_reference( derived ) and is_reference( base ) \ 737 and is_const( derived.base )\ 738 and is_both_declarated( base.base.base, derived.base ): 739 return True 740 return False741743 source = self.__source 744 target = self.__target 745 746 if self.__test_trivial(source, target): 747 return True 748 if is_array( source ) or is_array( target ): 749 return False 750 if self.__test_const_x_ref__to__x(source, target): 751 return True 752 if self.__test_const_ref_x__to__y(source, target): 753 return True 754 if self.__test_ref_x__to__x(source, target): 755 return True 756 if self.__test_ref_x__to__y(source, target): 757 return True 758 if self.__test_fundamental__to__fundamental( source, target ): 759 return True 760 if self.__test_pointer_to_func_or_mv__to__func_or_mv( source, target ): 761 return True 762 if self.__test_derived_to_based( source, target ): 763 return True 764 765 if isinstance( source, cpptypes.declarated_t ): 766 if isinstance( source.declaration, enumeration.enumeration_t ) \ 767 and is_fundamental( target ) \ 768 and not is_void( target ): 769 return True # enum could be converted to any integral type 770 771 if isinstance( source.declaration, class_declaration.class_t ): 772 source_inst = source.declaration 773 #class instance could be convertible to something else if it has operator 774 casting_operators = algorithm.find_all_declarations( source_inst.declarations 775 , type=calldef.casting_operator_t 776 , recursive=False ) 777 if casting_operators: 778 for operator in casting_operators: 779 if is_convertible( operator.return_type, target ): 780 return True 781 782 #may be target is class too, so in this case we should check whether is 783 #has constructor from source 784 if isinstance( target, cpptypes.declarated_t ): 785 if isinstance( target.declaration, class_declaration.class_t ): 786 constructors = algorithm.find_all_declarations( target.declaration.declarations 787 , type=calldef.constructor_t 788 , recursive=False ) 789 if constructors: 790 for constructor in constructors: 791 if 1 != len( constructor.arguments ): 792 continue 793 #TODO: add test to check explicitness 794 if is_convertible( source, constructor.arguments[0].type ): 795 return True 796 797 return False800 """returns True, if source could be converted to target, otherwise False""" 801 return __is_convertible_t( source, target ).is_convertible()802804 """implementation details""" 805 #It is not enough to check base classes, we should also to check 806 #member variables. 807 logger = utils.loggers.cxx_parser 808 809 if has_copy_constructor( class_ ) \ 810 and has_public_constructor( class_ ) \ 811 and has_public_assign( class_ ) \ 812 and has_public_destructor( class_ ): 813 msg = os.linesep.join([ 814 "__is_noncopyable_single - %s - COPYABLE:" % class_.decl_string 815 , " trivial copy constructor: yes" 816 , " public constructor: yes" 817 , " public assign: yes" 818 , " public destructor: yes" 819 ]) 820 logger.debug( msg ) 821 return False 822 if class_.find_noncopyable_vars(): 823 logger.debug( "__is_noncopyable_single(TRUE) - %s - contains noncopyable members" % class_.decl_string ) 824 return True 825 else: 826 logger.debug( "__is_noncopyable_single(FALSE) - %s - COPYABLE, because is doesn't contains noncopyable members" % class_.decl_string ) 827 return False828830 """returns True, if class is noncopyable, False otherwise""" 831 logger = utils.loggers.cxx_parser 832 class_ = class_traits.get_declaration( class_ ) 833 834 true_header = "is_noncopyable(TRUE) - %s - " % class_.decl_string 835 false_header = "is_noncopyable(false) - %s - " % class_.decl_string 836 837 if class_.class_type == class_declaration.CLASS_TYPES.UNION: 838 return False 839 840 if class_.is_abstract: 841 logger.debug( true_header + "abstract client" ) 842 return True 843 844 #if class has public, user defined copy constructor, than this class is 845 #copyable 846 copy_ = class_.find_copy_constructor() 847 if copy_ and copy_.access_type == 'public' and not copy_.is_artificial: 848 return False 849 850 for base_desc in class_.recursive_bases: 851 assert isinstance( base_desc, class_declaration.hierarchy_info_t ) 852 if base_desc.related_class.decl_string in ('::boost::noncopyable', '::boost::noncopyable_::noncopyable' ): 853 logger.debug( true_header + "derives from boost::noncopyable" ) 854 return True 855 if not has_copy_constructor( base_desc.related_class ): 856 base_copy_ = base_desc.related_class.find_copy_constructor() 857 if base_copy_: 858 if base_copy_.access_type == 'private': 859 logger.debug( true_header + "there is private copy constructor" ) 860 return True 861 else: 862 if __is_noncopyable_single( base_desc.related_class ): 863 logger.debug( true_header + "__is_noncopyable_single returned True" ) 864 return True 865 if __is_noncopyable_single( base_desc.related_class ): 866 logger.debug( true_header + "__is_noncopyable_single returned True" ) 867 return True 868 869 if not has_copy_constructor( class_ ): 870 logger.debug( true_header + "does not have trival copy constructor" ) 871 return True 872 elif not has_public_constructor( class_ ): 873 logger.debug( true_header + "does not have a public constructor" ) 874 return True 875 elif has_destructor( class_ ) and not has_public_destructor( class_ ): 876 logger.debug( true_header + "has private destructor") 877 return True 878 else: 879 return __is_noncopyable_single( class_ )880882 """small helper function, that checks whether class ( C{cls} ) is defined 883 under C{::xxx} namespace""" 884 if not cls.parent: 885 return False 886 887 if not isinstance( cls.parent, namespace.namespace_t ): 888 return False 889 890 if xxx != cls.parent.name: 891 return False 892 893 xxx_ns = cls.parent 894 if not xxx_ns.parent: 895 return False 896 897 if not isinstance( xxx_ns.parent, namespace.namespace_t ): 898 return False 899 900 if '::' != xxx_ns.parent.name: 901 return False 902 903 global_ns = xxx_ns.parent 904 return None is global_ns.parent905907 """implementation details""" 908 @staticmethod976910 """implementation details""" 911 if not cls.parent: 912 return False 913 914 if not isinstance( cls.parent, namespace.namespace_t ): 915 return False 916 917 if xxx != cls.parent.name: 918 return False 919 920 xxx_ns = cls.parent 921 if not xxx_ns.parent: 922 return False 923 924 if not isinstance( xxx_ns.parent, namespace.namespace_t ): 925 return False 926 927 if '::' != xxx_ns.parent.name: 928 return False 929 930 global_ns = xxx_ns.parent 931 return None is global_ns.parent932 933 @staticmethod935 """implementation details""" 936 if not value_type_str.startswith( '::' ): 937 value_type_str = '::' + value_type_str 938 found = global_ns.decls( name=value_type_str 939 , function=lambda decl: not isinstance( decl, calldef.calldef_t ) 940 , allow_empty=True ) 941 if not found: 942 no_global_ns_value_type_str = value_type_str[2:] 943 if cpptypes.FUNDAMENTAL_TYPES.has_key( no_global_ns_value_type_str ): 944 return cpptypes.FUNDAMENTAL_TYPES[ no_global_ns_value_type_str ] 945 elif is_std_string( value_type_str ): 946 string_ = global_ns.typedef( '::std::string' ) 947 return remove_declarated( string_ ) 948 elif is_std_wstring( value_type_str ): 949 string_ = global_ns.typedef( '::std::wstring' ) 950 return remove_declarated( string_ ) 951 else: 952 value_type_str = no_global_ns_value_type_str 953 has_const = value_type_str.startswith( 'const ' ) 954 if has_const: 955 value_type_str = value_type_str[ len('const '): ] 956 has_pointer = value_type_str.endswith( '*' ) 957 if has_pointer: 958 value_type_str = value_type_str[:-1] 959 found = None 960 if has_const or has_pointer: 961 found = impl_details.find_value_type( global_ns, value_type_str ) 962 if not found: 963 return None 964 else: 965 if isinstance( found, class_declaration.class_types ): 966 found = cpptypes.declarated_t( found ) 967 if has_const: 968 found = cpptypes.const_t( found ) 969 if has_pointer: 970 found = cpptypes.pointer_t( found ) 971 return found 972 if len( found ) == 1: 973 return found[0] 974 else: 975 return None978 """implements functionality, needed for convinient work with smart pointers""" 979 980 @staticmethod1010982 """returns True, if type represents instantiation of C{boost::shared_ptr}, False otherwise""" 983 type = remove_alias( type ) 984 type = remove_cv( type ) 985 type = remove_declarated( type ) 986 if not isinstance( type, ( class_declaration.class_declaration_t, class_declaration.class_t ) ): 987 return False 988 if not impl_details.is_defined_in_xxx( 'boost', type ): 989 return False 990 return type.decl_string.startswith( '::boost::shared_ptr<' )991 992 @staticmethod994 """returns reference to boost::shared_ptr value type""" 995 if not smart_pointer_traits.is_smart_pointer( type ): 996 raise TypeError( 'Type "%s" is not instantiation of boost::shared_ptr' % type.decl_string ) 997 type = remove_alias( type ) 998 cls = remove_cv( type ) 999 cls = remove_declarated( type ) 1000 if isinstance( cls, class_declaration.class_t ): 1001 return remove_declarated( cls.typedef( "value_type", recursive=False ).type ) 1002 elif not isinstance( cls, ( class_declaration.class_declaration_t, class_declaration.class_t ) ): 1003 raise RuntimeError( "Unable to find out shared_ptr value type. shared_ptr class is: %s" % cls.decl_string ) 1004 else: 1005 value_type_str = templates.args( cls.name )[0] 1006 ref = impl_details.find_value_type( cls.top_parent, value_type_str ) 1007 if None is ref: 1008 raise RuntimeError( "Unable to find out shared_ptr value type. shared_ptr class is: %s" % cls.decl_string ) 1009 return ref1012 """implements functionality, needed for convinient work with std::auto_ptr pointers""" 1013 1014 @staticmethod10441016 """returns True, if type represents instantiation of C{boost::shared_ptr}, False otherwise""" 1017 type = remove_alias( type ) 1018 type = remove_cv( type ) 1019 type = remove_declarated( type ) 1020 if not isinstance( type, ( class_declaration.class_declaration_t, class_declaration.class_t ) ): 1021 return False 1022 if not impl_details.is_defined_in_xxx( 'std', type ): 1023 return False 1024 return type.decl_string.startswith( '::std::auto_ptr<' )1025 1026 @staticmethod1028 """returns reference to boost::shared_ptr value type""" 1029 if not auto_ptr_traits.is_smart_pointer( type ): 1030 raise TypeError( 'Type "%s" is not instantiation of std::auto_ptr' % type.decl_string ) 1031 type = remove_alias( type ) 1032 cls = remove_cv( type ) 1033 cls = remove_declarated( type ) 1034 if isinstance( cls, class_declaration.class_t ): 1035 return remove_declarated( cls.typedef( "element_type", recursive=False ).type ) 1036 elif not isinstance( cls, ( class_declaration.class_declaration_t, class_declaration.class_t ) ): 1037 raise RuntimeError( "Unable to find out auto_ptr value type. auto_ptr class is: %s" % cls.decl_string ) 1038 else: 1039 value_type_str = templates.args( cls.name )[0] 1040 ref = impl_details.find_value_type( cls.top_parent, value_type_str ) 1041 if None is ref: 1042 raise RuntimeError( "Unable to find out auto_ptr value type. shared_ptr class is: %s" % cls.decl_string ) 1043 return ref1047 """returns True, if type represents C++ std::string, False otherwise""" 1048 decl_strings = [ 1049 '::std::basic_string<char,std::char_traits<char>,std::allocator<char> >' 1050 , '::std::basic_string<char, std::char_traits<char>, std::allocator<char> >' 1051 , '::std::string' ] 1052 if isinstance( type, types.StringTypes ): 1053 return type in decl_strings 1054 else: 1055 type = remove_alias( type ) 1056 return remove_cv( type ).decl_string in decl_strings10571059 """returns True, if type represents C++ std::wstring, False otherwise""" 1060 decl_strings = [ 1061 '::std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >' 1062 , '::std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >' 1063 , '::std::wstring' ] 1064 if isinstance( type, types.StringTypes ): 1065 return type in decl_strings 1066 else: 1067 type = remove_alias( type ) 1068 return remove_cv( type ).decl_string in decl_strings10691071 """returns True, if type represents C++ std::string, False otherwise""" 1072 decl_strings = [ 1073 '::std::basic_ostream<char, std::char_traits<char> >' 1074 , '::std::basic_ostream<char,std::char_traits<char> >' 1075 , '::std::ostream' ] 1076 if isinstance( type, types.StringTypes ): 1077 return type in decl_strings 1078 else: 1079 type = remove_alias( type ) 1080 return remove_cv( type ).decl_string in decl_strings10811084 """returns True, if type represents C++ std::string, False otherwise""" 1085 decl_strings = [ 1086 '::std::basic_ostream<wchar_t, std::char_traits<wchar_t> >' 1087 , '::std::basic_ostream<wchar_t,std::char_traits<wchar_t> >' 1088 , '::std::wostream' ] 1089 if isinstance( type, types.StringTypes ): 1090 return type in decl_strings 1091 else: 1092 type = remove_alias( type ) 1093 return remove_cv( type ).decl_string in decl_strings1094
Trees | Indices | Help |
|
---|
Generated by Epydoc 3.0.1 on Mon Oct 20 08:51:16 2008 | http://epydoc.sourceforge.net |