| 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_types 
  34      """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_ 
  43   
  45      """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_alias 
  60   
  62      """implementation details""" 
  63      return [ base 
  64               , cpptypes.const_t( base ) 
  65               , cpptypes.volatile_t( base ) 
  66               , cpptypes.volatile_t( cpptypes.const_t( base ) ) ] 
  67   
  69      """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] 
  79   
  81      """implementation details""" 
  82      types = decompose_type( type ) 
  83      return [ tp.__class__ for tp in types ] 
  84   
  86      """returns base type. 
  87   
  88      For C{const int} will return C{int} 
  89      """ 
  90      types = decompose_type( type ) 
  91      return types[-1] 
  92   
  94      """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 False 
 110   
 112      """returns True, if type represents C{bool}, False otherwise""" 
 113      return remove_alias( type_ ) in create_cv_types( cpptypes.bool_t() ) 
 114   
 116      """returns True, if type represents C{void}, False otherwise""" 
 117      return remove_alias( type ) in create_cv_types( cpptypes.void_t() ) 
 118   
 120      """returns True, if type represents C{void*}, False otherwise""" 
 121      return is_same( type, cpptypes.pointer_t( cpptypes.void_t() ) ) 
 122   
 124      """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_def 
 140   
 142      """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_def 
 148   
 150      """returns True, if type represents C++ integral or floating point type, False otherwise""" 
 151      return is_integral( type ) or is_floating_point( type ) 
 152   
 154      """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) ) 
 158   
 160      """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 ) 
 168   
 170      """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.base 
 185   
 187      """returns True, if type represents C++ reference type, False otherwise""" 
 188      nake_type = remove_alias( type ) 
 189      return isinstance( nake_type, cpptypes.reference_t ) 
 190   
 192      """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 ) 
 197   
 199      """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.size 
 205   
 207      """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 0 
 216   
 218      """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.base 
 227   
 229      """returns True, if type represents C++ const type, False otherwise""" 
 230      nake_type = remove_alias( type ) 
 231      return isinstance( nake_type, cpptypes.const_t ) 
 232   
 234      """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.base 
 244   
 246      """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 type 
 254   
 256      """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_type2 
 260   
 262      """returns True, if type represents C++ volatile type, False otherwise""" 
 263      nake_type = remove_alias( type ) 
 264      return isinstance( nake_type, cpptypes.volatile_t ) 
 265   
 267      """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.base 
 276   
 278      """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 result 
 289   
 291      """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) ) 
 295   
 297      """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   
 312   
 314          """returns True, if type represents the desired declaration, False otherwise""" 
 315          return isinstance( self.__apply_sequence( type ), self.declaration_class ) 
 316   
 318          """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 ) 
 324   
 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""" 
 347      """returns reference to trivial constructor or None""" 
 348      assert isinstance( type, class_declaration.class_t ) 
 349      return type.find_trivial_constructor() 
 350   
 352      """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 trivial 
 357   
 359      """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_constructor 
 364   
 366      """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] 
 371   
 373      """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 decls 
 379   
 381      """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 ) 
 386   
 388      """returns True, if class has public destructor, False otherwise""" 
 389      d = has_destructor( type ) 
 390      return d and d.access_type == 'public' 
 391   
 393      """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 False 
 408   
 410      """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 decls 
 416   
 418      """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 False 
 459   
 461      """returns True, if class has public operator==, otherwise False""" 
 462      return has_public_binary_operator( type, '==' ) 
 463   
 465      """returns True, if class has public operator<, otherwise False""" 
 466      return has_public_binary_operator( type, '<' ) 
 467   
 469      """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 False 
 499   
 501      """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 False 
 525   
 527      """implementation details""" 
 531   
 533          found = algorithm.find_declaration( class_decl.parent.declarations 
 534                                              , name=class_decl.name 
 535                                              , type=class_declaration.class_t ) 
 536          return found 
 537   
 539          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_ 
 547   
 549          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 True 
 576   
 578          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 True 
 611   
 612   
 614          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 False 
 627   
 629          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 False 
 640   
 642          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 False 
 653   
 655          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 False 
 666   
 668          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 False 
 684   
 686          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 False 
 741   
 743          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 False 
 798   
 800      """returns True, if source could be converted to target, otherwise False""" 
 801      return __is_convertible_t( source, target ).is_convertible() 
 802   
 804      """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 False 
 828   
 830      """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_ ) 
 880   
 882      """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.parent 
 905   
 907      """implementation details""" 
 908      @staticmethod 
 910          """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.parent 
 932   
 933      @staticmethod 
 935          """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 None 
 976   
 978      """implements functionality, needed for convinient work with smart pointers""" 
 979   
 980      @staticmethod 
 982          """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      @staticmethod 
 994          """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 ref 
1010   
1012      """implements functionality, needed for convinient work with std::auto_ptr pointers""" 
1013   
1014      @staticmethod 
1016          """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      @staticmethod 
1028          """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 ref 
1044   
1047      """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_strings 
1057   
1059      """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_strings 
1069   
1071      """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_strings 
1081   
1084      """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_strings 
1094   
| Trees | Indices | Help | 
 | 
|---|
| Generated by Epydoc 3.0.1 on Mon Oct 20 08:51:16 2008 | http://epydoc.sourceforge.net |