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