// -*- Mode: C++ -*- // // Copyright (C) 2013-2014 Red Hat, Inc. // // This file is part of the GNU Application Binary Interface Generic // Analysis and Instrumentation Library (libabigail). This library is // free software; you can redistribute it and/or modify it under the // terms of the GNU Lesser General Public License as published by the // Free Software Foundation; either version 3, or (at your option) any // later version. // This library is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Lesser Public License for more details. // You should have received a copy of the GNU Lesser General Public // License along with this program; see the file COPYING-LGPLV3. If // not, see . // // Author: Dodji Seketeli /// @file #ifndef __ABG_IR_H__ #define __ABG_IR_H__ #include #include #include "abg-fwd.h" #include "abg-hash.h" #include "abg-traverse.h" /// @file /// /// This file contains the declarations of the Internal Representation /// of libabigail. /*! @defgroup Memory Memory management considerations @{ For memory management and garbage collection of libabigail's IR artifacts, we use std::tr1::shared_ptr and std::tr1::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::get_canonical_function_type(). The type returned by that function is the one to use. 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. @} */ namespace abigail { /// @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_; location(unsigned v) : value_(v) { } public: location() : value_(0) { } unsigned get_value() const {return value_;} operator bool() const { return !!value_; } bool operator==(const location other) const {return value_ == other.value_;} bool operator<(const location other) const { return value_ < other.value_; } 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; /// Pimpl. shared_ptr priv_; public: 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; }; struct ir_node_visitor; /// Convenience typedef for a shared pointer on a @ref /// translation_unit type. typedef shared_ptr translation_unit_sptr; /// Convenience typedef for a vector of @ref translation_unit_sptr. typedef std::vector translation_units; /// Convenience typedef for a shared pointer on a @ref type_base typedef shared_ptr type_base_sptr; /// Convenience typedef for a weak pointer on a @ref type_base typedef weak_ptr type_base_wptr; /// Convenience typedef for a smart pointer on @ref decl_base. typedef shared_ptr decl_base_sptr; class function_type; class function_decl; /// Convenience typedef for a shared pointer on a @ref function_type typedef shared_ptr function_type_sptr; /// Convenience typedef for a weak pointer on a @ref function_type typedef weak_ptr function_type_wptr; struct ir_traversable_base; /// Convenience typedef for a shared pointer to @ref /// ir_traversable_base. typedef shared_ptr ir_traversable_base_sptr; /// 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 /// 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; typedef shared_ptr priv_sptr; priv_sptr priv_; // Forbidden translation_unit(); public: /// Convenience typedef for a shared pointer on a @ref global_scope. typedef shared_ptr global_scope_sptr; public: translation_unit(const std::string& path, char address_size = 0); virtual ~translation_unit(); const std::string& get_path() const; void set_path(const string&); const global_scope_sptr get_global_scope() 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 operator==(const translation_unit&) const; function_type_sptr get_canonical_function_type(function_type_sptr ftype) const; virtual bool traverse(ir_node_visitor& v); };//end class translation_unit bool operator==(translation_unit_sptr, 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; /// Convenience typedef for a map which key is a string and which /// value if the elf symbol of the same name. typedef std::tr1::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::tr1::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 }; /// Inject the elf_symbol::version here. class version; private: struct priv; shared_ptr priv_; public: elf_symbol(); elf_symbol(size_t i, const string& n, type t, binding b, bool d, const version& v); elf_symbol(const elf_symbol&); 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); binding get_binding() const; void set_binding(binding b); version& get_version() const; void set_version(const version& v); bool get_is_defined() const; void set_is_defined(bool d); bool is_public() const; bool is_function() const; bool is_variable() const; const elf_symbol* get_main_symbol() const; elf_symbol* get_main_symbol(); bool is_main_symbol() const; elf_symbol* get_next_alias() const; bool has_aliases() const; void add_alias(elf_symbol*); const string& get_id_string() const; string get_aliases_id_string(const string_elf_symbols_map_type& symtab) const; static bool get_name_and_version_from_id(const string& id, string& name, string& ver); elf_symbol& operator=(const elf_symbol& s); 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); bool string_to_elf_symbol_type(const string&, elf_symbol::type&); bool string_to_elf_symbol_binding(const string&, elf_symbol::binding&); 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; shared_ptr priv_; public: version(); version(const string& v, bool is_default); version(const version& v); 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; 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_); } virtual ~context_rel(); };// end class context_rel class class_decl; /// Convenience typedef for a shared pointer on a @ref class_decl typedef shared_ptr class_decl_sptr; /// Convenience typedef for a weak pointer on a @ref class_decl. typedef weak_ptr class_decl_wptr; /// The base type of all declarations. class decl_base : public ir_traversable_base { struct priv; typedef shared_ptr priv_sptr; protected: mutable priv_sptr priv_; bool hashing_started() const; void hashing_started(bool b) const; size_t peek_hash_value() const; const string& peek_qualified_name() const; void set_qualified_name(const string&) const; public: /// 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 }; // Forbidden decl_base(); virtual void set_scope(scope_decl*); protected: const context_rel_sptr get_context_rel() const; context_rel_sptr get_context_rel(); void set_context_rel(context_rel_sptr c); public: decl_base(const std::string& name, location locus, const std::string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); decl_base(location); decl_base(const decl_base&); virtual bool operator==(const decl_base&) const; virtual bool traverse(ir_node_visitor& v); virtual ~decl_base(); virtual size_t get_hash() const; void set_hash(size_t) const; bool get_is_in_public_symbol_table() const; void set_is_in_public_symbol_table(bool); location get_location() const; void set_location(const location& l); const string& get_name() const; virtual string get_pretty_representation() const; string get_qualified_parent_name() const; virtual void get_qualified_name(string& qualified_name) const; string get_qualified_name() const; void set_name(const string& n); const string& get_linkage_name() const; void set_linkage_name(const std::string& m); scope_decl* get_scope() const; visibility get_visibility() const; void set_visibility(visibility v); friend decl_base_sptr add_decl_to_scope(decl_base_sptr dcl, 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(const decl_base_sptr 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(decl_base_sptr d, bool s); friend bool get_member_function_is_virtual(const function_decl& f); friend void set_member_function_is_virtual(const function_decl&, bool); friend class class_decl; };// end class decl_base bool operator==(const decl_base_sptr, const decl_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); /// Convenience typedef for a shared pointer on a @ref scope_decl. typedef shared_ptr scope_decl_sptr; /// A declaration that introduces a scope. class scope_decl : public virtual decl_base { public: /// Convenience typedef for a vector of @ref decl_base_sptr. typedef std::vector declarations; /// Convenience typedef for a vector of @ref scope_decl_sptr. typedef std::vector scopes; private: declarations members_; scopes member_scopes_; scope_decl(); protected: virtual decl_base_sptr add_member_decl(const decl_base_sptr member); virtual decl_base_sptr insert_member_decl(const decl_base_sptr member, declarations::iterator before); virtual void remove_member_decl(const decl_base_sptr member); public: struct hash; scope_decl(const std::string& name, location locus, visibility vis = VISIBILITY_DEFAULT) : decl_base(name, locus, /*mangled_name=*/name, vis) {} scope_decl(location l) : decl_base("", l) {} virtual size_t get_hash() const; virtual bool operator==(const decl_base&) const; const declarations& get_member_decls() const {return members_;} declarations& get_member_decls() {return members_;} scopes& get_member_scopes() {return member_scopes_;} bool is_empty() const {return get_member_decls().empty();} 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 dcl, scope_decl* scpe); 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); };//end class scope_decl /// 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; }; /// Convenience typedef for shared pointer on @ref global_scope. typedef shared_ptr global_scope_sptr; /// 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) : decl_base("", location()), scope_decl("", location()), translation_unit_(tu) {} public: friend class translation_unit; translation_unit* get_translation_unit() const {return translation_unit_;} virtual ~global_scope(); }; /// An abstraction helper for type declarations class type_base { size_t size_in_bits_; size_t alignment_in_bits_; // Forbid this. type_base(); 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; struct cached_hash; type_base(size_t s, size_t a); virtual bool operator==(const type_base&) const; virtual ~type_base(); void set_size_in_bits(size_t); virtual size_t get_size_in_bits() const; void set_alignment_in_bits(size_t); virtual size_t get_alignment_in_bits() const; };//end class type_base /// 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; } }; /// Convenience typedef for a shared pointer on a @ref type_decl. typedef shared_ptr type_decl_sptr; /// 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 std::string& name, size_t size_in_bits, size_t alignment_in_bits, location locus, const std::string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT); static type_decl_sptr get_void_type_decl(); virtual bool operator==(const type_base&) const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_decl&) const; virtual string get_pretty_representation() const; virtual bool traverse(ir_node_visitor&); virtual ~type_decl(); };// end class type_decl. /// 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 std::string& name, size_t size_in_bits, size_t alignment_in_bits, location locus, visibility vis = VISIBILITY_DEFAULT); virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual ~scope_type_decl(); }; /// Convenience typedef for a shared pointer on namespace_decl. typedef shared_ptr namespace_decl_sptr; /// The abstraction of a namespace declaration class namespace_decl : public scope_decl { public: namespace_decl(const std::string& name, location locus, visibility vis = VISIBILITY_DEFAULT); virtual bool operator==(const decl_base&) const; virtual bool traverse(ir_node_visitor&); virtual ~namespace_decl(); };// end class namespace_decl typedef shared_ptr qualified_type_def_sptr; /// The abstraction of a qualified type. class qualified_type_def : public virtual type_base, public virtual decl_base { char cv_quals_; weak_ptr underlying_type_; // Forbidden. qualified_type_def(); protected: string build_name(bool) const; 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(shared_ptr type, CV quals, location locus); virtual size_t get_size_in_bits() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; char get_cv_quals() const; void set_cv_quals(char cv_quals); string get_cv_quals_string_prefix() const; shared_ptr get_underlying_type() const; virtual void get_qualified_name(string& qualified_name) const; virtual bool traverse(ir_node_visitor& v); virtual ~qualified_type_def(); }; // end class qualified_type_def. qualified_type_def::CV operator|(qualified_type_def::CV, qualified_type_def::CV); std::ostream& operator<<(std::ostream&, qualified_type_def::CV); /// Convenience typedef for a shared pointer on a @ref pointer_type_def typedef shared_ptr pointer_type_def_sptr; /// The abstraction of a pointer type. class pointer_type_def : public virtual type_base, public virtual decl_base { type_base_wptr pointed_to_type_; // Forbidden. pointer_type_def(); public: /// A hasher for instances of pointer_type_def struct hash; pointer_type_def(shared_ptr& pointed_to_type, size_t size_in_bits, size_t alignment_in_bits, location locus); virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; const type_base_sptr get_pointed_to_type() const; virtual void get_qualified_name(string&) const; virtual bool traverse(ir_node_visitor& v); virtual ~pointer_type_def(); }; // end class pointer_type_def /// Convenience typedef for a shared pointer on a @ref reference_type_def typedef shared_ptr reference_type_def_sptr; /// 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(); 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, location locus); virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; shared_ptr get_pointed_to_type() const; bool is_lvalue() const; virtual void get_qualified_name(string& qualified_name) const; virtual bool traverse(ir_node_visitor& v); virtual ~reference_type_def(); }; // end class reference_type_def /// Convenience typedef for a shared pointer on a @ref array_type_def typedef shared_ptr array_type_def_sptr; /// The abstraction of an array type. class array_type_def : public virtual type_base, public virtual decl_base { private: struct priv; typedef shared_ptr priv_sptr; priv_sptr priv_; // Forbidden. array_type_def(); 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; /// Abtraction for an array dimension class subrange_type { struct priv; typedef shared_ptr priv_sptr; priv_sptr priv_; // Forbidden. subrange_type(); public: /// Hasher for an instance of array::subrange struct hash; subrange_type(size_t lower_bound, size_t upper_bound, location loc); subrange_type(size_t upper_bound, location loc); size_t get_upper_bound() const; size_t get_lower_bound() const; void set_upper_bound(size_t ub); void set_lower_bound(size_t lb); size_t get_length() const; bool is_infinite() const; bool operator==(const subrange_type& o) const; location get_location() const; }; array_type_def(const type_base_sptr type, const std::vector& subs, location locus); virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; virtual void get_qualified_name(string& qualified_name) const; virtual string get_qualified_name() const; const type_base_sptr get_element_type() const; virtual void append_subrange(subrange_sptr sub); virtual void append_subranges(const std::vector& subs); virtual int get_dimension_count() const; virtual bool is_infinite() const; virtual string get_pretty_representation() const; virtual string get_subrange_representation() const; virtual bool traverse(ir_node_visitor& v); location get_location() const; const std::vector& get_subranges() const; virtual ~array_type_def(); }; // end class array_type_def /// Convenience typedef for shared pointer on enum_type_decl. typedef shared_ptr enum_type_decl_sptr; /// Abstracts a declaration for an enum type. class enum_type_decl : public virtual type_base, public virtual decl_base { public: /// A hasher for an enum_type_decl. struct hash; /// Enumerator Datum. class enumerator { string name_; size_t value_; public: enumerator() : value_(0) {} enumerator(const string& name, size_t value) : name_(name), value_(value) { } bool operator==(const enumerator& other) const { return (get_name() == other.get_name() && get_value() == other.get_value()); } const string& get_name() const {return name_;} const string get_qualified_name(const enum_type_decl_sptr enum_type) const {return enum_type->get_qualified_name() + "::" + get_name();} void set_name(const string& n) {name_ = n;} size_t get_value() const {return value_;} void set_value(size_t v) {value_=v;} }; /// Convenience typedef for a list of @ref enumerator. typedef std::vector enumerators; private: type_base_sptr underlying_type_; enumerators enumerators_; // Forbidden enum_type_decl(); public: /// 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, location locus, type_base_sptr underlying_type, enumerators& enms, const std::string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT) : type_base(underlying_type->get_size_in_bits(), underlying_type->get_alignment_in_bits()), decl_base(name, locus, mangled_name, vis), underlying_type_(underlying_type), enumerators_(enms) {} type_base_sptr get_underlying_type() const; const enumerators& get_enumerators() const; virtual string get_pretty_representation() 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(); }; // end class enum_type_decl /// Convenience typedef for a shared pointer on a @ref typedef_decl. typedef shared_ptr typedef_decl_sptr; /// The abstraction of a typedef declaration. class typedef_decl : public virtual type_base, public virtual decl_base { type_base_wptr underlying_type_; // Forbidden typedef_decl(); public: /// Hasher for the typedef_decl type. struct hash; typedef_decl(const string& name, const shared_ptr underlying_type, location locus, const std::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() const; shared_ptr get_underlying_type() const; virtual bool traverse(ir_node_visitor&); virtual ~typedef_decl(); };// end class typedef_decl class dm_context_rel; /// A convenience typedef for a shared pointer to dm_context_rel. typedef shared_ptr dm_context_rel_sptr; /// 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: bool is_laid_out_; size_t offset_in_bits_; public: dm_context_rel() : context_rel(), is_laid_out_(!is_static_), offset_in_bits_(0) {} dm_context_rel(scope_decl* s, bool is_laid_out, size_t offset_in_bits, access_specifier a, bool is_static) : context_rel(s, a, is_static), is_laid_out_(is_laid_out), offset_in_bits_(offset_in_bits) {} dm_context_rel(scope_decl* s) : context_rel(s), is_laid_out_(!is_static_), offset_in_bits_(0) {} bool get_is_laid_out() const {return is_laid_out_;} void set_is_laid_out(bool f) {is_laid_out_ = f;} size_t get_offset_in_bits() const {return offset_in_bits_;} void set_offset_in_bits(size_t o) {offset_in_bits_ = o;} bool operator==(const dm_context_rel& o) { if (!context_rel::operator==(o)) return false; return (is_laid_out_ == o.is_laid_out_ && offset_in_bits_ == o.offset_in_bits_); } virtual ~dm_context_rel(); };// end class class_decl::dm_context_rel /// Convenience typedef for a shared pointer on a @ref var_decl typedef shared_ptr var_decl_sptr; /// Abstracts a variable declaration. class var_decl : public virtual decl_base { struct priv; shared_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 std::string& name, shared_ptr type, location locus, const std::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; binding get_binding() const; void set_binding(binding b); void set_symbol(elf_symbol_sptr sym); elf_symbol_sptr get_symbol() const; var_decl_sptr clone() const; string get_id() const; virtual size_t get_hash() const; virtual string get_pretty_representation() const; virtual bool traverse(ir_node_visitor& v); virtual ~var_decl(); friend void set_data_member_offset(var_decl_sptr m, size_t o); friend size_t get_data_member_offset(const var_decl_sptr m); friend size_t get_data_member_offset(const var_decl& 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 /// Convenience typedef for a shared pointer on a @ref function_decl typedef shared_ptr function_decl_sptr; /// Abstraction for a function declaration. class function_decl : public virtual decl_base { struct priv; shared_ptr priv_; public: /// Hasher for function_decl struct hash; /// Equality functor to compare pointers to function_decl struct ptr_equal; 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; /// Abtraction for the parameter of a function. class parameter { type_base_wptr type_; unsigned index_; bool variadic_marker_; std::string name_; location location_; bool artificial_; public: /// Hasher for an instance of function::parameter struct hash; parameter(const shared_ptr type, unsigned index, const std::string& name, location loc, bool variadic_marker = false) : type_(type), index_(index), variadic_marker_ (variadic_marker), name_(name), location_(loc), artificial_(false) {} parameter(const shared_ptr type, const std::string& name, location loc, bool variadic_marker = false, bool is_artificial = false) : type_(type), index_(0), variadic_marker_ (variadic_marker), name_(name), location_(loc), artificial_(is_artificial) {} parameter(const shared_ptr type, unsigned index = 0, bool variadic_marker = false) : type_(type), index_(index), variadic_marker_ (variadic_marker), artificial_(false) {} const type_base_sptr get_type()const { if (type_.expired()) return type_base_sptr(); return type_base_sptr(type_); } /// @return a copy of the type name of the parameter. const string get_type_name() const { string str; if (variadic_marker_) str = "..."; else { type_base_sptr t = get_type(); assert(t); str += abigail::get_type_name(t); } return str; } /// @return a copy of the pretty representation of the type of the /// parameter. const string get_type_pretty_representation() const { string str; if (variadic_marker_) str = "..."; else { type_base_sptr t = get_type(); assert(t); str += get_type_declaration(t)->get_pretty_representation(); } return str; } const string get_name_id() const; unsigned get_index() const {return index_;} void set_index(unsigned i) {index_ = i;} const std::string& get_name() const {return name_;} location get_location() const {return location_;} /// Test if the parameter is artificial. /// /// Being artificial means the parameter was not explicitely /// mentionned in the source code, but was rather artificially /// created by the compiler. /// /// @return true if the parameter is artificial, false otherwise. bool get_artificial() const {return artificial_;} /// Getter for the artificial-ness of the parameter. /// /// Being artificial means the parameter was not explicitely /// mentionned in the source code, but was rather artificially /// created by the compiler. /// /// @param f set to true if the parameter is artificial. void set_artificial(bool f) {artificial_ = f;} bool operator==(const parameter& o) const { if ((get_variadic_marker() != o.get_variadic_marker()) || (get_index() != o.get_index()) || (!!get_type() != !!o.get_type()) || (get_type() && (*get_type() != *o.get_type()))) return false; return true; } bool get_variadic_marker() const {return variadic_marker_;} }; function_decl(const std::string& name, function_type_sptr function_type, bool declared_inline, location locus, const std::string& mangled_name, visibility vis, binding bind); function_decl(const std::string& name, shared_ptr fn_type, bool declared_inline, location locus, const std::string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_GLOBAL); virtual string get_pretty_representation() 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 shared_ptr get_type() const; const shared_ptr get_return_type() const; void set_type(shared_ptr fn_type); void set_symbol(elf_symbol_sptr sym); 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; string get_id() const; virtual bool traverse(ir_node_visitor&); virtual ~function_decl(); }; // end class function_decl /// Abstraction of a function type. class function_type : public virtual type_base { 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; private: function_type(); type_base_wptr return_type_; protected: parameters parms_; public: /// The most straightforward constructor for the the function_type /// class. /// /// @param return_type the return type of the function type. /// /// @param parms the list of parameters of the function type. /// Stricto sensu, we just need a list of types; we are using a list /// of parameters (where each parameter also carries the name of the /// parameter and its source location) to try and provide better /// diagnostics whenever it makes sense. If it appears that this /// wasts too many resources, we can fall back to taking just a /// vector of types here. /// /// @param size_in_bits the size of this type, in bits. /// /// @param alignment_in_bits the alignment of this type, in bits. /// /// @param size_in_bits the size of this type. function_type(shared_ptr return_type, const parameters& parms, size_t size_in_bits, size_t alignment_in_bits) : type_base(size_in_bits, alignment_in_bits), return_type_(return_type), parms_(parms) { for (parameters::size_type i = 0; i != parms_.size(); ++i) parms_[i]->set_index(i); } /// A constructor for a function_type that takes no parameters. /// /// @param return_type the return type of this function_type. /// /// @param size_in_bits the size of this type, in bits. /// /// @param alignment_in_bits the alignment of this type, in bits. function_type(shared_ptr return_type, size_t size_in_bits, size_t alignment_in_bits) : type_base(size_in_bits, alignment_in_bits), return_type_(return_type) {} /// A constructor for a function_type that takes no parameter and /// that has no return_type yet. These missing parts can (and must) /// be added later. /// /// @param size_in_bits the size of this type, in bits. /// /// @param alignment_in_bits the alignment of this type, in bits. function_type(size_t size_in_bits, size_t alignment_in_bits) : type_base(size_in_bits, alignment_in_bits) {} type_base_sptr get_return_type() const { if (return_type_.expired()) return type_base_sptr(); return type_base_sptr(return_type_); } void set_return_type(type_base_sptr t) {return_type_ = t;} const parameters& get_parameters() const {return parms_;} parameters& get_parameters() {return parms_;} void set_parameters(const parameters &p) {parms_ = p;} void append_parameter(parameter_sptr parm) { parm->set_index(parms_.size()); parms_.push_back(parm); } bool is_variadic() const {return !parms_.empty() && parms_.back()->get_variadic_marker();} parameters::const_iterator get_first_non_implicit_parm() const; virtual bool operator==(const type_base&) const; virtual ~function_type(); };//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 /// Convenience typedef for shared pointer to @ref method_type. typedef shared_ptr method_type_sptr; /// Abstracts the type of a class member function. class method_type : public function_type { class_decl_wptr class_type_; method_type(); public: /// Hasher for intances of method_type struct hash; method_type(shared_ptr return_type, shared_ptr class_type, const std::vector >& parms, size_t size_in_bits, size_t alignment_in_bits); method_type(shared_ptr return_type, shared_ptr class_type, const std::vector >& parms, size_t size_in_bits, size_t alignment_in_bits); method_type(shared_ptr class_type, size_t size_in_bits, size_t alignment_in_bits); method_type(size_t size_in_bits, size_t alignment_in_bits); class_decl_sptr get_class_type() const {return class_decl_sptr(class_type_);} void set_class_type(shared_ptr t); virtual ~method_type(); };// end class method_type. /// The base class of templates. class template_decl { // XXX std::list > parms_; public: /// Hasher. struct hash; template_decl() {} void add_template_parameter(shared_ptr p) {parms_.push_back(p);} const std::list >& get_template_parameters() const {return parms_;} 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 { unsigned index_; // Forbidden template_parameter(); public: /// Hashers. struct hash; struct dynamic_hash; struct shared_ptr_hash; template_parameter(unsigned index) : index_(index) {} virtual bool operator==(const template_parameter&) const; unsigned get_index() const {return index_;} virtual ~template_parameter(); };//end class template_parameter /// Abstracts a type template parameter. class type_tparameter : public template_parameter, public virtual type_decl { // Forbidden type_tparameter(); public: /// Hasher. struct hash; type_tparameter(unsigned index, const std::string& name, location locus) : decl_base(name, locus), type_base(0, 0), type_decl(name, 0, 0, locus), template_parameter(index) {} 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 { type_base_wptr type_; // Forbidden non_type_tparameter(); public: /// Hasher. struct hash; non_type_tparameter(unsigned index, const std::string& name, shared_ptr type, location locus) : decl_base(name, locus, ""), template_parameter(index), type_(type) {} virtual size_t get_hash() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const template_parameter&) const; type_base_sptr get_type() const { if (type_.expired()) return type_base_sptr(); return type_base_sptr(type_); } 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; }; /// Abstracts a template template parameter. class template_tparameter : public type_tparameter, public template_decl { // Forbidden template_tparameter(); public: /// A hasher for instances of template_tparameter struct hash; template_tparameter(unsigned index, const std::string& name, location locus) : decl_base(name, locus), type_base(0, 0), type_decl(name, 0, 0, locus, name, VISIBILITY_DEFAULT), type_tparameter(index, name, 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 { type_base_wptr type_; type_composition(); public: struct hash; type_composition(unsigned index, shared_ptr composed_type); type_base_sptr get_composed_type() const { if (type_.expired()) return type_base_sptr(); return type_base_sptr(type_); } void set_composed_type(type_base_sptr t) {type_ = 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 /// Convenience typedef for a shared pointer on a @ref function_tdecl typedef shared_ptr function_tdecl_sptr; /// Abstract a function template declaration. class function_tdecl : public template_decl, public scope_decl { shared_ptr pattern_; binding binding_; // Forbidden function_tdecl(); public: /// Hash functor for function templates. struct hash; struct shared_ptr_hash; function_tdecl(location locus, visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_NONE) : decl_base("", locus, "", vis), scope_decl("", locus), binding_(bind) {} function_tdecl(shared_ptr pattern, location locus, visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_NONE) : decl_base(pattern->get_name(), locus, pattern->get_name(), vis), scope_decl(pattern->get_name(), locus), binding_(bind) {set_pattern(pattern);} virtual bool operator==(const decl_base&) const; virtual bool operator==(const template_decl&) const; void set_pattern(shared_ptr p) { pattern_ = p; add_decl_to_scope(p, this); set_name(p->get_name()); } shared_ptr get_pattern() const {return pattern_;} binding get_binding() const {return binding_;} virtual bool traverse(ir_node_visitor& v); virtual ~function_tdecl(); }; // end class function_tdecl. /// Convenience typedef for a shared pointer on a @ref class_tdecl typedef shared_ptr class_tdecl_sptr; /// Abstract a class template. class class_tdecl : public template_decl, public scope_decl { shared_ptr pattern_; // Forbidden class_tdecl(); public: /// Hashers. struct hash; struct shared_ptr_hash; class_tdecl(location locus, visibility vis = VISIBILITY_DEFAULT) : decl_base("", locus, "", vis), scope_decl("", locus) {} class_tdecl(shared_ptr pattern, 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(shared_ptr p); shared_ptr get_pattern() const {return pattern_;} virtual bool traverse(ir_node_visitor& v); virtual ~class_tdecl(); };// end class class_tdecl /// Abstracts a class declaration. class class_decl : public scope_type_decl { // Forbidden class_decl(); public: /// Hasher. struct hash; /// Forward declarations. class member_base; class base_spec; class method_decl; class member_function_template; class member_class_template; /// Convenience typedef /// @{ typedef shared_ptr base_spec_sptr; typedef std::vector base_specs; typedef std::vector member_types; typedef std::vector data_members; typedef shared_ptr method_decl_sptr; typedef std::vector member_functions; typedef shared_ptr member_function_template_sptr; typedef std::vector member_function_templates; typedef shared_ptr member_class_template_sptr; typedef std::vector member_class_templates; /// @} private: struct priv; typedef shared_ptr priv_sptr; priv_sptr priv_; protected: virtual decl_base_sptr add_member_decl(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); public: class_decl(const std::string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, location locus, visibility vis, base_specs& bases, member_types& mbrs, data_members& data_mbrs, member_functions& member_fns); class_decl(const std::string& name, size_t size_in_bits, size_t align_in_bits, bool is_struct, location locus, visibility vis); class_decl(const std::string& name, bool is_struct, bool is_declaration_only = true); virtual string get_pretty_representation() const; bool get_is_declaration_only() const; void set_is_declaration_only(bool f); bool is_struct() const; void set_definition_of_declaration(class_decl_sptr); const class_decl_sptr& get_definition_of_declaration() const; void set_earlier_declaration(decl_base_sptr declaration); decl_base_sptr get_earlier_declaration() const; void add_base_specifier(shared_ptr b); const base_specs& get_base_specifiers() const; 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; 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; 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 member_functions& get_virtual_mem_fns() const; void sort_virtual_mem_fns(); void add_member_function_template(shared_ptr); const member_function_templates& get_member_function_templates() const; void add_member_class_template(shared_ptr m); const member_class_templates& get_member_class_templates() const; bool has_no_base_nor_member() const; virtual size_t get_hash() const; virtual bool operator==(const decl_base&) const; virtual bool operator==(const type_base&) const; bool operator==(const class_decl&) const; virtual bool traverse(ir_node_visitor& v); virtual ~class_decl(); };// end class class_decl /// 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_sptr, access_specifier); std::ostream& operator<<(std::ostream&, access_specifier); bool operator==(class_decl_sptr l, class_decl_sptr r); /// 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 class_decl::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 class_decl::member_base /// Abstraction of a base specifier in a class declaration. class class_decl::base_spec : public member_base, public virtual decl_base { shared_ptr base_class_; long offset_in_bits_; bool is_virtual_; // Forbidden base_spec(); public: /// Hasher. struct hash; base_spec(shared_ptr base, access_specifier a, long offset_in_bits = -1, bool is_virtual = false); base_spec(shared_ptr base, access_specifier a, long offset_in_bits = -1, bool is_virtual = false); const shared_ptr& get_base_class() const {return base_class_;} bool get_is_virtual() const {return is_virtual_;} long get_offset_in_bits() const {return offset_in_bits_;} virtual bool operator==(const member_base&) const; virtual size_t get_hash() const; };// end class class_decl::base_spec bool operator==(class_decl::base_spec_sptr l, class_decl::base_spec_sptr r); class mem_fn_context_rel; /// A convenience typedef for a shared pointer to @ref /// mem_fn_context_rel. typedef shared_ptr mem_fn_context_rel_sptr; /// 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_; size_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_(0), 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_(0), 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 /// Abstraction of the declaration of a method. This is an /// implementation detail for class_decl::member_function. class class_decl::method_decl : public function_decl { method_decl(); virtual void set_scope(scope_decl*); public: method_decl(const std::string& name, shared_ptr type, bool declared_inline, location locus, const std::string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_GLOBAL); method_decl(const std::string& name, shared_ptr type, bool declared_inline, location locus, const std::string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_GLOBAL); method_decl(const std::string& name, shared_ptr type, bool declared_inline, location locus, const std::string& mangled_name = "", visibility vis = VISIBILITY_DEFAULT, binding bind = BINDING_GLOBAL); /// @return the type of the current instance of the /// class_decl::method_decl. const shared_ptr get_type() const; void set_type(shared_ptr 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(const function_decl&, bool); friend bool get_member_function_is_dtor(const function_decl&); friend void set_member_function_is_dtor(const function_decl&, 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(const function_decl&, bool); friend size_t get_member_function_vtable_offset(const function_decl&); friend void set_member_function_vtable_offset(const function_decl&, size_t); friend bool get_member_function_is_virtual(const function_decl&); friend void set_member_function_is_virtual(const function_decl&, bool); virtual ~method_decl(); };// end class class_decl::method_decl /// Abstract a member function template. class class_decl::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) : decl_base(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 class_decl::member_function_template bool operator==(class_decl::member_function_template_sptr l, class_decl::member_function_template_sptr r); /// Abstracts a member class template template class class_decl::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(shared_ptr c, access_specifier access, bool is_static) : decl_base(c->get_name(), location()), member_base(access, is_static), class_tmpl_(c) {} operator const class_tdecl& () const { return *class_tmpl_; } shared_ptr 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 class_decl::member_class_template bool operator==(class_decl::member_class_template_sptr l, class_decl::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 hasher that manages to cache the computed hash and re-use it if /// it is available. struct type_base::cached_hash { size_t operator() (const type_base* t) const; size_t operator() (const type_base_sptr 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 class_decl::member_base. struct class_decl::member_base::hash { size_t operator()(const member_base& m) const; }; /// The hashing functor for class_decl::member_function_template. struct class_decl::member_function_template::hash { size_t operator()(const member_function_template& t) const; }; /// The hashing functor for class_decl::member_class_template struct class_decl::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 /// method of its choice, and provide and implementation for it. 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. struct ir_node_visitor : public node_visitor_base { virtual bool visit(scope_decl*); virtual bool visit(type_decl*); virtual bool visit(namespace_decl*); virtual bool visit(qualified_type_def*); virtual bool visit(pointer_type_def*); virtual bool visit(reference_type_def*); virtual bool visit(array_type_def*); virtual bool visit(enum_type_decl*); virtual bool visit(typedef_decl*); virtual bool visit(var_decl*); virtual bool visit(function_decl*); virtual bool visit(function_tdecl*); virtual bool visit(class_tdecl*); virtual bool visit(class_decl*); virtual bool visit(class_decl::member_function_template*); virtual bool visit(class_decl::member_class_template*); }; // 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 abigail #endif // __ABG_IR_H__