Skip to content

Commit 97f6fa2

Browse files
author
roman_yakovenko
committed
changing some of type_traits functions - adding support for artificial declarations
1 parent b74df45 commit 97f6fa2

File tree

1 file changed

+53
-122
lines changed

1 file changed

+53
-122
lines changed

pygccxml/declarations/type_traits.py

Lines changed: 53 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ def does_match_definition(given, main, secondary ):
111111
def is_bool( type_ ):
112112
"""returns True, if type represents C{bool}, False otherwise"""
113113
return remove_alias( type_ ) in create_cv_types( cpptypes.bool_t() )
114-
114+
115115
def is_void( type ):
116116
"""returns True, if type represents C{void}, False otherwise"""
117117
return remove_alias( type ) in create_cv_types( cpptypes.void_t() )
@@ -213,7 +213,7 @@ def array_item_type(type_):
213213
return remove_pointer( type_ )
214214
else:
215215
assert 0
216-
216+
217217
def remove_reference(type):
218218
"""removes reference from the type definition
219219
@@ -348,115 +348,46 @@ def find_trivial_constructor( type ):
348348
assert isinstance( type, class_declaration.class_t )
349349
return type.find_trivial_constructor()
350350

351-
def has_trivial_constructor( type ):
352-
"""returns True, if class has public trivial constructor, False otherwise"""
353-
logger = utils.loggers.cxx_parser
354-
true_header = "has_trivial_constructor(TRUE)- %s - " % type.decl_string
355-
false_header = "has_trivial_constructor(false)- %s - " % type.decl_string
356-
357-
if '0.9' in type.compiler:
358-
trivial = type.constructors( lambda x: x.is_trivial_constructor
359-
, recursive=False
360-
, allow_empty=True )
361-
if trivial:
362-
if trivial[0].access_type == 'public':
363-
logger.debug( true_header + "there is user defined public trivial constructor" )
364-
return True
365-
else:
366-
logger.debug( false_header + "there is user defined non-public trivial constructor" )
367-
return False
368-
else:
369-
#there is no trivial constructor, so I should find out whether other constructors exist
370-
if type.constructors( recursive=False, allow_empty=True ):
371-
logger.debug( false_header + "there are other user defined constructors" )
372-
return False
373-
else:
374-
if __contains_noncopyable_mem_var( type ):
375-
logger.debug( false_header + "class doesn't have any user defined constructor and BUT it is NOT copyable" )
376-
return False
377-
else:
378-
logger.debug( true_header + "class doesn't have any user defined constructor and it is copyable" )
379-
return True
380-
else:
381-
cons = find_trivial_constructor( type )
382-
return cons and cons.access_type == 'public'
383-
384-
"""
385-
Question: Do I have to define a copy constructor and assignment operator?
386-
387-
Answer:
388-
C++ implicitly declares a copy constructor and an assignment operator
389-
for every class, struct and union unless the user declared them explicitly.
390-
A copy constructor isnot implicitly declared if the class has any user-declared
391-
constructor(s). Implicitly defined copy constructor and assignment operator
392-
are said to be trivial if:
393-
394-
* their class has no virtual functions and no virtual base class(es)
395-
* all direct base classes and nonstatic data members of their class have trivial constructors
396-
397-
Otherwise, the copy constructor and the assignment operator are non-trivial.
398-
Implicitly-declared non-trivial copy constructor and assignment operator are
399-
implicitly-defined.
400-
401-
The assignment operator is called "copy assignment operator" in the standard.
402-
This verbosity doesnot convey any new or hidden meanings. Perhaps it's meant to
403-
differentiate between the assignment operator of fundamental types and the
404-
assignment operator member function of class types. In this series I will stick
405-
to the term assignment operator.
406-
"""
351+
def has_trivial_constructor( class_ ):
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
407357

408358
def has_copy_constructor( class_ ):
409-
"""returns True, if class has public copy constructor, False otherwise"""
359+
"""if class has public copy constructor, this function will return reference to it, None otherwise"""
410360
class_ = class_traits.get_declaration( class_ )
411-
if '0.9' in class_.compiler:
412-
copy_ = class_.find_copy_constructor()
413-
if copy_:
414-
if copy_.access_type == 'public':
415-
return True
416-
else:
417-
return False
418-
else:
419-
if __contains_noncopyable_mem_var( class_ ):
420-
return False
421-
else:
422-
return True
423-
else:
424-
constructors = filter( lambda x: isinstance( x, calldef.constructor_t ) \
425-
and x.is_copy_constructor
426-
, class_.public_members )
427-
return bool( constructors )
428-
429-
def has_destructor(type):
430-
"""returns True, if class has destructor, False otherwise"""
431-
assert isinstance( type, class_declaration.class_t )
432-
return bool( algorithm.find_declaration( type.get_members()
433-
, type=calldef.destructor_t
434-
, recursive=False ) )
435-
436-
def has_public_constructor(type):
437-
"""returns True, if class has public constructor, False otherwise"""
438-
assert isinstance( type, class_declaration.class_t )
439-
decls = algorithm.find_all_declarations( type.public_members
440-
, type=calldef.constructor_t
441-
, recursive=False )
442-
constructors = filter( lambda decl: not decl.is_copy_constructor, decls )
443-
return bool( constructors ) or has_trivial_constructor( type )
361+
copy_constructor = class_.find_copy_constructor()
362+
if copy_constructor and copy_constructor.access_type == 'public':
363+
return copy_constructor
444364

445-
def has_public_assign(type):
365+
def has_destructor(class_):
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+
372+
def has_public_constructor(class_):
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+
380+
def has_public_assign(class_):
446381
"""returns True, if class has public assign operator, False otherwise"""
447-
assert isinstance( type, class_declaration.class_t )
448-
decls = algorithm.find_all_declarations( type.public_members
449-
, type=calldef.member_operator_t
450-
, recursive=False )
451-
decls = filter( lambda decl: decl.symbol == '=', decls )
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 )
452385
return bool( decls )
453386

454387
def has_public_destructor(type):
455388
"""returns True, if class has public destructor, False otherwise"""
456-
assert isinstance( type, class_declaration.class_t )
457-
return bool( algorithm.find_declaration( type.public_members
458-
, type=calldef.destructor_t
459-
, recursive=False ) )
389+
d = has_destructor( type )
390+
return d and d.access_type == 'public'
460391

461392
def is_base_and_derived( based, derived ):
462393
"""returns True, if there is "base and derived" relationship between classes, False otherwise"""
@@ -468,20 +399,20 @@ def is_base_and_derived( based, derived ):
468399
all_derived = ( [derived] )
469400
else: #tuple
470401
all_derived = derived
471-
402+
472403
for derived_cls in all_derived:
473404
for base_desc in derived_cls.recursive_bases:
474405
if base_desc.related_class == based:
475406
return True
476407
return False
477-
408+
478409
def has_any_non_copyconstructor( type):
479-
"""returns True, if class has any non "copy constructor", otherwise False"""
480-
assert isinstance( type, class_declaration.class_t )
481-
constructors = filter( lambda x: isinstance( x, calldef.constructor_t ) \
482-
and not x.is_copy_constructor
483-
, type.public_members )
484-
return bool( constructors ) or has_trivial_constructor( type )
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
485416

486417
def has_public_binary_operator( type, operator_symbol ):
487418
"""returns True, if type has public binary operator, otherwise False"""
@@ -916,36 +847,36 @@ def __is_noncopyable_single( class_):
916847
if __contains_noncopyable_mem_var( class_ ):
917848
logger.debug( "__is_noncopyable_single(TRUE) - %s - contains noncopyable members" % class_.decl_string )
918849
return True
919-
else:
850+
else:
920851
logger.debug( "__is_noncopyable_single(FALSE) - %s - COPYABLE, because is doesn't contains noncopyable members" % class_.decl_string )
921852
return False
922853

923854
def is_noncopyable( class_ ):
924855
"""returns True, if class is noncopyable, False otherwise"""
925-
logger = utils.loggers.cxx_parser
856+
logger = utils.loggers.cxx_parser
926857
class_ = class_traits.get_declaration( class_ )
927-
858+
928859
true_header = "is_noncopyable(TRUE) - %s - " % class_.decl_string
929860
false_header = "is_noncopyable(false) - %s - " % class_.decl_string
930-
861+
931862
if class_.class_type == class_declaration.CLASS_TYPES.UNION:
932863
return False
933864

934865
if class_.is_abstract:
935866
logger.debug( true_header + "abstract client" )
936867
return True
937868

938-
#if class has public, user defined copy constructor, than this class is
869+
#if class has public, user defined copy constructor, than this class is
939870
#copyable
940871
copy_ = class_.find_copy_constructor()
941872
if copy_ and copy_.access_type == 'public' and not copy_.is_artificial:
942873
return False
943-
874+
944875
for base_desc in class_.recursive_bases:
945-
assert isinstance( base_desc, class_declaration.hierarchy_info_t )
876+
assert isinstance( base_desc, class_declaration.hierarchy_info_t )
946877
if base_desc.related_class.decl_string in ('::boost::noncopyable', '::boost::noncopyable_::noncopyable' ):
947878
logger.debug( true_header + "derives from boost::noncopyable" )
948-
return True
879+
return True
949880
if not has_copy_constructor( base_desc.related_class ):
950881
base_copy_ = base_desc.related_class.find_copy_constructor()
951882
if base_copy_:
@@ -959,7 +890,7 @@ def is_noncopyable( class_ ):
959890
if __is_noncopyable_single( base_desc.related_class ):
960891
logger.debug( true_header + "__is_noncopyable_single returned True" )
961892
return True
962-
893+
963894
if not has_copy_constructor( class_ ):
964895
logger.debug( true_header + "does not have trival copy constructor" )
965896
return True
@@ -1032,9 +963,9 @@ def find_value_type( global_ns, value_type_str ):
1032963
found = global_ns.decls( name=value_type_str
1033964
, function=lambda decl: not isinstance( decl, calldef.calldef_t )
1034965
, allow_empty=True )
1035-
if not found:
966+
if not found:
1036967
no_global_ns_value_type_str = value_type_str[2:]
1037-
if cpptypes.FUNDAMENTAL_TYPES.has_key( no_global_ns_value_type_str ):
968+
if cpptypes.FUNDAMENTAL_TYPES.has_key( no_global_ns_value_type_str ):
1038969
return cpptypes.FUNDAMENTAL_TYPES[ no_global_ns_value_type_str ]
1039970
elif is_std_string( value_type_str ):
1040971
string_ = global_ns.typedef( '::std::string' )
@@ -1137,7 +1068,7 @@ def is_std_ostream( type ):
11371068
else:
11381069
type = remove_alias( type )
11391070
return remove_cv( type ).decl_string in decl_strings
1140-
1071+
11411072

11421073
def is_std_wostream( type ):
11431074
"""returns True, if type represents C++ std::string, False otherwise"""

0 commit comments

Comments
 (0)