// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // -*- Mode: C++ -*- // // Copyright (C) 2013-2020 Red Hat, Inc. // // Author: Dodji Seketeli /// @file /// /// Types of the main internal representation of libabigail. /// /// This internal representation abstracts the artifacts that make up /// an application binary interface. #ifndef __ABG_IR_H__ #define __ABG_IR_H__ #include #include #include #include #include #include #include "abg-cxx-compat.h" #include "abg-fwd.h" #include "abg-hash.h" #include "abg-traverse.h" #include "abg-config.h" /// @file /// /// This file contains the declarations of the Internal Representation /// of libabigail. /// @defgroup Memory Memory management /// @{ /// /// How objects' lifetime is handled in libabigail. /// /// For memory management and garbage collection of libabigail's IR /// artifacts, we use std::shared_ptr and std::weak_ptr. /// /// When manipulating these IR artifacts, there are a few rules to keep in /// mind. /// /// The declaration for a type is owned by only one scope /// /// This means that for each instance of abigail::type_base (a type) there /// is an instance of abigail::scope_decl that owns a @ref /// abigail::decl_base_sptr (a shared pointer to an abigail::decl_base) /// that points to the declaration of that type. The /// abigail::type_base_sptr is added to the scope using the function /// abigail::add_decl_to_scope(). /// /// There is a kind of type that is usually not syntactically owned by /// a scope: it's function type. In libabigail, function types are /// represented by abigail::function_type and abigail::method_type. /// These types must be owned by the translation unit they originate /// from. Adding them to the translation unit must be done by a call /// to the method function /// abigail::translation::bind_function_type_life_time(). /// /// A declaration that has a type does NOT own the type /// /// This means that, for instance, in an abigail::var_decl (a variable /// declaration), the type of the declaration is not owned by the /// declaration. In other (concrete) words, the variable declaration /// doesn't have a shared pointer to the type. Rather, it has a *weak* /// pointer to its type. That means that it has a data member of type /// abigail::type_base_wptr that contains the type of the declaration. /// /// But then abigail::var_decl::get_type() returns a shared pointer that /// is constructed from the internal weak pointer to the type. That way, /// users of the type of the var can own a temporary reference on it and /// be assured that the type's life time is long enough for their need. /// /// Likewise, data members, function and template parameters similarly /// have weak pointers on their type. /// /// If, for a reason, you really need to keep a type alive for the /// entire lifetime of the type system, then you can bind the life /// time of that type to the life time of the @ref environment that is /// supposed to outlive the type system. You do that by passing the /// type to the function environment::keep_type_alive(). /// /// @} namespace abigail { /// The namespace of the internal representation of ABI artifacts like /// types and decls. namespace ir { // Inject some std types in here. using std::unordered_map; /// A convenience typedef for an unordered set of pointer values typedef unordered_set pointer_set; /// Functor to hash a canonical type by using its pointer value. struct canonical_type_hash { size_t operator()(const type_base_sptr& l) const; size_t operator()(const type_base *l) const; }; //end struct canonical_type_hash /// Helper typedef for an unordered set of type_base_sptr which uses /// pointer value to tell its members appart, because the members are /// canonical types. typedef unordered_set canonical_type_sptr_set_type; /// Helper typedef for a vector of pointer to type_base. typedef vector type_base_ptrs_type; /// Helper typedef for a vector of shared pointer to a type_base. typedef vector type_base_sptrs_type; /// This is an abstraction of the set of resources necessary to manage /// several aspects of the internal representations of the Abigail /// library. /// /// An environment can be seen as the boundaries in which all related /// Abigail artifacts live. So before doing anything using this /// library, the first thing to create is, well, you know it now, an /// environment. /// /// Note that the lifetime of environment objects must be longer than /// the lifetime of any other type in the Abigail system. So a given /// instance of @ref environment must stay around as long as you are /// using libabigail. It's only when you are done using the library /// that you can de-allocate the environment instance. class environment { public: struct priv; std::unique_ptr priv_; /// A convenience typedef for a map of canonical types. The key is /// the pretty representation string of a particular type and the /// value is the vector of canonical types that have the same pretty /// representation string. typedef std::unordered_map > canonical_types_map_type; environment(); virtual ~environment(); canonical_types_map_type& get_canonical_types_map(); const canonical_types_map_type& get_canonical_types_map() const; const type_base_sptr& get_void_type() const; const type_base_sptr& get_variadic_parameter_type() const; bool canonicalization_is_done() const; void canonicalization_is_done(bool); bool do_on_the_fly_canonicalization() const; void do_on_the_fly_canonicalization(bool f); bool decl_only_class_equals_definition() const; void decl_only_class_equals_definition(bool f) const; bool is_void_type(const type_base_sptr&) const; bool is_void_type(const type_base*) const; bool is_variadic_parameter_type(const type_base*) const; bool is_variadic_parameter_type(const type_base_sptr&) const; interned_string intern(const string&) const; const config& get_config() const; #ifdef WITH_DEBUG_SELF_COMPARISON void set_self_comparison_debug_input(const corpus_sptr& corpus); void get_self_comparison_debug_inputs(corpus_sptr& first_corpus, corpus_sptr& second_corpus); void self_comparison_debug_is_on(bool); bool self_comparison_debug_is_on() const; #endif #ifdef WITH_DEBUG_TYPE_CANONICALIZATION void debug_type_canonicalization_is_on(bool flag); bool debug_type_canonicalization_is_on() const; #endif vector* get_canonical_types(const char* name); type_base* get_canonical_type(const char* name, unsigned index); #ifdef WITH_DEBUG_SELF_COMPARISON unordered_map& get_type_id_canonical_type_map() const; unordered_map& get_pointer_type_id_map(); string get_type_id_from_pointer(uintptr_t ptr); uintptr_t get_canonical_type_from_type_id(const char*); #endif friend class class_or_union; friend class class_decl; friend class function_type; friend void keep_type_alive(type_base_sptr); }; // end class environment class location_manager; /// @brief The source location of a token. /// /// This represents the location of a token coming from a given /// translation unit. This location is actually an abstraction of /// cursor in the table of all the locations of all the tokens of the /// translation unit. That table is managed by the @ref location_manager /// type. To get the file path, line and column numbers associated to /// a given instance of @ref location, you need to use the /// location_manager::expand_location method. class location { unsigned value_; // The location manager to use to decode the value above. There is // one location manager per translation unit, and the location // manager's life time is managed by its translation unit. location_manager* loc_manager_; // Whether the location is artificial. Being artificial means that // the location wasn't generated by the original emitter of the // metadata (i.e, the compiler if the metadata is debug info). For // instance, implicit location derived from the position of XML // elements in the abixml file is represented as artificial // locations. bool is_artificial_; location(unsigned v, location_manager* m) : value_(v), loc_manager_(m), is_artificial_(false) {} /// Get the location manager to use to decode the value of this /// location. /// /// @return the location manager for the current location value. location_manager* get_location_manager() const {return loc_manager_;} public: /// Test if the location is artificial. /// /// Being artificial means that the location wasn't generated by the /// original emitter of the metadata (i.e, the compiler if the /// metadata is debug info). For instance, the implicit location /// derived from the position of a given XML element in the abixml /// file is represented as artificial locations. The same XML /// element might carry a non-artificial (natural?) location that was /// originally emitted by the compiler that generated the original /// debug info the abixml file is derived from. /// /// @return true iff the location is artificial. bool get_is_artificial() const {return is_artificial_;} /// Set the artificial-ness of the location. /// /// Being artificial means that the location wasn't generated by the /// original emitter of the metadata (i.e, the compiler if the /// metadata is debug info). For instance, the implicit location /// derived from the position of a given XML element in the abixml /// file is represented as artificial locations. The same XML /// element might carry a non-artificial (natural?) location that /// was originally emitted by the compiler that generated the /// original debug info the abixml file is derived from. /// /// @param f the new artificial-ness state. void set_is_artificial(bool f) {is_artificial_ = f;} /// Copy constructor of the location. /// /// @param l the location to copy from. location(const location& l) : value_(l.value_), loc_manager_(l.loc_manager_), is_artificial_(l.is_artificial_) {} /// Assignment operator of the location. /// /// @param l the location to assign to the current one. location& operator=(const location& l) { value_ = l.value_; loc_manager_ = l.loc_manager_; is_artificial_ = l.is_artificial_; return *this; } /// Default constructor for the @ref location type. location() : value_(), loc_manager_(), is_artificial_() {} /// Get the value of the location. unsigned get_value() const {return value_;} /// Convert the location into a boolean. /// /// @return true iff the value of the location is different from /// zero. operator bool() const {return !!value_;} /// Equality operator of the @ref location type. /// /// @param other the other location to compare against. /// /// @return true iff both locations are equal. bool operator==(const location &other) const {return value_ == other.value_;} /// "Less than" operator of the @ref location type. /// /// @parm other the other location type to compare against. /// /// @return true iff the current instance is less than the @p other /// one. bool operator<(const location &other) const {return value_ < other.value_;} /// Expand the current location into a tripplet file path, line and /// column number. /// /// @param path the output parameter this function sets the expanded /// path to. /// /// @param line the output parameter this function sets the expanded /// line number to. /// /// @param column the output parameter this function sets the /// expanded column number to. void expand(std::string& path, unsigned& line, unsigned& column) const; string expand(void) const; friend class location_manager; }; // end class location /// @brief The entry point to manage locations. /// /// This type keeps a table of all the locations for tokens of a /// given translation unit. class location_manager { struct priv; std::unique_ptr priv_; public: location_manager(); ~location_manager(); location create_new_location(const std::string& fle, size_t lne, size_t col); void expand_location(const location& location, std::string& path, unsigned& line, unsigned& column) const; }; /// The base of an entity of the intermediate representation that is /// to be traversed. struct ir_traversable_base : public traversable_base { /// Traverse a given IR node and its children, calling an visitor on /// each node. /// /// @param v the visitor to call on each traversed node. /// /// @return true if the all the IR node tree was traversed. virtual bool traverse(ir_node_visitor& v); }; // end class ir_traversable_base /// The hashing functor for using instances of @ref type_or_decl_base /// as values in a hash map or set. struct type_or_decl_hash { /// Function-call Operator to hash the string representation of an /// ABI artifact. /// /// @param artifact the ABI artifact to hash. /// /// @return the hash value of the string representation of @p /// artifact. size_t operator()(const type_or_decl_base *artifact) const { string repr = get_pretty_representation(artifact); std::hash do_hash; return do_hash(repr); } /// Function-call Operator to hash the string representation of an /// ABI artifact. /// /// @param artifact the ABI artifact to hash. /// /// @return the hash value of the string representation of @p /// artifact. size_t operator()(const type_or_decl_base_sptr& artifact) const {return operator()(artifact.get());} }; // end struct type_or_decl_hash /// The comparison functor for using instances of @ref /// type_or_decl_base as values in a hash map or set. struct type_or_decl_equal { /// The function-call operator to compare the string representations /// of two ABI artifacts. /// /// @param l the left hand side ABI artifact operand of the /// comparison. /// /// @param r the right hand side ABI artifact operand of the /// comparison. /// /// @return true iff the string representation of @p l equals the one /// of @p r. bool operator()(const type_or_decl_base *l, const type_or_decl_base *r) const { string repr1 = get_pretty_representation(l); string repr2 = get_pretty_representation(r); return repr1 == repr2; } /// The function-call operator to compare the string representations /// of two ABI artifacts. /// /// @param l the left hand side ABI artifact operand of the /// comparison. /// /// @param r the right hand side ABI artifact operand of the /// comparison. /// /// @return true iff the string representation of @p l equals the one /// of @p r. bool operator()(const type_or_decl_base_sptr &l, const type_or_decl_base_sptr &r) const {return operator()(l.get(), r.get());} }; // end type_or_decl_equal /// A convenience typedef for a hash set of type_or_decl_base_sptr typedef unordered_set artifact_sptr_set_type; /// A convenience typedef for a hash set of const type_or_decl_base* typedef unordered_set artifact_ptr_set_type; /// A convenience typedef for a map which key is a string and which /// value is a @ref type_base_wptr. typedef unordered_map string_type_base_wptr_map_type; /// A convenience typedef for a map which key is an @ref /// interned_string and which value is a @ref type_base_wptr. typedef unordered_map istring_type_base_wptr_map_type; /// A convenience typedef for a map which key is an @ref /// interned_string and which value is a @ref type_base_wptr. typedef unordered_map istring_type_or_decl_base_sptr_map_type; /// This is a type that aggregates maps of all the kinds of types that /// are supported by libabigail. /// /// For instance, the type_maps contains a map of string to basic /// type, a map of string to class type, a map of string to union /// types, etc. The key of a map entry is the pretty representation /// of the type, and the value of the map entry is the type. class type_maps { struct priv; std::unique_ptr priv_; public: type_maps(); ~type_maps(); bool empty() const; const istring_type_base_wptrs_map_type& basic_types() const; istring_type_base_wptrs_map_type& basic_types(); const istring_type_base_wptrs_map_type& class_types() const; istring_type_base_wptrs_map_type& class_types(); istring_type_base_wptrs_map_type& union_types(); const istring_type_base_wptrs_map_type& union_types() const; istring_type_base_wptrs_map_type& enum_types(); const istring_type_base_wptrs_map_type& enum_types() const; istring_type_base_wptrs_map_type& typedef_types(); const istring_type_base_wptrs_map_type& typedef_types() const; istring_type_base_wptrs_map_type& qualified_types(); const istring_type_base_wptrs_map_type& qualified_types() const; istring_type_base_wptrs_map_type& pointer_types(); const istring_type_base_wptrs_map_type& pointer_types() const; istring_type_base_wptrs_map_type& reference_types(); const istring_type_base_wptrs_map_type& reference_types() const; istring_type_base_wptrs_map_type& array_types(); const istring_type_base_wptrs_map_type& array_types() const; const istring_type_base_wptrs_map_type& subrange_types() const; istring_type_base_wptrs_map_type& subrange_types(); istring_type_base_wptrs_map_type& function_types(); const istring_type_base_wptrs_map_type& function_types() const; const vector& get_types_sorted_by_name() const; }; // end class type_maps; /// This is the abstraction of the set of relevant artefacts (types, /// variable declarations, functions, templates, etc) bundled together /// into a translation unit. class translation_unit : public traversable_base { struct priv; std::unique_ptr priv_; // Forbidden translation_unit() = delete; public: /// Convenience typedef for a shared pointer on a @ref global_scope. typedef shared_ptr global_scope_sptr; /// The language of the translation unit. enum language { LANG_UNKNOWN = 0, LANG_Cobol74, LANG_Cobol85, LANG_C89, LANG_C99, LANG_C11, LANG_C, LANG_C_plus_plus_03, LANG_C_plus_plus_11, LANG_C_plus_plus_14, LANG_C_plus_plus, LANG_ObjC, LANG_ObjC_plus_plus, LANG_Fortran77, LANG_Fortran90, LANG_Fortran95, LANG_Ada83, LANG_Ada95, LANG_Pascal83, LANG_Modula2, LANG_Java, LANG_PLI, LANG_UPC, LANG_D, LANG_Python, LANG_Go, LANG_Rust, LANG_Mips_Assembler }; public: translation_unit(const ir::environment* env, const std::string& path, char address_size = 0); virtual ~translation_unit(); const environment* get_environment() const; environment* get_environment(); void set_environment(const environment*); language get_language() const; void set_language(language l); const std::string& get_path() const; void set_path(const string&); const std::string& get_compilation_dir_path() const; void set_compilation_dir_path(const std::string&); const std::string& get_absolute_path() const; void set_corpus(corpus*); const corpus* get_corpus() const; corpus* get_corpus(); const scope_decl_sptr& get_global_scope() const; scope_decl_sptr& get_global_scope(); const type_maps& get_types() const; type_maps& get_types(); const vector& get_live_fn_types() const; location_manager& get_loc_mgr(); const location_manager& get_loc_mgr() const; bool is_empty() const; char get_address_size() const; void set_address_size(char); bool is_constructed() const; void set_is_constructed(bool); bool operator==(const translation_unit&) const; bool operator!=(const translation_unit&) const; void bind_function_type_life_time(function_type_sptr) const; virtual bool traverse(ir_node_visitor& v); friend function_type_sptr lookup_function_type_in_translation_unit(const function_type& t, const translation_unit& tu); friend function_type_sptr synthesize_function_type_from_translation_unit(const function_type& fn_type, translation_unit& tu); friend type_base_sptr synthesize_type_from_translation_unit(const type_base_sptr& type, translation_unit& tu); };//end class translation_unit /// A comparison functor to compare translation units based on their /// absolute paths. struct shared_translation_unit_comp { /// Compare two translations units based on their absolute paths. /// /// @param lhs the first translation unit to consider for the /// comparison. /// /// @param rhs the second translatin unit to consider for the /// comparison. bool operator()(const translation_unit_sptr& lhs, const translation_unit_sptr& rhs) const {return lhs->get_absolute_path() < rhs->get_absolute_path();} }; // end struct shared_translation_unit_comp /// Convenience typedef for an ordered set of @ref /// translation_unit_sptr. typedef std::set translation_units; string translation_unit_language_to_string(translation_unit::language); translation_unit::language string_to_translation_unit_language(const string&); bool is_c_language(translation_unit::language l); bool is_cplus_plus_language(translation_unit::language l); bool is_java_language(translation_unit::language l); bool is_ada_language(translation_unit::language l); bool operator==(const translation_unit_sptr&, const translation_unit_sptr&); bool operator!=(const translation_unit_sptr&, const translation_unit_sptr&); /// Access specifier for class members. enum access_specifier { no_access, public_access, protected_access, private_access, }; class elf_symbol; /// A convenience typedef for a shared pointer to elf_symbol. typedef shared_ptr elf_symbol_sptr; /// A convenience typedef for a weak pointer to elf_symbol. typedef weak_ptr elf_symbol_wptr; /// Convenience typedef for a map which key is a string and which /// value if the elf symbol of the same name. typedef std::unordered_map string_elf_symbol_sptr_map_type; /// Convenience typedef for a shared pointer to an /// string_elf_symbol_sptr_map_type. typedef shared_ptr string_elf_symbol_sptr_map_sptr; /// Convenience typedef for a vector of elf_symbol typedef std::vector elf_symbols; /// Convenience typedef for a map which key is a string and which /// value is a vector of elf_symbol. typedef std::unordered_map string_elf_symbols_map_type; /// Convenience typedef for a shared pointer to /// string_elf_symbols_map_type. typedef shared_ptr string_elf_symbols_map_sptr; /// Abstraction of an elf symbol. /// /// This is useful when a given corpus has been read from an ELF file. /// In that case, a given decl might be associated to its underlying /// ELF symbol, if that decl is publicly exported in the ELF file. In /// that case, comparing decls might involve comparing their /// underlying symbols as well. class elf_symbol { public: /// The type of a symbol. enum type { NOTYPE_TYPE = 0, OBJECT_TYPE, FUNC_TYPE, SECTION_TYPE, FILE_TYPE, COMMON_TYPE, TLS_TYPE, GNU_IFUNC_TYPE }; /// The binding of a symbol. enum binding { LOCAL_BINDING = 0, GLOBAL_BINDING, WEAK_BINDING, GNU_UNIQUE_BINDING }; /// The visibility of the symbol. enum visibility { DEFAULT_VISIBILITY, PROTECTED_VISIBILITY, HIDDEN_VISIBILITY, INTERNAL_VISIBILITY, }; /// Inject the elf_symbol::version here. class version; private: struct priv; std::unique_ptr priv_; elf_symbol(); elf_symbol(const environment* e, size_t i, size_t s, const string& n, type t, binding b, bool d, bool c, const version& ve, visibility vi, bool is_in_ksymtab = false, const abg_compat::optional& crc = {}, const abg_compat::optional& ns = {}, bool is_suppressed = false); elf_symbol(const elf_symbol&); elf_symbol& operator=(const elf_symbol& s); public: static elf_symbol_sptr create(); static elf_symbol_sptr create(const environment* e, size_t i, size_t s, const string& n, type t, binding b, bool d, bool c, const version& ve, visibility vi, bool is_in_ksymtab = false, const abg_compat::optional& crc = {}, const abg_compat::optional& ns = {}, bool is_suppressed = false); const environment* get_environment() const; void set_environment(const environment*) const; size_t get_index() const; void set_index(size_t); const string& get_name() const; void set_name(const string& n); type get_type() const; void set_type(type t); size_t get_size() const; void set_size(size_t); binding get_binding() const; void set_binding(binding b); version& get_version() const; void set_version(const version& v); void set_visibility(visibility v); visibility get_visibility() const; bool is_defined() const; void is_defined(bool d); bool is_public() const; bool is_function() const; bool is_variable() const; bool is_in_ksymtab() const; void set_is_in_ksymtab(bool is_in_ksymtab); const abg_compat::optional& get_crc() const; void set_crc(const abg_compat::optional& crc); const abg_compat::optional& get_namespace() const; void set_namespace(const abg_compat::optional& ns); bool is_suppressed() const; void set_is_suppressed(bool is_suppressed); const elf_symbol_sptr get_main_symbol() const; elf_symbol_sptr get_main_symbol(); bool is_main_symbol() const; elf_symbol_sptr update_main_symbol(const std::string&); elf_symbol_sptr get_next_alias() const; bool has_aliases() const; int get_number_of_aliases() const; void add_alias(const elf_symbol_sptr&); bool is_common_symbol() const; bool has_other_common_instances() const; elf_symbol_sptr get_next_common_instance() const; void add_common_instance(const elf_symbol_sptr&); const string& get_id_string() const; elf_symbol_sptr get_alias_from_name(const string& name) const; elf_symbol_sptr get_alias_which_equals(const elf_symbol& other) const; string get_aliases_id_string(const string_elf_symbols_map_type& symtab, bool include_symbol_itself = true) const; string get_aliases_id_string(bool include_symbol_itself = true) const; static bool get_name_and_version_from_id(const string& id, string& name, string& ver); bool operator==(const elf_symbol&) const; bool does_alias(const elf_symbol&) const; }; // end class elf_symbol. std::ostream& operator<<(std::ostream& o, elf_symbol::type t); std::ostream& operator<<(std::ostream& o, elf_symbol::binding t); std::ostream& operator<<(std::ostream& o, elf_symbol::visibility t); bool string_to_elf_symbol_type(const string&, elf_symbol::type&); bool string_to_elf_symbol_binding(const string&, elf_symbol::binding&); bool string_to_elf_symbol_visibility(const string&, elf_symbol::visibility&); bool elf_symbol_is_function(elf_symbol::type); bool elf_symbol_is_variable(elf_symbol::type); bool operator==(const elf_symbol_sptr& lhs, const elf_symbol_sptr& rhs); bool operator!=(const elf_symbol_sptr& lhs, const elf_symbol_sptr& rhs); bool elf_symbols_alias(const elf_symbol& s1, const elf_symbol& s2); void compute_aliases_for_elf_symbol(const elf_symbol& symbol, const string_elf_symbols_map_type& symtab, vector& alias_set); /// The abstraction of the version of an ELF symbol. class elf_symbol::version { struct priv; std::unique_ptr priv_; public: version(); version(const string& v, bool is_default); version(const version& v); ~version(); operator const string&() const; const string& str() const; void str(const string& s); bool is_default() const; void is_default(bool f); bool is_empty() const; bool operator==(const version& o) const; bool operator!=(const version& o) const; version& operator=(const version& o); };// end class elf_symbol::version class context_rel; /// A convenience typedef for shared pointers to @ref context_rel typedef shared_ptr context_rel_sptr; /// The abstraction of the relationship between an entity and its /// containing scope (its context). That relationship can carry /// properties like access rights (if the parent is a class_decl), /// etc. /// /// But importantly, this relationship carries a pointer to the /// actualy parent. class context_rel { protected: scope_decl* scope_; enum access_specifier access_; bool is_static_; public: context_rel() : scope_(0), access_(no_access), is_static_(false) {} context_rel(scope_decl* s) : scope_(s), access_(no_access), is_static_(false) {} context_rel(scope_decl* s, access_specifier a, bool f) : scope_(s), access_(a), is_static_(f) {} scope_decl* get_scope() const {return scope_;} access_specifier get_access_specifier() const {return access_;} void set_access_specifier(access_specifier a) {access_ = a;} bool get_is_static() const {return is_static_;} void set_is_static(bool s) {is_static_ = s;} void set_scope(scope_decl* s) {scope_ = s;} bool operator==(const context_rel& o)const { return (access_ == o.access_ && is_static_ == o.is_static_); } /// Inequality operator. /// /// @param o the other instance of @ref context_rel to compare the /// current instance against. /// /// @return true iff the current instance of @ref context_rel is /// different from @p o. bool operator!=(const context_rel& o) const {return !operator==(o);} virtual ~context_rel(); };// end class context_rel /// A bitfield that gives callers of abigail::ir::equals() some /// insight about how different two internal representation artifacts /// are. enum change_kind { NO_CHANGE_KIND = 0, /// This means that a given IR artifact has a local type change. LOCAL_TYPE_CHANGE_KIND = 1 << 0, /// This means that a given IR artifact has a local non-type change. /// That is a change that is carried by the artifact itself, not by /// its type. LOCAL_NON_TYPE_CHANGE_KIND = 1 << 1, /// Testing (anding) against this mask means that a given IR artifact has /// local differences, with respect to the other artifact it was compared /// against. A local change is a change that is carried by the artifact /// itself (or its type), rather than by one off its sub-types. ALL_LOCAL_CHANGES_MASK = LOCAL_TYPE_CHANGE_KIND | LOCAL_NON_TYPE_CHANGE_KIND, /// This means that a given IR artifact has changes in some of its /// sub-types, with respect to the other artifact it was compared /// against. SUBTYPE_CHANGE_KIND = 1 << 2, };// end enum change_kind change_kind operator|(change_kind, change_kind); change_kind operator&(change_kind, change_kind); change_kind& operator|=(change_kind&, change_kind); change_kind& operator&=(change_kind&, change_kind); bool maybe_compare_as_member_decls(const decl_base& l, const decl_base& r, change_kind* k); bool equals(const decl_base&, const decl_base&, change_kind*); /// The base class of both types and declarations. class type_or_decl_base : public ir_traversable_base { struct priv; mutable std::unique_ptr priv_; type_or_decl_base(); protected: /// This is a bitmap type which instance is meant to contain the /// runtime type of a given ABI artifact. Bits of the identifiers /// of the type of a given artifact as well as the types it inherits /// from are to be set to 1. enum type_or_decl_kind { ABSTRACT_TYPE_OR_DECL, ABSTRACT_DECL_BASE = 1, ABSTRACT_SCOPE_DECL = 1 << 1, GLOBAL_SCOPE_DECL = 1 << 2, NAMESPACE_DECL = 1 << 3, VAR_DECL = 1 << 4, FUNCTION_DECL = 1 << 5, FUNCTION_PARAMETER_DECL = 1 << 6, METHOD_DECL = 1 << 7, TEMPLATE_DECL = 1 << 8, ABSTRACT_TYPE_BASE = 1 << 9, ABSTRACT_SCOPE_TYPE_DECL = 1 << 10, BASIC_TYPE = 1 << 11, QUALIFIED_TYPE = 1 << 12, POINTER_TYPE = 1 << 13, REFERENCE_TYPE = 1 << 14, ARRAY_TYPE = 1 << 15, ENUM_TYPE = 1 << 16, TYPEDEF_TYPE = 1 << 17, CLASS_TYPE = 1 << 18, UNION_TYPE = 1 << 19, FUNCTION_TYPE = 1 << 20, METHOD_TYPE = 1 << 21, }; // end enum type_or_decl_kind enum type_or_decl_kind kind() const; void kind(enum type_or_decl_kind); const void* runtime_type_instance() const; void* runtime_type_instance(); void runtime_type_instance(void*); const void* type_or_decl_base_pointer() const; void* type_or_decl_base_pointer(); bool hashing_started() const; void hashing_started(bool) const; public: type_or_decl_base(const environment*, enum type_or_decl_kind k = ABSTRACT_TYPE_OR_DECL); type_or_decl_base(const type_or_decl_base&); virtual ~type_or_decl_base(); bool get_is_artificial() const; void set_is_artificial(bool); const environment* get_environment() const; environment* get_environment(); void set_environment(const environment*); void set_artificial_location(const location &); location& get_artificial_location() const; bool has_artificial_location() const; const corpus* get_corpus() const; corpus* get_corpus(); void set_translation_unit(translation_unit*); const translation_unit* get_translation_unit() const; translation_unit* get_translation_unit(); type_or_decl_base& operator=(const type_or_decl_base&); virtual bool traverse(ir_node_visitor&); virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const = 0; friend type_or_decl_base::type_or_decl_kind operator|(type_or_decl_base::type_or_decl_kind, type_or_decl_base::type_or_decl_kind); friend type_or_decl_base::type_or_decl_kind& operator|=(type_or_decl_base::type_or_decl_kind&, type_or_decl_base::type_or_decl_kind); friend type_or_decl_base::type_or_decl_kind operator&(type_or_decl_base::type_or_decl_kind, type_or_decl_base::type_or_decl_kind); friend type_or_decl_base::type_or_decl_kind& operator&=(type_or_decl_base::type_or_decl_kind&, type_or_decl_base::type_or_decl_kind); friend class_decl* is_class_type(const type_or_decl_base*); friend pointer_type_def* is_pointer_type(type_or_decl_base*); friend type_base* is_type(const type_or_decl_base*); friend decl_base* is_decl(const type_or_decl_base* d); }; // end class type_or_decl_base type_or_decl_base::type_or_decl_kind operator|(type_or_decl_base::type_or_decl_kind, type_or_decl_base::type_or_decl_kind); type_or_decl_base::type_or_decl_kind& operator|=(type_or_decl_base::type_or_decl_kind&, type_or_decl_base::type_or_decl_kind); type_or_decl_base::type_or_decl_kind operator&(type_or_decl_base::type_or_decl_kind, type_or_decl_base::type_or_decl_kind); type_or_decl_base::type_or_decl_kind& operator&=(type_or_decl_base::type_or_decl_kind&, type_or_decl_base::type_or_decl_kind); bool operator==(const type_or_decl_base&, const type_or_decl_base&); bool operator==(const type_or_decl_base_sptr&, const type_or_decl_base_sptr&); bool operator!=(const type_or_decl_base_sptr&, const type_or_decl_base_sptr&); void set_environment_for_artifact(type_or_decl_base* artifact, const environment* env); void set_environment_for_artifact(type_or_decl_base_sptr artifact, const environment* env); /// The base type of all declarations. class decl_base : public virtual type_or_decl_base { // Forbidden decl_base(); struct priv; protected: const interned_string& peek_qualified_name() const; void clear_qualified_name(); void set_qualified_name(const interned_string&) const; const interned_string& peek_temporary_qualified_name() const; void set_temporary_qualified_name(const interned_string&) const; public: // This is public because some internals of the library need to // update it. But it's opaque to client code anyway, so no big // deal. Also, it's not handled by a shared_ptr because accessing // the data members of the priv struct for this decl_base shows up // on performance profiles when dealing with big binaries with a lot // of types; dereferencing the shared_ptr involves locking of some // sort and that is slower than just dereferencing a pointer likere // here. There are other types for which the priv pointer is // managed using shared_ptr just fine, because those didn't show up // during our performance profiling. priv* priv_; /// Facility to hash instances of decl_base. struct hash; /// ELF visibility enum visibility { VISIBILITY_NONE, VISIBILITY_DEFAULT, VISIBILITY_PROTECTED, VISIBILITY_HIDDEN, VISIBILITY_INTERNAL }; /// ELF binding enum binding { BINDING_NONE, BINDING_LOCAL, BINDING_GLOBAL, BINDING_WEAK }; virtual void set_scope(scope_decl*); protected: const context_rel* get_context_rel() const; context_rel* get_context_rel(); void set_context_rel(context_rel *c); public: decl_base(const environment* e, const string& name, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); decl_base(const environment* e, const interned_string& name, const location& locus, const interned_string& mangled_name = interned_string(), visibility vis = VISIBILITY_DEFAULT); decl_base(const environment*, const location&); decl_base(const decl_base&); virtual bool operator==(const decl_base&) const; virtual bool operator!=(const decl_base&) const; virtual bool traverse(ir_node_visitor& v); virtual ~decl_base(); virtual size_t get_hash() const; virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; virtual void get_qualified_name(interned_string& qualified_name, bool internal = false) const; virtual const interned_string& get_qualified_name(bool internal = false) const; virtual const interned_string& get_scoped_name() const; bool get_is_in_public_symbol_table() const; void set_is_in_public_symbol_table(bool); const location& get_location() const; void set_location(const location& l); const interned_string& get_name() const; const interned_string& get_qualified_parent_name() const; void set_name(const string& n); bool get_is_anonymous() const; void set_is_anonymous(bool); bool get_has_anonymous_parent() const; bool get_is_anonymous_or_has_anonymous_parent() const; typedef_decl_sptr get_naming_typedef() const; void set_naming_typedef(const typedef_decl_sptr&); const interned_string& get_linkage_name() const; virtual void set_linkage_name(const string& m); scope_decl* get_scope() const; visibility get_visibility() const; void set_visibility(visibility v); const decl_base_sptr get_earlier_declaration() const; void set_earlier_declaration(const decl_base_sptr&); const decl_base_sptr get_definition_of_declaration() const; void set_definition_of_declaration(const decl_base_sptr&); const decl_base* get_naked_definition_of_declaration() const; bool get_is_declaration_only() const; void set_is_declaration_only(bool f); friend type_base_sptr canonicalize(type_base_sptr); friend bool equals(const decl_base&, const decl_base&, change_kind*); friend bool equals(const var_decl&, const var_decl&, change_kind*); friend bool maybe_compare_as_member_decls(const decl_base& l, const decl_base& r, change_kind* k); friend decl_base_sptr add_decl_to_scope(decl_base_sptr decl, scope_decl* scpe); friend void remove_decl_from_scope(decl_base_sptr); friend decl_base_sptr insert_decl_into_scope(decl_base_sptr, vector >::iterator, scope_decl*); friend enum access_specifier get_member_access_specifier(const decl_base& d); friend enum access_specifier get_member_access_specifier(const decl_base_sptr& d); friend void set_member_access_specifier(decl_base& d, access_specifier a); friend bool get_member_is_static(const decl_base& d); friend bool get_member_is_static(const decl_base_sptr& d); friend void set_member_is_static(const decl_base_sptr& d, bool s); friend void set_member_is_static(decl_base& d, bool s); friend bool get_member_function_is_virtual(const function_decl& f); friend void set_member_function_is_virtual(function_decl&, bool); friend class class_or_union; friend class class_decl; friend class scope_decl; };// end class decl_base bool operator==(const decl_base_sptr&, const decl_base_sptr&); bool operator!=(const decl_base_sptr&, const decl_base_sptr&); bool operator==(const type_base_sptr&, const type_base_sptr&); bool operator!=(const type_base_sptr&, const type_base_sptr&); std::ostream& operator<<(std::ostream&, decl_base::visibility); std::ostream& operator<<(std::ostream&, decl_base::binding); bool equals(const scope_decl&, const scope_decl&, change_kind*); /// A declaration that introduces a scope. class scope_decl : public virtual decl_base { struct priv; std::unique_ptr priv_; public: /// Convenience typedef for a vector of @ref decl_base_sptr. typedef std::vector declarations; /// Convenience typedef for a vector of @ref function_type_sptr. typedef std::vector function_types; /// Convenience typedef for a vector of @ref scope_decl_sptr. typedef std::vector scopes; scope_decl(); protected: virtual decl_base_sptr add_member_decl(const decl_base_sptr& member); virtual decl_base_sptr insert_member_decl(decl_base_sptr member, declarations::iterator before); virtual void remove_member_decl(decl_base_sptr member); public: struct hash; scope_decl(const environment* env, const string& name, const location& locus, visibility vis = VISIBILITY_DEFAULT); scope_decl(const environment* env, location& l); virtual size_t get_hash() const; virtual bool operator==(const decl_base&) const; const canonical_type_sptr_set_type& get_canonical_types() const; canonical_type_sptr_set_type& get_canonical_types(); const type_base_sptrs_type& get_sorted_canonical_types() const; const declarations& get_member_decls() const; declarations& get_member_decls(); const declarations& get_sorted_member_decls() const; virtual size_t get_num_anonymous_member_classes() const; virtual size_t get_num_anonymous_member_unions() const; virtual size_t get_num_anonymous_member_enums() const; scopes& get_member_scopes(); const scopes& get_member_scopes() const; bool is_empty() const; bool find_iterator_for_member(const decl_base*, declarations::iterator&); bool find_iterator_for_member(const decl_base_sptr, declarations::iterator&); virtual bool traverse(ir_node_visitor&); virtual ~scope_decl(); friend decl_base_sptr add_decl_to_scope(decl_base_sptr decl, scope_decl* scope); friend decl_base_sptr insert_decl_into_scope(decl_base_sptr decl, scope_decl::declarations::iterator before, scope_decl* scope); friend void remove_decl_from_scope(decl_base_sptr decl); friend type_base_sptr canonicalize(type_base_sptr); };//end class scope_decl bool operator==(const scope_decl_sptr&, const scope_decl_sptr&); bool operator!=(const scope_decl_sptr&, const scope_decl_sptr&); /// Hasher for the @ref scope_decl type. struct scope_decl::hash { size_t operator()(const scope_decl& d) const; size_t operator()(const scope_decl* d) const; }; /// This abstracts the global scope of a given translation unit. /// /// Only one instance of this class must be present in a given /// translation_unit. That instance is implicitely created the first /// time translatin_unit::get_global_scope is invoked. class global_scope : public scope_decl { translation_unit* translation_unit_; global_scope(translation_unit *tu); public: friend class translation_unit; translation_unit* get_translation_unit() const {return translation_unit_;} virtual ~global_scope(); }; bool equals(const type_base&, const type_base&, change_kind*); /// An abstraction helper for type declarations class type_base : public virtual type_or_decl_base { struct priv; public: // This priv pointer is not handled by a shared_ptr because // accessing the data members of the priv struct for this type_base // shows up on performance profiles when dealing with big binaries // with a lot of types; dereferencing the shared_ptr involves // locking of some sort and that is slower than just dereferencing a // pointer likere here. There are other types for which the priv // pointer is managed using shared_ptr just fine, because those // didn't show up during our performance profiling. priv* priv_; private: // Forbid this. type_base(); static type_base_sptr get_canonical_type_for(type_base_sptr); protected: virtual void on_canonical_type_set(); public: /// A hasher for type_base types. struct hash; /// A hasher for types. It gets the dynamic type of the current /// instance of type and hashes it accordingly. Note that the hashing /// function of this hasher must be updated each time a new kind of /// type is added to the IR. struct dynamic_hash; /// A hasher for shared_ptr that will hash it based on the /// runtime type of the type pointed to. struct shared_ptr_hash; type_base(const environment* e, size_t s, size_t a); friend type_base_sptr canonicalize(type_base_sptr); type_base_sptr get_canonical_type() const; type_base* get_naked_canonical_type() const; const interned_string& get_cached_pretty_representation(bool internal = false) const; virtual bool operator==(const type_base&) const; virtual bool operator!=(const type_base&) const; virtual bool traverse(ir_node_visitor&); virtual ~type_base(); virtual void set_size_in_bits(size_t); virtual size_t get_size_in_bits() const; virtual void set_alignment_in_bits(size_t); virtual size_t get_alignment_in_bits() const; };//end class type_base /// Hash functor for instances of @ref type_base. struct type_base::hash { size_t operator()(const type_base& t) const; size_t operator()(const type_base* t) const; size_t operator()(const type_base_sptr t) const; }; // end struct type_base::hash /// A predicate for deep equality of instances of /// type_base* struct type_ptr_equal { bool operator()(const type_base* l, const type_base* r) const { if (!!l != !!r) return false; if (l == r) return true; if (l) return *l == *r; return true; } }; /// A predicate for deep equality of instances of /// shared_ptr struct type_shared_ptr_equal { bool operator()(const type_base_sptr l, const type_base_sptr r) const { if (!!l != !!r) return false; if (l.get() == r.get()) return true; if (l) return *l == *r; return true; } }; bool equals(const type_decl&, const type_decl&, change_kind*); /// A basic type declaration that introduces no scope. class type_decl : public virtual decl_base, public virtual type_base { // Forbidden. type_decl(); public: /// Facility to hash instance of type_decl struct hash; type_decl(const environment* env, const string& name, size_t size_in_bits, size_t alignment_in_bits, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); virtual bool operator==(const type_base&) const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_decl&) const; bool operator!=(const type_decl&)const; virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; virtual bool traverse(ir_node_visitor&); virtual ~type_decl(); };// end class type_decl. bool equals(const scope_type_decl&, const scope_type_decl&, change_kind*); bool operator==(const type_decl_sptr&, const type_decl_sptr&); bool operator!=(const type_decl_sptr&, const type_decl_sptr&); /// A type that introduces a scope. class scope_type_decl : public scope_decl, public virtual type_base { scope_type_decl(); public: /// Hasher for instances of scope_type_decl struct hash; scope_type_decl(const environment* env, const string& name, size_t size_in_bits, size_t alignment_in_bits, const location& locus, visibility vis = VISIBILITY_DEFAULT); virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual bool traverse(ir_node_visitor&); virtual ~scope_type_decl(); }; /// The abstraction of a namespace declaration class namespace_decl : public scope_decl { public: namespace_decl(const environment* env, const string& name, const location& locus, visibility vis = VISIBILITY_DEFAULT); virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; virtual bool operator==(const decl_base&) const; virtual bool traverse(ir_node_visitor&); virtual ~namespace_decl(); bool is_empty_or_has_empty_sub_namespaces() const; };// end class namespace_decl bool equals(const qualified_type_def&, const qualified_type_def&, change_kind*); /// The abstraction of a qualified type. class qualified_type_def : public virtual type_base, public virtual decl_base { class priv; std::unique_ptr priv_; // Forbidden. qualified_type_def(); protected: string build_name(bool, bool internal = false) const; virtual void on_canonical_type_set(); public: /// A Hasher for instances of qualified_type_def struct hash; /// Bit field values representing the cv qualifiers of the /// underlying type. enum CV { CV_NONE = 0, CV_CONST = 1, CV_VOLATILE = 1 << 1, CV_RESTRICT = 1 << 2 }; qualified_type_def(type_base_sptr type, CV quals, const location& locus); qualified_type_def(environment* env, CV quals, const location& locus); virtual size_t get_size_in_bits() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual bool operator==(const qualified_type_def&) const; CV get_cv_quals() const; void set_cv_quals(CV cv_quals); string get_cv_quals_string_prefix() const; type_base_sptr get_underlying_type() const; void set_underlying_type(const type_base_sptr&); virtual void get_qualified_name(interned_string& qualified_name, bool internal = false) const; virtual const interned_string& get_qualified_name(bool internal = false) const; virtual bool traverse(ir_node_visitor& v); virtual ~qualified_type_def(); }; // end class qualified_type_def. bool operator==(const qualified_type_def_sptr&, const qualified_type_def_sptr&); bool operator!=(const qualified_type_def_sptr&, const qualified_type_def_sptr&); qualified_type_def::CV operator|(qualified_type_def::CV, qualified_type_def::CV); qualified_type_def::CV& operator|=(qualified_type_def::CV&, qualified_type_def::CV); qualified_type_def::CV operator&(qualified_type_def::CV, qualified_type_def::CV); qualified_type_def::CV operator~(qualified_type_def::CV); std::ostream& operator<<(std::ostream&, qualified_type_def::CV); string get_string_representation_of_cv_quals(const qualified_type_def::CV); interned_string get_name_of_qualified_type(const type_base_sptr& underlying_type, qualified_type_def::CV quals, bool qualified = true, bool internal = false); qualified_type_def_sptr lookup_qualified_type(const type_base_sptr&, qualified_type_def::CV, const translation_unit&); bool equals(const pointer_type_def&, const pointer_type_def&, change_kind*); /// The abstraction of a pointer type. class pointer_type_def : public virtual type_base, public virtual decl_base { struct priv; std::unique_ptr priv_; // Forbidden. pointer_type_def(); protected: virtual void on_canonical_type_set(); public: /// A hasher for instances of pointer_type_def struct hash; pointer_type_def(const type_base_sptr& pointed_to_type, size_t size_in_bits, size_t alignment_in_bits, const location& locus); pointer_type_def(environment* env, size_t size_in_bits, size_t alignment_in_bits, const location& locus); void set_pointed_to_type(const type_base_sptr&); virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; bool operator==(const pointer_type_def&) const; const type_base_sptr get_pointed_to_type() const; type_base* get_naked_pointed_to_type() const; virtual void get_qualified_name(interned_string&, bool internal = false) const; virtual const interned_string& get_qualified_name(bool internal = false) const; virtual bool traverse(ir_node_visitor& v); virtual ~pointer_type_def(); }; // end class pointer_type_def bool operator==(const pointer_type_def_sptr&, const pointer_type_def_sptr&); bool operator!=(const pointer_type_def_sptr&, const pointer_type_def_sptr&); bool equals(const reference_type_def&, const reference_type_def&, change_kind*); /// Abstracts a reference type. class reference_type_def : public virtual type_base, public virtual decl_base { type_base_wptr pointed_to_type_; bool is_lvalue_; // Forbidden. reference_type_def(); protected: virtual void on_canonical_type_set(); public: /// Hasher for intances of reference_type_def. struct hash; reference_type_def(const type_base_sptr pointed_to_type, bool lvalue, size_t size_in_bits, size_t alignment_in_bits, const location& locus); reference_type_def(const environment* env, bool lvalue, size_t size_in_bits, size_t alignment_in_bits, const location& locus); void set_pointed_to_type(type_base_sptr& pointed_to_type); virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; bool operator==(const reference_type_def&) const; type_base_sptr get_pointed_to_type() const; bool is_lvalue() const; virtual void get_qualified_name(interned_string& qualified_name, bool internal = false) const; virtual const interned_string& get_qualified_name(bool internal = false) const; virtual bool traverse(ir_node_visitor& v); virtual ~reference_type_def(); }; // end class reference_type_def bool operator==(const reference_type_def_sptr&, const reference_type_def_sptr&); bool operator!=(const reference_type_def_sptr&, const reference_type_def_sptr&); bool equals(const array_type_def&, const array_type_def&, change_kind*); /// The abstraction of an array type. class array_type_def : public virtual type_base, public virtual decl_base { struct priv; std::unique_ptr priv_; // Forbidden. array_type_def(); void update_size(); public: /// Hasher for intances of array_type_def. struct hash; class subrange_type; /// Convenience typedef for a shared pointer on a @ref /// function_decl::subrange typedef shared_ptr subrange_sptr; /// Convenience typedef for a vector of @ref subrange_sptr typedef std::vector subranges_type; /// Abstraction for an array range type, like in Ada, or just for an /// array dimension like in C or C++. class subrange_type : public virtual type_base, public virtual decl_base { struct priv; std::unique_ptr priv_; // Forbidden. subrange_type(); public: virtual ~subrange_type(); /// This class is to hold the value of the bound of a subrange. /// The value can be either signed or unsigned, at least when it /// comes from DWARF. The class keeps the sign information, but /// allows users to access the value as signed or unsigned as they /// see fit. class bound_value { public: enum signedness { UNSIGNED_SIGNEDNESS, SIGNED_SIGNEDNESS }; private: signedness s_; public: union { uint64_t unsigned_; int64_t signed_; } v_; bound_value(); bound_value(uint64_t); bound_value(int64_t); enum signedness get_signedness() const; void set_signedness(enum signedness s); int64_t get_signed_value() const; uint64_t get_unsigned_value(); void set_unsigned(uint64_t v); void set_signed(int64_t v); bool operator==(const bound_value&) const; }; //end class bound_value /// Hasher for an instance of array::subrange struct hash; subrange_type(const environment* env, const string& name, bound_value lower_bound, bound_value upper_bound, const type_base_sptr& underlying_type, const location& loc, translation_unit::language l = translation_unit::LANG_C11); subrange_type(const environment* env, const string& name, bound_value lower_bound, bound_value upper_bound, const location& loc, translation_unit::language l = translation_unit::LANG_C11); subrange_type(const environment* env, const string& name, bound_value upper_bound, const location& loc, translation_unit::language l = translation_unit::LANG_C11); type_base_sptr get_underlying_type() const; void set_underlying_type(const type_base_sptr &); int64_t get_upper_bound() const; int64_t get_lower_bound() const; void set_upper_bound(int64_t ub); void set_lower_bound(int64_t lb); uint64_t get_length() const; bool is_infinite() const; void is_infinite(bool); translation_unit::language get_language() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; bool operator==(const subrange_type& o) const; bool operator!=(const subrange_type& o) const; string as_string() const; static string vector_as_string(const vector&); virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; virtual bool traverse(ir_node_visitor&); }; // end class subrange_type array_type_def(const type_base_sptr type, const std::vector& subs, const location& locus); array_type_def(environment* env, const std::vector& subs, const location& locus); translation_unit::language get_language() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual void get_qualified_name(interned_string& qualified_name, bool internal = false) const; virtual const interned_string& get_qualified_name(bool internal = false) const; const type_base_sptr get_element_type() const; void set_element_type(const type_base_sptr& element_type); virtual void append_subranges(const std::vector& subs); virtual int get_dimension_count() const; virtual bool is_infinite() const; virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; virtual string get_subrange_representation() const; virtual bool traverse(ir_node_visitor& v); const location& get_location() const; const std::vector& get_subranges() const; virtual ~array_type_def(); }; // end class array_type_def array_type_def::subrange_type* is_subrange_type(const type_or_decl_base *type); array_type_def::subrange_sptr is_subrange_type(const type_or_decl_base_sptr &type); bool equals(const enum_type_decl&, const enum_type_decl&, change_kind*); /// Abstracts a declaration for an enum type. class enum_type_decl : public virtual type_base, public virtual decl_base { class priv; std::unique_ptr priv_; // Forbidden enum_type_decl(); public: /// A hasher for an enum_type_decl. struct hash; /// Enumerator Datum. class enumerator; /// Convenience typedef for a list of @ref enumerator. typedef std::vector enumerators; /// Constructor of an enum type declaration. /// /// @param name the name of the enum /// /// @param locus the locus at which the enum appears in the source /// code. /// /// @param underlying_type the underlying type of the enum /// /// @param enms a list of enumerators for this enum. /// /// @param mangled_name the mangled name of the enum type. /// /// @param vis the visibility of instances of this type. enum_type_decl(const string& name, const location& locus, type_base_sptr underlying_type, enumerators& enms, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); type_base_sptr get_underlying_type() const; const enumerators& get_enumerators() const; enumerators& get_enumerators(); virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual bool traverse(ir_node_visitor& v); virtual ~enum_type_decl(); friend bool enum_has_non_name_change(const enum_type_decl& l, const enum_type_decl& r, change_kind* k); }; // end class enum_type_decl bool operator==(const enum_type_decl_sptr& l, const enum_type_decl_sptr& r); bool operator!=(const enum_type_decl_sptr& l, const enum_type_decl_sptr& r); bool enum_has_non_name_change(const enum_type_decl& l, const enum_type_decl& r, change_kind* k); /// The abstraction of an enumerator class enum_type_decl::enumerator { class priv; std::unique_ptr priv_; public: enumerator(); ~enumerator(); enumerator(const environment* env, const string& name, int64_t value); enumerator(const enumerator&); enumerator& operator=(const enumerator&); bool operator==(const enumerator& other) const; bool operator!=(const enumerator& other) const; const environment* get_environment() const; const interned_string& get_name() const; const interned_string& get_qualified_name(bool internal = false) const; void set_name(const string& n); int64_t get_value() const; void set_value(int64_t v); enum_type_decl* get_enum_type() const; void set_enum_type(enum_type_decl*); }; // end class enum_type_def::enumerator bool equals(const typedef_decl&, const typedef_decl&, change_kind*); /// The abstraction of a typedef declaration. class typedef_decl : public virtual type_base, public virtual decl_base { struct priv; std::unique_ptr priv_; // Forbidden typedef_decl(); public: /// Hasher for the typedef_decl type. struct hash; typedef_decl(const string& name, const type_base_sptr underlying_type, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); typedef_decl(const string& name, environment* env, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); virtual size_t get_size_in_bits() const; virtual size_t get_alignment_in_bits() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; type_base_sptr get_underlying_type() const; void set_underlying_type(const type_base_sptr&); virtual bool traverse(ir_node_visitor&); virtual ~typedef_decl(); };// end class typedef_decl /// The abstraction for a data member context relationship. This /// relates a data member to its parent class. /// /// The relationship carries properties like the offset of the data /// member, if applicable. class dm_context_rel : public context_rel { protected: struct priv; std::unique_ptr priv_; public: dm_context_rel(); dm_context_rel(scope_decl* s, bool is_laid_out, size_t offset_in_bits, access_specifier a, bool is_static); dm_context_rel(scope_decl* s); bool get_is_laid_out() const; void set_is_laid_out(bool f); size_t get_offset_in_bits() const; void set_offset_in_bits(size_t o); const var_decl* get_anonymous_data_member() const; void set_anonymous_data_member(var_decl *); bool operator==(const dm_context_rel& o) const; bool operator!=(const dm_context_rel& o) const; virtual ~dm_context_rel(); };// end class class_decl::dm_context_rel bool equals(const var_decl&, const var_decl&, change_kind*); bool equals_modulo_cv_qualifier(const array_type_def*, const array_type_def*); /// Abstracts a variable declaration. class var_decl : public virtual decl_base { struct priv; std::unique_ptr priv_; // Forbidden var_decl(); virtual void set_scope(scope_decl*); public: /// Hasher for a var_decl type. struct hash; /// Equality functor to compare pointers to variable_decl. struct ptr_equal; var_decl(const string& name, type_base_sptr type, const location& locus, const string& mangled_name, visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_NONE); virtual bool operator==(const decl_base&) const; const type_base_sptr get_type() const; const type_base* get_naked_type() const; binding get_binding() const; void set_binding(binding b); void set_symbol(const elf_symbol_sptr& sym); const elf_symbol_sptr& get_symbol() const; var_decl_sptr clone() const; interned_string get_id() const; virtual const interned_string& get_qualified_name(bool internal = false) const; virtual size_t get_hash() const; virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; string get_anon_dm_reliable_name(bool qualified = true) const; virtual bool traverse(ir_node_visitor& v); virtual ~var_decl(); friend void set_data_member_offset(var_decl_sptr m, uint64_t o); friend uint64_t get_data_member_offset(const var_decl_sptr m); friend uint64_t get_data_member_offset(const var_decl& m); friend uint64_t get_absolute_data_member_offset(const var_decl& m); friend uint64_t get_absolute_data_member_offset(const var_decl_sptr& m); friend void set_data_member_is_laid_out(var_decl_sptr m, bool l); friend bool get_data_member_is_laid_out(const var_decl& m); friend bool get_data_member_is_laid_out(const var_decl_sptr m); }; // end class var_decl bool equals(const function_decl&, const function_decl&, change_kind*); /// Abstraction for a function declaration. class function_decl : public virtual decl_base { struct priv; // This priv pointer is not handled by a shared_ptr because // accessing the data members of the priv struct for this // function_decl shows up on performance profiles when dealing with // big binaries with a lot of types; dereferencing the shared_ptr // involves locking of some sort and that is slower than just // dereferencing a pointer likere here. There are other types for // which the priv pointer is managed using shared_ptr just fine, // because those didn't show up during our performance profiling. priv* priv_; public: /// Hasher for function_decl struct hash; /// Equality functor to compare pointers to function_decl struct ptr_equal; /// Abstraction for the parameter of a function. class parameter; /// Convenience typedef for a shared pointer on a @ref /// function_decl::parameter typedef shared_ptr parameter_sptr; /// Convenience typedef for a vector of @ref parameter_sptr typedef std::vector parameters; function_decl(const string& name, function_type_sptr function_type, bool declared_inline, const location& locus, const string& mangled_name, visibility vis, binding bind); function_decl(const string& name, type_base_sptr fn_type, bool declared_inline, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_GLOBAL); virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; string get_pretty_representation_of_declarator (bool internal = false) const; const std::vector& get_parameters() const; void append_parameter(parameter_sptr parm); void append_parameters(std::vector& parms); parameters::const_iterator get_first_non_implicit_parm() const; const function_type_sptr get_type() const; const function_type* get_naked_type() const; const type_base_sptr get_return_type() const; void set_type(const function_type_sptr& fn_type); void set_symbol(const elf_symbol_sptr& sym); const elf_symbol_sptr& get_symbol() const; bool is_declared_inline() const; binding get_binding() const; function_decl_sptr clone() const; virtual bool operator==(const decl_base& o) const; /// Return true iff the function takes a variable number of /// parameters. /// /// @return true if the function taks a variable number /// of parameters. bool is_variadic() const; virtual size_t get_hash() const; interned_string get_id() const; virtual bool traverse(ir_node_visitor&); virtual ~function_decl(); }; // end class function_decl bool operator==(const function_decl_sptr& l, const function_decl_sptr& r); bool operator!=(const function_decl_sptr& l, const function_decl_sptr& r); bool function_decls_alias(const function_decl& f1, const function_decl& f2); bool equals(const function_decl::parameter&, const function_decl::parameter&, change_kind*); /// A comparison functor to compare pointer to instances of @ref /// type_or_decl_base. struct type_or_decl_base_comp { /// Comparison operator for ABI artifacts. /// /// @param f the first ABI artifact to consider for the comparison. /// /// @param s the second ABI artifact to consider for the comparison. /// /// @return true iff @p f is lexicographically less than than @p s. bool operator()(const type_or_decl_base *f, const type_or_decl_base *s) { function_decl *f_fn = is_function_decl(f), *s_fn = is_function_decl(s); if (f_fn && s_fn) return function_decl_is_less_than(*f_fn, *s_fn); var_decl *f_var = is_var_decl(f), *s_var = is_var_decl(s); if (f_var && s_var) return get_name(f_var) < get_name(s_var); string l_repr = get_pretty_representation(f), r_repr = get_pretty_representation(s); return l_repr < r_repr; } /// Comparison operator for ABI artifacts. /// /// @param f the first ABI artifact to consider for the comparison. /// /// @param s the second ABI artifact to consider for the comparison. /// /// @return true iff @p f is lexicographically less than than @p s. bool operator()(const type_or_decl_base_sptr& f, const type_or_decl_base_sptr& s) {return operator()(f.get(), s.get());} }; // end struct type_or_decl_base_comp /// Abstraction of a function parameter. class function_decl::parameter : public decl_base { struct priv; std::unique_ptr priv_; public: /// Hasher for an instance of function::parameter struct hash; parameter(const type_base_sptr type, unsigned index, const string& name, const location& loc, bool variadic_marker = false); parameter(const type_base_sptr type, unsigned index, const string& name, const location& loc, bool variadic_marker, bool is_artificial); parameter(const type_base_sptr type, const string& name, const location& loc, bool variadic_marker = false, bool is_artificial = false); parameter(const type_base_sptr type, unsigned index = 0, bool variadic_marker = false); virtual ~parameter(); const type_base_sptr get_type()const; interned_string get_type_name() const; const string get_type_pretty_representation() const; interned_string get_name_id() const; unsigned get_index() const; void set_index(unsigned i); bool get_variadic_marker() const; bool operator==(const parameter& o) const; virtual bool operator==(const decl_base&) const; virtual bool traverse(ir_node_visitor& v); virtual size_t get_hash() const; virtual void get_qualified_name(interned_string& qualified_name, bool internal = false) const; virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; }; // end class function_decl::parameter bool operator==(const function_decl::parameter_sptr&, const function_decl::parameter_sptr&); /// A hashing functor for a function_decl::parameter. struct function_decl::parameter::hash { size_t operator()(const function_decl::parameter&) const; size_t operator()(const function_decl::parameter*) const; size_t operator()(const function_decl::parameter_sptr) const; }; // end struct function_decl::parameter::hash function_decl::parameter* is_function_parameter(const type_or_decl_base*); function_decl::parameter_sptr is_function_parameter(const type_or_decl_base_sptr tod); bool equals(const function_type&, const function_type&, change_kind*); /// Abstraction of a function type. class function_type : public virtual type_base { protected: virtual void on_canonical_type_set(); public: /// Hasher for an instance of function_type struct hash; /// Convenience typedef for a shared pointer on a @ref /// function_decl::parameter typedef shared_ptr parameter_sptr; /// Convenience typedef for a vector of @ref parameter_sptr typedef std::vector parameters; struct priv; std::unique_ptr priv_; private: function_type(); public: function_type(type_base_sptr return_type, const parameters& parms, size_t size_in_bits, size_t alignment_in_bits); function_type(type_base_sptr return_type, size_t size_in_bits, size_t alignment_in_bits); function_type(const environment* env, size_t size_in_bits, size_t alignment_in_bits); type_base_sptr get_return_type() const; void set_return_type(type_base_sptr t); const parameters& get_parameters() const; const parameter_sptr get_parm_at_index_from_first_non_implicit_parm(size_t) const; void set_parameters(const parameters &p); void append_parameter(parameter_sptr parm); bool is_variadic() const; parameters::const_iterator get_first_non_implicit_parm() const; parameters::const_iterator get_first_parm() const; const interned_string& get_cached_name(bool internal = false) const; virtual bool operator==(const type_base&) const; virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; virtual bool traverse(ir_node_visitor&); virtual ~function_type(); friend bool equals(const function_type&, const function_type&, change_kind*); };//end class function_type /// The hashing functor for @ref function_type. struct function_type::hash { size_t operator()(const function_type& t) const; size_t operator()(const function_type* t) const; size_t operator()(const function_type_sptr t) const; };// end struct function_type::hash /// Abstracts the type of a class member function. class method_type : public function_type { struct priv; std::unique_ptr priv_; method_type(); public: /// Hasher for intances of method_type struct hash; method_type(type_base_sptr return_type, class_or_union_sptr class_type, const std::vector& parms, bool is_const, size_t size_in_bits, size_t alignment_in_bits); method_type(type_base_sptr return_type, type_base_sptr class_type, const std::vector& parms, bool is_const, size_t size_in_bits, size_t alignment_in_bits); method_type(class_or_union_sptr class_type, bool is_const, size_t size_in_bits, size_t alignment_in_bits); method_type(const environment* env, size_t size_in_bits, size_t alignment_in_bits); class_or_union_sptr get_class_type() const; void set_class_type(const class_or_union_sptr& t); void set_is_const(bool); bool get_is_const() const; virtual ~method_type(); virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; friend interned_string get_method_type_name(const method_type& fn_type, bool internal); };// end class method_type. /// The base class of templates. class template_decl : public virtual decl_base { class priv; std::unique_ptr priv_; template_decl(); public: /// Hasher. struct hash; template_decl(const environment* env, const string& name, const location& locus, visibility vis = VISIBILITY_DEFAULT); void add_template_parameter(const template_parameter_sptr p); const std::list& get_template_parameters() const; virtual bool operator==(const template_decl& o) const; virtual ~template_decl(); };//end class template_decl /// Base class for a template parameter. Client code should use the /// more specialized type_template_parameter, /// non_type_template_parameter and template_template_parameter below. class template_parameter { class priv; std::unique_ptr priv_; // Forbidden template_parameter(); public: /// Hashers. struct hash; struct dynamic_hash; struct shared_ptr_hash; template_parameter(unsigned index, template_decl_sptr enclosing_tdecl); virtual bool operator==(const template_parameter&) const; bool operator!=(const template_parameter&) const; unsigned get_index() const; const template_decl_sptr get_enclosing_template_decl() const; bool get_hashing_has_started() const; void set_hashing_has_started(bool f) const; virtual ~template_parameter(); };//end class template_parameter struct template_decl::hash { size_t operator()(const template_decl& t) const; };// end struct template_decl::hash /// Abstracts a type template parameter. class type_tparameter : public template_parameter, public virtual type_decl { class priv; std::unique_ptr priv_; // Forbidden type_tparameter(); public: /// Hasher. struct hash; type_tparameter(unsigned index, template_decl_sptr enclosing_tdecl, const string& name, const location& locus); virtual bool operator==(const type_base&) const; virtual bool operator==(const template_parameter&) const; virtual bool operator==(const type_tparameter&) const; virtual ~type_tparameter(); };// end class type_tparameter. /// Abstracts non type template parameters. class non_type_tparameter : public template_parameter, public virtual decl_base { class priv; std::unique_ptr priv_; type_base_wptr type_; // Forbidden non_type_tparameter(); public: /// Hasher. struct hash; non_type_tparameter(unsigned index, template_decl_sptr enclosing_tdecl, const string& name, type_base_sptr type, const location& locus); virtual size_t get_hash() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const template_parameter&) const; const type_base_sptr get_type() const; virtual ~non_type_tparameter(); };// end class non_type_tparameter /// Hasher for the @ref non_type_tparameter type. struct non_type_tparameter::hash { size_t operator()(const non_type_tparameter& t) const; size_t operator()(const non_type_tparameter* t) const; }; class template_tparameter; /// Abstracts a template template parameter. class template_tparameter : public type_tparameter, public template_decl { class priv; std::unique_ptr priv_; // Forbidden template_tparameter(); public: /// A hasher for instances of template_tparameter struct hash; template_tparameter(unsigned index, template_decl_sptr enclosing_tdecl, const string& name, const location& locus); virtual bool operator==(const type_base&) const; virtual bool operator==(const template_parameter&) const; virtual bool operator==(const template_decl&) const; virtual ~template_tparameter(); }; /// This abstracts a composition of types based on template type /// parameters. The result of the composition is a type that can be /// referred to by a template non-type parameter. Instances of this /// type can appear at the same level as template parameters, in the /// scope of a template_decl. class type_composition : public template_parameter, public virtual decl_base { class priv; std::unique_ptr priv_; type_composition(); public: struct hash; type_composition(unsigned index, template_decl_sptr tdecl, type_base_sptr composed_type); const type_base_sptr get_composed_type() const; void set_composed_type(type_base_sptr t); virtual size_t get_hash() const; virtual ~type_composition(); }; /// Hasher for the @ref type_composition type. struct type_composition::hash { size_t operator()(const type_composition& t) const; size_t operator()(const type_composition* t) const; }; //struct type_composition::hash /// Abstract a function template declaration. class function_tdecl : public template_decl, public scope_decl { class priv; std::unique_ptr priv_; // Forbidden function_tdecl(); public: /// Hash functor for function templates. struct hash; struct shared_ptr_hash; function_tdecl(const environment* env, const location& locus, visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_NONE); function_tdecl(function_decl_sptr pattern, const location& locus, visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_NONE); virtual bool operator==(const decl_base&) const; virtual bool operator==(const template_decl&) const; virtual bool operator==(const function_tdecl&) const; void set_pattern(shared_ptr p); shared_ptr get_pattern() const; binding get_binding() const; virtual bool traverse(ir_node_visitor& v); virtual ~function_tdecl(); }; // end class function_tdecl. /// Abstract a class template. class class_tdecl : public template_decl, public scope_decl { class priv; std::unique_ptr priv_; // Forbidden class_tdecl(); public: /// Hashers. struct hash; struct shared_ptr_hash; class_tdecl(const environment* env, const location& locus, visibility vis = VISIBILITY_DEFAULT); class_tdecl(class_decl_sptr pattern, const location& locus, visibility vis = VISIBILITY_DEFAULT); virtual bool operator==(const decl_base&) const; virtual bool operator==(const template_decl&) const; virtual bool operator==(const class_tdecl&) const; void set_pattern(class_decl_sptr p); shared_ptr get_pattern() const; virtual bool traverse(ir_node_visitor& v); virtual ~class_tdecl(); };// end class class_tdecl /// The base class for member types, data members and member /// functions. Its purpose is mainly to carry the access specifier /// (and possibly other properties that might be shared by all class /// members) for the member. class member_base { protected: enum access_specifier access_; bool is_static_; private: // Forbidden member_base(); public: /// Hasher. struct hash; member_base(access_specifier a, bool is_static = false) : access_(a), is_static_(is_static) {} /// Getter for the access specifier of this member. /// /// @return the access specifier for this member. access_specifier get_access_specifier() const {return access_;} /// Setter for the access specifier of this member. /// /// @param a the new access specifier. void set_access_specifier(access_specifier a) {access_ = a;} /// @return true if the member is static, false otherwise. bool get_is_static() const {return is_static_;} /// Set a flag saying if the parameter is static or not. /// /// @param f set to true if the member is static, false otherwise. void set_is_static(bool f) {is_static_ = f;} virtual bool operator==(const member_base& o) const; };// end class member_base /// Abstraction of the declaration of a method. class method_decl : public function_decl { method_decl(); virtual void set_scope(scope_decl*); public: method_decl(const string& name, method_type_sptr type, bool declared_inline, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_GLOBAL); method_decl(const string& name, function_type_sptr type, bool declared_inline, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_GLOBAL); method_decl(const string& name, type_base_sptr type, bool declared_inline, const location& locus, const string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_GLOBAL); virtual void set_linkage_name(const string&); /// @return the type of the current instance of the /// method_decl. const method_type_sptr get_type() const; void set_type(const method_type_sptr fn_type) {function_decl::set_type(fn_type);} friend bool get_member_function_is_ctor(const function_decl&); friend void set_member_function_is_ctor(function_decl&, bool); friend void set_member_function_is_ctor(const function_decl_sptr&, bool); friend bool get_member_function_is_dtor(const function_decl&); friend void set_member_function_is_dtor(function_decl&, bool); friend void set_member_function_is_dtor(const function_decl_sptr&, bool); friend bool get_member_function_is_static(const function_decl&); friend void set_member_function_is_static(const function_decl&, bool); friend bool get_member_function_is_const(const function_decl&); friend void set_member_function_is_const(function_decl&, bool); friend void set_member_function_is_const(const function_decl_sptr&, bool); friend bool member_function_has_vtable_offset(const function_decl&); friend ssize_t get_member_function_vtable_offset(const function_decl&); friend void set_member_function_vtable_offset(function_decl&, ssize_t); friend void set_member_function_vtable_offset(const function_decl_sptr&, ssize_t); friend bool get_member_function_is_virtual(const function_decl&); friend void set_member_function_is_virtual(function_decl&, bool); virtual ~method_decl(); };// end class method_decl bool operator==(const method_decl_sptr& l, const method_decl_sptr& r); bool operator!=(const method_decl_sptr& l, const method_decl_sptr& r); /// The base type of @ref class_decl and @ref union_decl class class_or_union : public scope_type_decl { public: struct priv; priv *priv_; private: // Forbidden class_or_union(); protected: virtual decl_base_sptr add_member_decl(const decl_base_sptr&); virtual decl_base_sptr insert_member_decl(decl_base_sptr member, declarations::iterator before); virtual void remove_member_decl(decl_base_sptr); void maybe_fixup_members_of_anon_data_member(var_decl_sptr& anon_dm); public: /// Hasher. struct hash; /// Convenience typedef /// @{ typedef vector member_types; typedef vector data_members; typedef vector member_functions; typedef unordered_map virtual_mem_fn_map_type; typedef unordered_map string_mem_fn_ptr_map_type; typedef unordered_map string_mem_fn_sptr_map_type; /// @} class_or_union(const environment* env, const string& name, size_t size_in_bits, size_t align_in_bits, const location& locus, visibility vis, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns); class_or_union(const environment* env, const string& name, size_t size_in_bits, size_t align_in_bits, const location& locus, visibility vis); class_or_union(const environment* env, const string& name, bool is_declaration_only = true); virtual void set_size_in_bits(size_t); virtual size_t get_size_in_bits() const; virtual size_t get_alignment_in_bits() const; virtual void set_alignment_in_bits(size_t); void insert_member_type(type_base_sptr t, declarations::iterator before); void add_member_type(type_base_sptr t); type_base_sptr add_member_type(type_base_sptr t, access_specifier a); void remove_member_type(type_base_sptr t); const member_types& get_member_types() const; virtual size_t get_num_anonymous_member_classes() const; virtual size_t get_num_anonymous_member_unions() const; virtual size_t get_num_anonymous_member_enums() const; type_base_sptr find_member_type(const string& name) const; void add_data_member(var_decl_sptr v, access_specifier a, bool is_laid_out, bool is_static, size_t offset_in_bits); const data_members& get_data_members() const; const var_decl_sptr find_data_member(const string&) const; const var_decl_sptr find_data_member(const var_decl_sptr&) const; const var_decl_sptr find_anonymous_data_member(const var_decl_sptr&) const; const data_members& get_non_static_data_members() const; void add_member_function(method_decl_sptr f, access_specifier a, bool is_static, bool is_ctor, bool is_dtor, bool is_const); void add_member_function(method_decl_sptr f, access_specifier a, bool is_virtual, size_t vtable_offset, bool is_static, bool is_ctor, bool is_dtor, bool is_const); const member_functions& get_member_functions() const; const method_decl* find_member_function(const string& mangled_name) const; method_decl* find_member_function(const string& mangled_name); method_decl_sptr find_member_function_sptr(const string& mangled_name); const method_decl* find_member_function_from_signature(const string& s) const; method_decl* find_member_function_from_signature(const string& s); void add_member_function_template(member_function_template_sptr); const member_function_templates& get_member_function_templates() const; void add_member_class_template(member_class_template_sptr m); const member_class_templates& get_member_class_templates() const; bool has_no_member() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual bool operator==(const class_or_union&) const; virtual bool traverse(ir_node_visitor& v); virtual ~class_or_union(); friend method_decl_sptr copy_member_function(class_or_union_sptr& t, const method_decl*m); friend method_decl_sptr copy_member_function(class_or_union_sptr& t, const method_decl_sptr& m); friend void fixup_virtual_member_function(method_decl_sptr method); friend void set_member_is_static(decl_base& d, bool s); friend bool equals(const class_or_union&, const class_or_union&, change_kind*); friend bool equals(const class_decl&, const class_decl&, change_kind*); friend class method_decl; friend class class_decl; }; // end class class_or_union method_decl_sptr copy_member_function(const class_or_union_sptr& clazz, const method_decl_sptr& f); method_decl_sptr copy_member_function(const class_or_union_sptr& clazz, const method_decl* f); bool operator==(const class_or_union_sptr& l, const class_or_union_sptr& r); bool operator!=(const class_or_union_sptr& l, const class_or_union_sptr& r); /// Hasher for the @ref class_or_union type struct class_or_union::hash { size_t operator()(const class_or_union& t) const; size_t operator()(const class_or_union* t) const; }; // end struct class_decl::hash /// Abstracts a class declaration. class class_decl : public class_or_union { // Forbidden class_decl(); protected: virtual decl_base_sptr insert_member_decl(decl_base_sptr member, declarations::iterator before); public: /// Hasher. struct hash; /// Forward declarations. class base_spec; /// Convenience typedef /// @{ typedef shared_ptr base_spec_sptr; typedef vector base_specs; /// @} protected: virtual void on_canonical_type_set(); private: struct priv; // This priv it's not handled by a shared_ptr because accessing the // data members of the priv struct for this class_decl shows up on // performance profiles when dealing with big binaries with a lot of // types; dereferencing the shared_ptr involves locking of some sort // and that is slower than just dereferencing a pointer likere here. // There are other types for which the priv pointer is managed using // shared_ptr just fine, because those didn't show up during our // performance profiling. priv * priv_; public: class_decl(const environment* env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, base_specs& bases, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns); class_decl(const environment* env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, base_specs& bases, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns, bool is_anonymous); class_decl(const environment* env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis); class_decl(const environment* env, const string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, const location& locus, visibility vis, bool is_anonymous); class_decl(const environment* env, const string& name, bool is_struct, bool is_declaration_only = true); virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; void is_struct(bool f); bool is_struct() const; void add_base_specifier(shared_ptr b); const base_specs& get_base_specifiers() const; class_decl_sptr find_base_class(const string&) const; const member_functions& get_virtual_mem_fns() const; const virtual_mem_fn_map_type& get_virtual_mem_fns_map() const; void sort_virtual_mem_fns(); bool has_no_base_nor_member() const; bool has_virtual_member_functions() const; bool has_virtual_bases() const; bool has_vtable() const; ssize_t get_biggest_vtable_offset() const; virtual size_t get_hash() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual bool operator==(const class_decl&) const; virtual bool traverse(ir_node_visitor& v); virtual ~class_decl(); friend void fixup_virtual_member_function(method_decl_sptr method); friend void set_member_is_static(decl_base& d, bool s); friend bool equals(const class_decl&, const class_decl&, change_kind*); friend class method_decl; friend class class_or_union; };// end class class_decl bool equals(const class_decl&, const class_decl&, change_kind*); method_decl_sptr copy_member_function(const class_decl_sptr& clazz, const method_decl_sptr& f); method_decl_sptr copy_member_function(const class_decl_sptr& clazz, const method_decl* f); void fixup_virtual_member_function(method_decl_sptr method); /// Hasher for the @ref class_decl type struct class_decl::hash { size_t operator()(const class_decl& t) const; size_t operator()(const class_decl* t) const; }; // end struct class_decl::hash enum access_specifier get_member_access_specifier(const decl_base&); enum access_specifier get_member_access_specifier(const decl_base_sptr&); void set_member_access_specifier(decl_base&, access_specifier); void set_member_access_specifier(const decl_base_sptr&, access_specifier); std::ostream& operator<<(std::ostream&, access_specifier); bool operator==(const class_decl_sptr& l, const class_decl_sptr& r); bool operator!=(const class_decl_sptr& l, const class_decl_sptr& r); bool equals(const class_decl::base_spec&, const class_decl::base_spec&, change_kind*); /// Abstraction of a base specifier in a class declaration. class class_decl::base_spec : public member_base, public virtual decl_base { struct priv; std::unique_ptr priv_; // Forbidden base_spec(); public: /// Hasher. struct hash; base_spec(const class_decl_sptr& base, access_specifier a, long offset_in_bits = -1, bool is_virtual = false); base_spec(const type_base_sptr& base, access_specifier a, long offset_in_bits = -1, bool is_virtual = false); virtual ~base_spec(); class_decl_sptr get_base_class() const; bool get_is_virtual() const; long get_offset_in_bits() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const member_base&) const; virtual size_t get_hash() const; virtual bool traverse(ir_node_visitor&); };// end class class_decl::base_spec bool operator==(const class_decl::base_spec_sptr& l, const class_decl::base_spec_sptr& r); bool operator!=(const class_decl::base_spec_sptr& l, const class_decl::base_spec_sptr& r); class_decl::base_spec* is_class_base_spec(type_or_decl_base*); class_decl::base_spec_sptr is_class_base_spec(type_or_decl_base_sptr); /// Abstracts a union type declaration. class union_decl : public class_or_union { // Forbid union_decl(); public: union_decl(const environment* env, const string& name, size_t size_in_bits, const location& locus, visibility vis, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns); union_decl(const environment* env, const string& name, size_t size_in_bits, const location& locus, visibility vis, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns, bool is_anonymous); union_decl(const environment* env, const string& name, size_t size_in_bits, const location& locus, visibility vis); union_decl(const environment* env, const string& name, size_t size_in_bits, const location& locus, visibility vis, bool is_anonymous); union_decl(const environment* env, const string& name, bool is_declaration_only = true); virtual string get_pretty_representation(bool internal = false, bool qualified_name = true) const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual bool operator==(const union_decl&) const; virtual bool traverse(ir_node_visitor& v); virtual ~union_decl(); }; // union_decl bool equals(const union_decl&, const union_decl&, change_kind*); method_decl_sptr copy_member_function(const union_decl_sptr& union_type, const method_decl_sptr& f); method_decl_sptr copy_member_function(const union_decl_sptr& union_type, const method_decl* f); bool operator==(const union_decl_sptr& l, const union_decl_sptr& r); bool operator!=(const union_decl_sptr& l, const union_decl_sptr& r); /// Abstraction of a member function context relationship. This /// relates a member function to its parent class. class mem_fn_context_rel : public context_rel { protected: bool is_virtual_; ssize_t vtable_offset_in_bits_; bool is_constructor_; bool is_destructor_; bool is_const_; public: mem_fn_context_rel() : context_rel(), is_virtual_(false), vtable_offset_in_bits_(-1), is_constructor_(false), is_destructor_(false), is_const_(false) {} mem_fn_context_rel(scope_decl* s) : context_rel(s), is_virtual_(false), vtable_offset_in_bits_(-1), is_constructor_(false), is_destructor_(false), is_const_(false) {} mem_fn_context_rel(scope_decl* s, bool is_constructor, bool is_destructor, bool is_const, bool is_virtual, size_t vtable_offset_in_bits, access_specifier access, bool is_static) : context_rel(s, access, is_static), is_virtual_(is_virtual), vtable_offset_in_bits_(vtable_offset_in_bits), is_constructor_(is_constructor), is_destructor_(is_destructor), is_const_(is_const) {} bool is_virtual() const {return is_virtual_;} void is_virtual(bool is_virtual) {is_virtual_ = is_virtual;} /// Getter for the vtable offset property. /// /// This is the vtable offset of the member function of this /// relation. /// /// @return the vtable offset property of the relation. size_t vtable_offset() const {return vtable_offset_in_bits_;} /// Setter for the vtable offset property. /// /// This is the vtable offset of the member function of this /// relation. /// /// @partam s the new vtable offset. void vtable_offset(size_t s) {vtable_offset_in_bits_ = s;} /// Getter for the 'is-constructor' property. /// /// This tells if the member function of this relation is a /// constructor. /// /// @return the is-constructor property of the relation. bool is_constructor() const {return is_constructor_;} /// Setter for the 'is-constructor' property. /// /// @param f the new value of the the property. Is true if this is /// for a constructor, false otherwise. void is_constructor(bool f) {is_constructor_ = f;} /// Getter for the 'is-destructor' property. /// /// Tells if the member function of this relation is a destructor. /// /// @return the is-destructor property of the relation; bool is_destructor() const {return is_destructor_;} /// Setter for the 'is-destructor' property. /// /// @param f the new value of the property. Is true if this is for /// a destructor, false otherwise. void is_destructor(bool f) {is_destructor_ = f;} /// Getter for the 'is-const' property. /// /// Tells if the member function of this relation is a const member /// function. /// /// @return the 'is-const' property of the relation. bool is_const() const {return is_const_;} /// Setter for the 'is-const' property. /// /// @param f the new value of the property. Is true if this is for /// a const entity, false otherwise. void is_const(bool f) {is_const_ = f;} virtual ~mem_fn_context_rel(); }; // end class mem_fn_context_rel method_decl* is_method_decl(const type_or_decl_base*); method_decl* is_method_decl(const type_or_decl_base&); method_decl_sptr is_method_decl(const type_or_decl_base_sptr&); const var_decl* lookup_data_member(const type_base* type, const char* dm_name); const function_decl::parameter* get_function_parameter(const decl_base* fun, unsigned parm_num); /// Abstract a member function template. class member_function_template : public member_base, public virtual decl_base { bool is_constructor_; bool is_const_; shared_ptr fn_tmpl_; // Forbiden member_function_template(); public: /// Hasher. struct hash; member_function_template(function_tdecl_sptr f, access_specifier access, bool is_static, bool is_constructor, bool is_const) : type_or_decl_base(f->get_environment()), decl_base(f->get_environment(), f->get_name(), location()), member_base(access, is_static), is_constructor_(is_constructor), is_const_(is_const), fn_tmpl_(f) {} bool is_constructor() const {return is_constructor_;} bool is_const() const {return is_const_;} operator const function_tdecl& () const {return *fn_tmpl_;} function_tdecl_sptr as_function_tdecl() const {return fn_tmpl_;} virtual bool operator==(const member_base& o) const; virtual bool traverse(ir_node_visitor&); };// end class member_function_template bool operator==(const member_function_template_sptr& l, const member_function_template_sptr& r); bool operator!=(const member_function_template_sptr& l, const member_function_template_sptr& r); /// Abstracts a member class template template class member_class_template : public member_base, public virtual decl_base { shared_ptr class_tmpl_; // Forbidden member_class_template(); public: /// Hasher. struct hash; member_class_template(class_tdecl_sptr c, access_specifier access, bool is_static) : type_or_decl_base(c->get_environment()), decl_base(c->get_environment(), c->get_name(), location()), member_base(access, is_static), class_tmpl_(c) {} operator const class_tdecl& () const { return *class_tmpl_; } class_tdecl_sptr as_class_tdecl() const {return class_tmpl_;} virtual bool operator==(const member_base& o) const; virtual bool operator==(const member_class_template&) const; virtual bool traverse(ir_node_visitor& v); };// end class member_class_template bool operator==(const member_class_template_sptr& l, const member_class_template_sptr& r); bool operator!=(const member_class_template_sptr& l, const member_class_template_sptr& r); // Forward declarations for select nested hashers. struct type_base::shared_ptr_hash { size_t operator()(const shared_ptr t) const; }; struct type_base::dynamic_hash { size_t operator()(const type_base* t) const; }; /// A hashing functor for instances and pointers of @ref var_decl. struct var_decl::hash { size_t operator()(const var_decl& t) const; size_t operator()(const var_decl* t) const; }; //end struct var_decl::hash /// A comparison functor for pointers to @ref var_decl. struct var_decl::ptr_equal { /// Return true if the two instances of @ref var_decl are equal. /// /// @param l the first variable to compare. /// /// @param r the second variable to compare. /// /// @return true if @p l equals @p r. bool operator()(const var_decl* l, const var_decl* r) const { if (l == r) return true; if (!!l != !!r) return false; return (*l == *r); } };// end struct var_decl::ptr_equal /// A hashing functor fo instances and pointers of @ref function_decl. struct function_decl::hash { size_t operator()(const function_decl& t) const; size_t operator()(const function_decl* t) const; };//end struct function_decl::hash /// Equality functor for instances of @ref function_decl struct function_decl::ptr_equal { /// Tests if two pointers to @ref function_decl are equal. /// /// @param l the first pointer to @ref function_decl to consider in /// the comparison. /// /// @param r the second pointer to @ref function_decl to consider in /// the comparison. /// /// @return true if the two functions @p l and @p r are equal, false /// otherwise. bool operator()(const function_decl* l, const function_decl* r) const { if (l == r) return true; if (!!l != !!r) return false; return (*l == *r); } };// function_decl::ptr_equal /// The hashing functor for class_decl::base_spec. struct class_decl::base_spec::hash { size_t operator()(const base_spec& t) const; }; /// The hashing functor for member_base. struct member_base::hash { size_t operator()(const member_base& m) const; }; /// The hashing functor for member_function_template. struct member_function_template::hash { size_t operator()(const member_function_template& t) const; }; /// The hashing functor for member_class_template struct member_class_template::hash { size_t operator()(const member_class_template& t) const; }; struct function_tdecl::hash { size_t operator()(const function_tdecl& t) const; }; struct function_tdecl::shared_ptr_hash { size_t operator()(const shared_ptr f) const; }; struct class_tdecl::hash { size_t operator()(const class_tdecl& t) const; }; struct class_tdecl::shared_ptr_hash { size_t operator()(const shared_ptr t) const; }; /// The base class for the visitor type hierarchy used for traversing /// a translation unit. /// /// Client code willing to get notified for a certain kind of node /// during the IR traversal might want to define a visitor class that /// inherit ir_node_visitor, overload the ir_node_visitor::visit_begin() /// or ir_node_visitor::visit_end() method of its choice, and provide /// and implementation for it. If either /// ir_node_visitor::visit_begin() or ir_node_visitor::visit_end() /// return false, it means the traversal has to stop immediately after /// the methods' return. If the methods return true, it means the /// traversal keeps going. /// /// That new visitor class would then be passed to e.g, /// translation_unit::traverse or to the traverse method of any type /// where the traversal is supposed to start from. class ir_node_visitor : public node_visitor_base { struct priv; std::unique_ptr priv_; public: ir_node_visitor(); virtual ~ir_node_visitor(); void allow_visiting_already_visited_type_node(bool); bool allow_visiting_already_visited_type_node() const; void mark_type_node_as_visited(type_base *); void forget_visited_type_nodes(); bool type_node_has_been_visited(type_base*) const; virtual bool visit_begin(decl_base*); virtual bool visit_end(decl_base*); virtual bool visit_begin(scope_decl*); virtual bool visit_end(scope_decl*); virtual bool visit_begin(type_base*); virtual bool visit_end(type_base*); virtual bool visit_begin(scope_type_decl*); virtual bool visit_end(scope_type_decl*); virtual bool visit_begin(type_decl*); virtual bool visit_end(type_decl*); virtual bool visit_begin(namespace_decl*); virtual bool visit_end(namespace_decl*); virtual bool visit_begin(qualified_type_def*); virtual bool visit_end(qualified_type_def*); virtual bool visit_begin(pointer_type_def*); virtual bool visit_end(pointer_type_def*); virtual bool visit_begin(reference_type_def*); virtual bool visit_end(reference_type_def*); virtual bool visit_begin(array_type_def*); virtual bool visit_end(array_type_def*); virtual bool visit_begin(array_type_def::subrange_type*); virtual bool visit_end(array_type_def::subrange_type*); virtual bool visit_begin(enum_type_decl*); virtual bool visit_end(enum_type_decl*); virtual bool visit_begin(typedef_decl*); virtual bool visit_end(typedef_decl*); virtual bool visit_begin(function_type*); virtual bool visit_end(function_type*); virtual bool visit_begin(var_decl*); virtual bool visit_end(var_decl*); virtual bool visit_begin(function_decl*); virtual bool visit_end(function_decl*); virtual bool visit_begin(function_decl::parameter*); virtual bool visit_end(function_decl::parameter*); virtual bool visit_begin(function_tdecl*); virtual bool visit_end(function_tdecl*); virtual bool visit_begin(class_tdecl*); virtual bool visit_end(class_tdecl*); virtual bool visit_begin(class_or_union *); virtual bool visit_end(class_or_union *); virtual bool visit_begin(class_decl*); virtual bool visit_end(class_decl*); virtual bool visit_begin(union_decl*); virtual bool visit_end(union_decl*); virtual bool visit_begin(class_decl::base_spec*); virtual bool visit_end(class_decl::base_spec*); virtual bool visit_begin(member_function_template*); virtual bool visit_end(member_function_template*); virtual bool visit_begin(member_class_template*); virtual bool visit_end(member_class_template*); }; // end struct ir_node_visitor // Debugging facility void fns_to_str(vector::const_iterator a_begin, vector::const_iterator a_end, vector::const_iterator b_begin, vector::const_iterator b_end, std::ostream& o); }// end namespace ir } // end namespace abigail #endif // __ABG_IR_H__