# Copyright 2014 Insight Software Consortium. # Copyright 2004-2008 Roman Yakovenko. # Distributed under the Boost Software License, Version 1.0. # See http://www.boost.org/LICENSE_1_0.txt from pygccxml.declarations import * from .. import utils class linker_t(decl_visitor_t, type_visitor_t, object): def __init__(self, decls, types, access, membership, files): decl_visitor_t.__init__(self) type_visitor_t.__init__(self) object.__init__(self) self.__decls = decls self.__types = types self.__access = access self.__membership = membership self.__files = files self.__inst = None self.__compiler = None if self.__decls: for d in self.__decls.values(): self.__compiler = d.compiler break @property def instance(self): return self.__inst @instance.setter def instance(self, inst): self.__inst = inst # use inst, to reduce attribute access time if isinstance(inst, declaration_t) and inst.location: inst.location.file_name = self.__files[inst.location.file_name] def __link_type(self, type_id): if type_id is None: # in some situations type_id is None, return_type of constructor or # destructor return None elif type_id in self.__types: return self.__types[type_id] elif type_id in self.__decls: base = declarated_t(declaration=self.__decls[type_id]) self.__types[type_id] = base return base elif '...' == type_id: return ellipsis_t() else: return unknown_t() def __link_compound_type(self): self.__inst.base = self.__link_type(self.__inst.base) def __link_members(self): if id(self.__inst) not in self.__membership: return for member in self.__membership[id(self.__inst)]: if member not in self.__access: continue access = self.__access[member] if member not in self.__decls: continue decl = self.__decls[member] if isinstance(self.__inst, class_t): self.__inst.adopt_declaration(decl, access) else: self.__inst.adopt_declaration(decl) def __link_calldef(self): self.__inst.return_type = self.__link_type(self.__inst.return_type) if isinstance(self.__inst, type_t): linked_args = [ self.__link_type(arg) for arg in self.__inst.arguments_types] self.__inst.arguments_types = linked_args else: for arg in self.__inst.arguments: arg.type = self.__link_type(arg.type) for index in range(len(self.__inst.exceptions)): try: self.__inst.exceptions[index] = self.__decls[ self.__inst.exceptions[index]] except KeyError: self.__inst.exceptions[index] = self.__link_type( self.__inst.exceptions[index]) def visit_member_function(self): self.__link_calldef() def visit_constructor(self): self.__link_calldef() def visit_destructor(self): self.__link_calldef() def visit_member_operator(self): self.__link_calldef() def visit_casting_operator(self): self.__link_calldef() # will be fixed by patcher. It is needed because of demangled name # taken into account # self.__inst._name = 'operator ' + self.__inst.return_type.decl_string def visit_free_function(self): self.__link_calldef() def visit_free_operator(self): self.__link_calldef() def visit_class_declaration(self): pass def visit_class(self): self.__link_members() # GCC-XML sometimes generates constructors with names that does not # match class name. I think this is because those constructors are # compiler generated. I need to find out more about this and to talk # with Brad new_name = self.__inst._name if templates.is_instantiation(new_name): new_name = templates.name(new_name) for decl in self.__inst.declarations: if not isinstance(decl, constructor_t): continue if '.' in decl._name or '$' in decl._name: decl._name = new_name bases = self.__inst.bases.split() self.__inst.bases = [] for base in bases: # it could be "_5" or "protected:_5" data = base.split(':') base_decl = self.__decls[data[-1]] access = ACCESS_TYPES.PUBLIC if 2 == len(data): access = data[0] self.__inst.bases.append(hierarchy_info_t(base_decl, access)) base_decl.derived.append(hierarchy_info_t(self.__inst, access)) def visit_enumeration(self): pass def visit_namespace(self): self.__link_members() def visit_typedef(self): self.__inst.type = self.__link_type(self.__inst.type) def visit_variable(self): self.__inst.type = self.__link_type(self.__inst.type) def visit_void(self): pass def visit_char(self): pass def visit_signed_char(self): pass def visit_unsigned_char(self): pass def visit_wchar(self): pass def visit_short_int(self): pass def visit_short_unsigned_int(self): pass def visit_bool(self): pass def visit_int(self): pass def visit_unsigned_int(self): pass def visit_long_int(self): pass def visit_long_unsigned_int(self): pass def visit_long_long_int(self): pass def visit_long_long_unsigned_int(self): pass def visit_int128(self): pass def visit_uint128(self): pass def visit_float(self): pass def visit_double(self): pass def visit_long_double(self): pass def visit_complex_long_double(self): pass def visit_complex_double(self): pass def visit_complex_float(self): pass def visit_jbyte(self): pass def visit_jshort(self): pass def visit_jint(self): pass def visit_jlong(self): pass def visit_jfloat(self): pass def visit_jdouble(self): pass def visit_jchar(self): pass def visit_jboolean(self): pass def visit_volatile(self): if isinstance(self.__inst.base, const_t): const_type_inst = self.__inst.base const_type_inst.base = self.__link_type(const_type_inst.base) else: self.__link_compound_type() def visit_const(self): self.__link_compound_type() def visit_pointer(self): if '0.9' in self.__compiler and \ isinstance(self.__inst.base, member_variable_type_t): original_inst = self.__inst self.__inst = self.__inst.base self.visit_member_variable_type() self.__inst = original_inst else: self.__link_compound_type() def visit_reference(self): self.__link_compound_type() def visit_array(self): self.__link_compound_type() def visit_free_function_type(self): self.__link_calldef() def visit_member_function_type(self): self.__link_calldef() if isinstance(self.__inst, type_t): self.__inst.class_inst = self.__link_type(self.__inst.class_inst) def visit_member_variable_type(self): self.__inst.variable_type = self.__link_type(self.__inst.variable_type) self.__link_compound_type() def visit_declarated(self): if utils.is_str(self.__inst.declaration): self.__inst.declaration = self.__decls[self.__inst.declaration] def visit_restrict(self): self.__link_compound_type()