| Home | 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
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Mon Oct 20 09:00:32 2008 | http://epydoc.sourceforge.net |