1   
  2   
  3   
  4   
  5   
  6  """ 
  7  defines classes, that describes C++ classes 
  8   
  9  This modules contains definition for next C++ declarations: 
 10      - class definition 
 11      - class declaration 
 12      - small helper class for describing C++ class hierarchy 
 13  """ 
 14   
 15  import scopedef 
 16  import itertools 
 17  import compilers 
 18  import algorithm 
 19  import declaration 
 20  import dependencies 
 21  from pygccxml import utils 
 29   
 36   
 50   
 53      """describes class relationship""" 
 54 -    def __init__(self, related_class=None, access=None, is_virtual=False ): 
  63   
 70   
 72          return not self.__eq__( other ) 
  73   
 79   
 86      related_class = property( _get_related_class, _set_related_class 
 87                                , doc="reference to base or derived L{class<class_t>}") 
 88   
 94      access = property( _get_access, _set_access ) 
 95      access_type = property( _get_access, _set_access 
 96                              , doc="describes L{hierarchy type<ACCESS_TYPES>}") 
 97   
 98       
100          return self._is_virtual 
 102          self._is_virtual = new_is_virtual 
 103      is_virtual = property( _get_is_virtual, _set_is_virtual 
104                             , doc="indicates whether the inheritance is virtual or not") 
 105   
108      """describes class declaration""" 
110          """creates class that describes C++ class declaration( and not definition )""" 
111          declaration.declaration_t.__init__( self, name ) 
112          self._aliases = [] 
113          self._container_traits = None 
114          self._container_traits_set = False 
 115   
117          """implementation details""" 
118          return [] 
 119   
122   
126          self._aliases = new_aliases 
 127      aliases = property( _get_aliases, _set_aliases 
128                           , doc="List of L{aliases<typedef_t>} to this instance") 
129   
130      @property 
132          """reference to L{container traits<container_traits.py>} or None""" 
133          if self._container_traits_set == False: 
134              import container_traits  
135              self._container_traits_set = True 
136              self._container_traits = container_traits.find_container_traits( self ) 
137          return self._container_traits 
 138   
 141   
142 -class class_t( scopedef.scopedef_t ): 
 143      """describes class definition""" 
144   
145      USE_DEMANGLED_AS_NAME = True 
147          """creates class that describes C++ class definition""" 
148          scopedef.scopedef_t.__init__( self, name ) 
149          if class_type: 
150              assert( class_type in CLASS_TYPES.ALL ) 
151          self._class_type = class_type 
152          self._bases = [] 
153          self._derived = [] 
154          self._is_abstract = is_abstract 
155          self._public_members = [] 
156          self._private_members = [] 
157          self._protected_members = [] 
158          self._aliases = [] 
159          self._byte_size = 0 
160          self._byte_align = 0 
161          self._container_traits = None 
162          self._container_traits_set = False 
163          self._recursive_bases = None 
164          self._recursive_derived = None 
 165   
195   
201   
211   
227   
229          return self._class_type 
 231          if new_class_type: 
232              assert( new_class_type in CLASS_TYPES.ALL ) 
233          self._class_type = new_class_type 
 234      class_type = property( _get_class_type, _set_class_type 
235                             , doc="describes class L{type<CLASS_TYPES>}") 
236   
240          self._bases = new_bases 
 241      bases = property( _get_bases, _set_bases 
242                        , doc="list of L{base classes<hierarchy_info_t>}") 
243   
244      @property 
246          """list of all L{base classes<hierarchy_info_t>}""" 
247          if self._recursive_bases is None: 
248              to_go = self.bases[:] 
249              all_bases = [] 
250              while to_go: 
251                  base = to_go.pop() 
252                  if base not in all_bases: 
253                      all_bases.append( base ) 
254                      to_go.extend( base.related_class.bases ) 
255              self._recursive_bases = all_bases 
256          return self._recursive_bases 
 257   
261          self._derived = new_derived 
 262      derived = property( _get_derived, _set_derived 
263                          , doc="list of L{derived classes<hierarchy_info_t>}") 
264   
265      @property 
267          """list of all L{derive classes<hierarchy_info_t>}""" 
268          if self._recursive_derived is None: 
269              to_go = self.derived[:] 
270              all_derived = [] 
271              while to_go: 
272                  derive = to_go.pop() 
273                  if derive not in all_derived: 
274                      all_derived.append( derive ) 
275                      to_go.extend( derive.related_class.derived ) 
276              self._recursive_derived = all_derived 
277          return self._recursive_derived 
 278   
280          if self.compiler == compilers.MSVC_PDB_9: 
281               
282              import calldef 
283              import function_traits 
284              from matchers import virtuality_type_matcher_t as vtmatcher_t 
285              filter_pv = vtmatcher_t( calldef.VIRTUALITY_TYPES.PURE_VIRTUAL ) 
286              if self.calldefs( filter_pv, recursive=False, allow_empty=True ): 
287                  return True 
288              filter_npv = vtmatcher_t( calldef.VIRTUALITY_TYPES.VIRTUAL ) \ 
289                           | vtmatcher_t( calldef.VIRTUALITY_TYPES.NOT_VIRTUAL ) 
290              pv_calldefs = [] 
291              npv_calldefs = [] 
292   
293              npv_calldefs.extend( self.calldefs( filter_npv, recursive=False, allow_empty=True ) ) 
294              for base in self.recursive_bases: 
295                  cls = base.related_class 
296                  pv_calldefs.extend( cls.calldefs( filter_pv, recursive=False, allow_empty=True ) ) 
297                  npv_calldefs.extend( cls.calldefs( filter_npv, recursive=False, allow_empty=True ) ) 
298   
299              for pure_virtual in pv_calldefs: 
300                  impl_found = filter( lambda f: function_traits.is_same_function( pure_virtual, f ) 
301                                       , npv_calldefs ) 
302                  if not impl_found: 
303                      return True 
304              return False 
305          else: 
306              return self._is_abstract 
 309      is_abstract = property( _get_is_abstract, _set_is_abstract 
310                              ,doc="describes whether class abstract or not" ) 
311   
313          return self._public_members 
 315          self._public_members = new_public_members 
 316      public_members = property( _get_public_members, _set_public_members 
317                                 , doc="list of all public L{members<declaration_t>}") 
318   
320          return self._private_members 
 322          self._private_members = new_private_members 
 323      private_members = property( _get_private_members, _set_private_members 
324                                  , doc="list of all private L{members<declaration_t>}") 
325   
327          return self._protected_members 
 329          self._protected_members = new_protected_members 
 330      protected_members = property( _get_protected_members, _set_protected_members 
331                                    , doc="list of all protected L{members<declaration_t>}" ) 
332   
336          self._aliases = new_aliases 
 337      aliases = property( _get_aliases, _set_aliases 
338                           , doc="List of L{aliases<typedef_t>} to this instance") 
339   
341          return self._byte_size 
 343          self._byte_size = new_byte_size 
 344      byte_size = property( _get_byte_size, _set_byte_size 
345                            , doc="Size of this class in bytes @type: int") 
346   
352          self._byte_align = new_byte_align 
 353      byte_align = property( _get_byte_align, _set_byte_align 
354                            , doc="Alignment of this class in bytes @type: int") 
355   
358   
384   
404   
422   
447   
457   
471   
472      @property 
474          """reference to L{container traits<container_traits.py>} or None""" 
475          if self._container_traits_set == False: 
476              import container_traits  
477              self._container_traits_set = True 
478              self._container_traits = container_traits.find_container_traits( self ) 
479          return self._container_traits 
 480   
487   
494   
503       
505          """returns list of all noncopyable variables""" 
506          import type_traits as tt 
507          logger = utils.loggers.cxx_parser 
508          mvars = self.vars( lambda v: not v.type_qualifiers.has_static, recursive=False, allow_empty=True ) 
509          noncopyable_vars = [] 
510          for mvar in mvars: 
511              type_ = tt.remove_reference( mvar.type ) 
512              if tt.is_const( type_ ): 
513                  no_const = tt.remove_const( type_ ) 
514                  if tt.is_fundamental( no_const ) or tt.is_enum( no_const): 
515                      logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - fundamental or enum" % self.decl_string ) 
516                      noncopyable_vars.append( mvar ) 
517                  if tt.is_class( no_const ): 
518                      logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - class" % self.decl_string ) 
519                      noncopyable_vars.append( mvar ) 
520                  if tt.is_array( no_const ): 
521                      logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes const member variable - array" % self.decl_string ) 
522                      noncopyable_vars.append( mvar ) 
523              if tt.class_traits.is_my_case( type_ ): 
524                  cls = tt.class_traits.get_declaration( type_ ) 
525                  if tt.is_noncopyable( cls ): 
526                      logger.debug( "__contains_noncopyable_mem_var - %s - TRUE - containes member variable - class that is not copyable" % self.decl_string ) 
527                      noncopyable_vars.append( mvar )                 
528          logger.debug( "__contains_noncopyable_mem_var - %s - false - doesn't contains noncopyable members" % self.decl_string ) 
529          return noncopyable_vars 
 530   
531   
532  class_types = ( class_t, class_declaration_t ) 
533