mirror of
git://sourceware.org/git/libabigail.git
synced 2024-12-18 16:04:34 +00:00
2cf9a18e8c
This is a follow-up patch for the commit:
43d56de
Handle several member anonymous types of the same kind
It allows support for severan anonymous types even when these are not
members of a class/unions.
The patch introduces the concept of a scoped name. It's a qualified
name for a decl made of the name of the decl appended to the
*unqualified* name of its scope. Unlike for qualified names, the
scoped name won't have a "__anonymous_*__" string in its name if its
directly containing scope is not anonymous; a qualified name might
still have that string in its name because the decl has a parent scope
(not necessarily its directly containing scope though) that is
anonymous.
The patch goes on to update the logic for comparison of decls that are
anonymous. For a decl which direct scope is *NOT* anonymous, the
scoped name is what's used in the comparison. Otherwise, only the
name of the decl is used.
The patch also updates how we detect changes in data members and
member types, in the comparison engine. It now uses the names of the
data members, rather than their qualified name. This is in the scope
of the current class/union anyway. The improvement is that the fact
that the class/union itself is anonymous (even if its anonymous name
changes to another anonymous name) won't have any spurious impact on
the detection of name change of the members.
The patch considers the change of an anonymous decl name which
anonymous name changes to another anonymous name as being harmless.
The patch updates the logic of category propagation in the comparison
engine. Although a public typedef to private underlying type needs to
stay public and thus not propagate the PRIVATE_TYPE_CATEGORY from its
child diff node to himself, it still needs to suppress the changes to
the private underlying diff node that were suppressed (because of the
private-ness), unless that typedef has local changes.
* include/abg-ir.h (decl_base::get_scoped_name): Declare new
member function.
(scope_decl::get_num_anonymous_member_{classes, unions, enums}):
Declare new virtual member functions.
(class_decl::get_num_anonymous_member_{classes, unions, enums}):
Adjust to make these virtual. It's not necessary but I feel
redundancy is a kind of self-documentation here.
* src/abg-comp-filter.cc (has_harmless_name_change): Consider
anonymous name changes as harmless.
* src/abg-comparison.cc
(class_or_union_diff::ensure_lookup_tables_populated): Consider
the names of the members rather than their qualified names.
(suppression_categorization_visitor::visit_end): Suppress the
changes to the private underlying diff node that were suppressed
because of the private-ness, unless that typedef has local
changes.
* src/abg-dwarf-reader.cc (build_enum_type)
(add_or_update_class_type, add_or_update_union_type): Handle
anonymous types in namespaces as well, not just in class/unions.
* src/abg-ir.cc (decl_base::priv::scoped_name_): Define new data
member.
(decl_base::get_scoped_name): Define new member function.
(equals): For the decl_base overload, use scoped name in the
comparison, unless the decl belongs to an anonymous type. For the
class_or_union_diff, only consider scoped_name during comparison.
Avoid name comparison between anonymous types.
(scope_decl::get_num_anonymous_member_{classes, unions, enums}):
Define new member functions.
(types_have_similar_structure): Do not compare names between
anonymous types.
(qualified_name_setter::do_update): Update scoped names too.
* tests/data/test-abidiff/test-PR18791-report0.txt: Adjust.
* tests/data/test-annotate/libtest23.so.abi: Likewise.
* tests/data/test-annotate/test13-pr18894.so.abi: Likewise.
* tests/data/test-annotate/test14-pr18893.so.abi: Likewise.
* tests/data/test-annotate/test15-pr18892.so.abi: Likewise.
* tests/data/test-annotate/test21-pr19092.so.abi: Likewise.
* tests/data/test-diff-dwarf/test43-PR22913-report-0.txt:
Likewise.
* tests/data/test-diff-dwarf/test46-rust-report-0.txt: Likewise.
* tests/data/test-diff-filter/test30-pr18904-rvalueref-report0.txt:
Likewise.
* tests/data/test-diff-filter/test30-pr18904-rvalueref-report1.txt:
Likewise.
* tests/data/test-diff-filter/test30-pr18904-rvalueref-report2.txt:
Likewise.
* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-0.txt:
Likewise.
* tests/data/test-diff-filter/test31-pr18535-libstdc++-report-1.txt:
Likewise.
* tests/data/test-diff-filter/test33-report-0.txt: Likewise.
* tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt:
Likewise.
* tests/data/test-diff-filter/test44-anonymous-data-member-report-0.txt:
Likewise.
* tests/data/test-diff-pkg/libsigc++-2.0-0c2a_2.4.0-1_amd64--libsigc++-2.0-0v5_2.4.1-1ubuntu2_amd64-report-0.txt:
Likewise.
* tests/data/test-diff-pkg/nss-3.23.0-1.0.fc23.x86_64-report-0.txt:
Likewise.
* tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-0.txt:
Likewise.
* tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-1.txt:
Likewise.
* tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-2.txt:
Likewise.
* tests/data/test-diff-pkg/spice-server-0.12.4-19.el7.x86_64-0.12.8-1.el7.x86_64-report-3.txt:
Likewise.
* tests/data/test-read-dwarf/PR22015-libboost_iostreams.so.abi:
Likewise.
* tests/data/test-read-dwarf/PR22122-libftdc.so.abi: Likewise.
* tests/data/test-read-dwarf/libtest23.so.abi: Likewise.
* tests/data/test-read-dwarf/test10-pr18818-gcc.so.abi: Likewise.
* tests/data/test-read-dwarf/test11-pr18828.so.abi: Likewise.
* tests/data/test-read-dwarf/test12-pr18844.so.abi: Likewise.
* tests/data/test-read-dwarf/test13-pr18894.so.abi: Likewise.
* tests/data/test-read-dwarf/test14-pr18893.so.abi: Likewise.
* tests/data/test-read-dwarf/test15-pr18892.so.abi: Likewise.
* tests/data/test-read-dwarf/test16-pr18904.so.abi: Likewise.
* tests/data/test-read-dwarf/test21-pr19092.so.abi: Likewise.
* tests/data/test-read-dwarf/test22-pr19097-libstdc++.so.6.0.17.so.abi:
Likewise.
* tests/data/test-read-dwarf/test9-pr18818-clang.so.abi: Likewise.
Signed-off-by: Dodji Seketeli <dodji@redhat.com>
4554 lines
102 KiB
C++
4554 lines
102 KiB
C++
// -*- Mode: C++ -*-
|
|
//
|
|
// Copyright (C) 2013-2019 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 <http://www.gnu.org/licenses/>.
|
|
//
|
|
// 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 <assert.h>
|
|
#include <stdint.h>
|
|
#include <cstdlib>
|
|
#include <tr1/unordered_map>
|
|
#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
|
|
/// @{
|
|
///
|
|
/// How objects' lifetime is handled in libabigail.
|
|
///
|
|
/// 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.
|
|
///
|
|
/// <b>The declaration for a type is owned by only one scope </b>
|
|
///
|
|
/// 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().
|
|
///
|
|
/// <b> A declaration that has a type does NOT own the type </b>
|
|
///
|
|
/// 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::tr1 types in here.
|
|
using std::tr1::unordered_map;
|
|
|
|
/// A convenience typedef fo r an ordered set of size_t.
|
|
typedef unordered_set<size_t> pointer_set;
|
|
|
|
/// 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:
|
|
|
|
/// 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::tr1::unordered_map<string,
|
|
std::vector<type_base_sptr> > canonical_types_map_type;
|
|
|
|
private:
|
|
struct priv;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr priv_;
|
|
public:
|
|
|
|
environment();
|
|
virtual ~environment();
|
|
|
|
canonical_types_map_type&
|
|
get_canonical_types_map();
|
|
|
|
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;
|
|
|
|
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_;
|
|
|
|
location(unsigned v, location_manager* m)
|
|
: value_(v), loc_manager_(m)
|
|
{}
|
|
|
|
/// 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:
|
|
|
|
/// Copy constructor of the location.
|
|
///
|
|
/// @param l the location to copy from.
|
|
location(const location& l)
|
|
: value_(l.value_),
|
|
loc_manager_(l.loc_manager_)
|
|
{}
|
|
|
|
/// 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_;
|
|
return *this;
|
|
}
|
|
|
|
/// Default constructor for the @ref location type.
|
|
location()
|
|
: value_(), loc_manager_()
|
|
{}
|
|
|
|
/// 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;
|
|
|
|
/// Pimpl.
|
|
shared_ptr<priv> 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;
|
|
};
|
|
|
|
/// 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::tr1::hash<string> 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<type_or_decl_base_sptr,
|
|
type_or_decl_hash,
|
|
type_or_decl_equal> artifact_sptr_set_type;
|
|
|
|
/// A convenience typedef for a hash set of const type_or_decl_base*
|
|
typedef unordered_set<const type_or_decl_base*,
|
|
type_or_decl_hash,
|
|
type_or_decl_equal> 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> 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<interned_string, type_base_wptr, hash_interned_string>
|
|
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<interned_string,
|
|
type_or_decl_base_sptr,
|
|
hash_interned_string>
|
|
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.
|
|
class type_maps
|
|
{
|
|
struct priv;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
priv_sptr priv_;
|
|
|
|
public:
|
|
|
|
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;
|
|
}; // 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr priv_;
|
|
|
|
// Forbidden
|
|
translation_unit();
|
|
|
|
public:
|
|
/// Convenience typedef for a shared pointer on a @ref global_scope.
|
|
typedef shared_ptr<scope_decl> 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_PL1,
|
|
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<function_type_sptr>&
|
|
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
|
|
|
|
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> elf_symbol_sptr;
|
|
|
|
/// A convenience typedef for a weak pointer to elf_symbol.
|
|
typedef weak_ptr<elf_symbol> 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::tr1::unordered_map<string, elf_symbol_sptr>
|
|
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_type>
|
|
string_elf_symbol_sptr_map_sptr;
|
|
|
|
/// Convenience typedef for a vector of elf_symbol
|
|
typedef std::vector<elf_symbol_sptr> 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>
|
|
string_elf_symbols_map_type;
|
|
|
|
/// Convenience typedef for a shared pointer to
|
|
/// string_elf_symbols_map_type.
|
|
typedef shared_ptr<string_elf_symbols_map_type> 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;
|
|
shared_ptr<priv> 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);
|
|
|
|
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);
|
|
|
|
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;
|
|
|
|
const elf_symbol_sptr
|
|
get_main_symbol() const;
|
|
|
|
elf_symbol_sptr
|
|
get_main_symbol();
|
|
|
|
bool
|
|
is_main_symbol() const;
|
|
|
|
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);
|
|
|
|
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
|
|
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<elf_symbol_sptr>& alias_set);
|
|
|
|
/// The abstraction of the version of an ELF symbol.
|
|
class elf_symbol::version
|
|
{
|
|
struct priv;
|
|
shared_ptr<priv> 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;
|
|
|
|
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> 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 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.
|
|
///
|
|
/// Note that if this bit is set, then either one of the @ref
|
|
/// LOCAL_TYPE_CHANGE_KIND or LOCAL_NON_TYPE_CHANGE_KIND bit must be
|
|
/// set to, detailing what the kind of local change we have.
|
|
LOCAL_CHANGE_KIND = 1,
|
|
|
|
/// This means that a given IR artifact has a local type change. If
|
|
/// this bit is set, then the LOCAL_CHANGE_KIND bit must be set too.
|
|
LOCAL_TYPE_CHANGE_KIND = 1 << 1,
|
|
|
|
/// 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. If this bit is set, then the LOCAL_CHANGE_KIND bit
|
|
/// must be set too.
|
|
LOCAL_NON_TYPE_CHANGE_KIND = 1 << 2,
|
|
|
|
/// 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 << 3,
|
|
|
|
/// The masks below must always be the last enumerators.
|
|
ALL_LOCAL_CHANGES_MASK =
|
|
LOCAL_CHANGE_KIND | LOCAL_TYPE_CHANGE_KIND | LOCAL_NON_TYPE_CHANGE_KIND
|
|
};// 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
|
|
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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
mutable priv_sptr priv_;
|
|
|
|
type_or_decl_base();
|
|
|
|
protected:
|
|
|
|
bool hashing_started() const;
|
|
|
|
void hashing_started(bool) const;
|
|
|
|
public:
|
|
|
|
type_or_decl_base(const environment*);
|
|
|
|
type_or_decl_base(const type_or_decl_base&);
|
|
|
|
virtual ~type_or_decl_base();
|
|
|
|
const environment*
|
|
get_environment() const;
|
|
|
|
environment*
|
|
get_environment();
|
|
|
|
void
|
|
set_environment(const environment*);
|
|
|
|
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) const = 0;
|
|
}; // end class type_or_decl_base
|
|
|
|
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
|
|
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) 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);
|
|
|
|
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);
|
|
|
|
friend type_base_sptr
|
|
canonicalize(type_base_sptr);
|
|
|
|
friend type_base_sptr
|
|
re_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 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<shared_ptr<decl_base> >::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_decl;
|
|
|
|
friend class scope_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&);
|
|
|
|
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
|
|
{
|
|
public:
|
|
|
|
/// Convenience typedef for a vector of @ref decl_base_sptr.
|
|
typedef std::vector<decl_base_sptr > declarations;
|
|
/// Convenience typedef for a vector of @ref function_type_sptr.
|
|
typedef std::vector<function_type_sptr > function_types;
|
|
/// Convenience typedef for a vector of @ref scope_decl_sptr.
|
|
typedef std::vector<scope_decl_sptr> scopes;
|
|
/// The type of the private data of @ref scope_decl.
|
|
struct priv;
|
|
/// A convenience typedef for a shared pointer to scope_decl::priv.
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
private:
|
|
priv_sptr priv_;
|
|
|
|
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(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 declarations&
|
|
get_member_decls() const;
|
|
|
|
declarations&
|
|
get_member_decls();
|
|
|
|
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);
|
|
};//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)
|
|
: type_or_decl_base(tu->get_environment()),
|
|
decl_base(tu->get_environment(), "", location()),
|
|
scope_decl(tu->get_environment(), "", location()),
|
|
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<type_base> 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);
|
|
|
|
friend type_base_sptr re_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<type_base>
|
|
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) 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) 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
priv_sptr priv_;
|
|
|
|
// Forbidden.
|
|
qualified_type_def();
|
|
|
|
protected:
|
|
string build_name(bool, bool internal = false) 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(type_base_sptr type, 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;
|
|
|
|
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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr priv_;
|
|
|
|
// Forbidden.
|
|
pointer_type_def();
|
|
|
|
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);
|
|
|
|
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();
|
|
|
|
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);
|
|
|
|
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
|
|
{
|
|
private:
|
|
struct priv;
|
|
typedef shared_ptr<priv> 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_type> subrange_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref subrange_sptr
|
|
typedef std::vector<subrange_sptr> 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
priv_sptr priv_;
|
|
|
|
// Forbidden.
|
|
subrange_type();
|
|
public:
|
|
|
|
/// 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);
|
|
}; //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,
|
|
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<subrange_sptr>&);
|
|
|
|
virtual string
|
|
get_pretty_representation(bool internal = false) const;
|
|
|
|
virtual bool
|
|
traverse(ir_node_visitor&);
|
|
}; // end class subrange_type
|
|
|
|
array_type_def(const type_base_sptr type,
|
|
const std::vector<subrange_sptr>& 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_subrange(subrange_sptr sub);
|
|
|
|
virtual void
|
|
append_subranges(const std::vector<subrange_sptr>& subs);
|
|
|
|
virtual int
|
|
get_dimension_count() const;
|
|
|
|
virtual bool
|
|
is_infinite() const;
|
|
|
|
virtual string
|
|
get_pretty_representation(bool internal = false) const;
|
|
|
|
virtual string
|
|
get_subrange_representation() const;
|
|
|
|
virtual bool
|
|
traverse(ir_node_visitor& v);
|
|
|
|
const location&
|
|
get_location() const;
|
|
|
|
const std::vector<subrange_sptr>&
|
|
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
|
|
{
|
|
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<enumerator> enumerators;
|
|
|
|
private:
|
|
|
|
class priv;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr priv_;
|
|
|
|
// 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,
|
|
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) 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
priv_sptr priv_;
|
|
|
|
|
|
public:
|
|
|
|
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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr 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);
|
|
|
|
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) const;
|
|
|
|
type_base_sptr
|
|
get_underlying_type() const;
|
|
|
|
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:
|
|
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) const
|
|
{
|
|
if (!context_rel::operator==(o))
|
|
return false;
|
|
|
|
return (is_laid_out_ == o.is_laid_out_
|
|
&& offset_in_bits_ == o.offset_in_bits_);
|
|
}
|
|
|
|
bool
|
|
operator!=(const dm_context_rel& o) const
|
|
{return !operator==(o);}
|
|
|
|
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;
|
|
shared_ptr<priv> 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) 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 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> parameter_sptr;
|
|
|
|
/// Convenience typedef for a vector of @ref parameter_sptr
|
|
typedef std::vector<parameter_sptr> 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) const;
|
|
|
|
string
|
|
get_pretty_representation_of_declarator (bool internal = false) const;
|
|
|
|
const std::vector<parameter_sptr >&
|
|
get_parameters() const;
|
|
|
|
void
|
|
append_parameter(parameter_sptr parm);
|
|
|
|
void
|
|
append_parameters(std::vector<parameter_sptr >& 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr 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);
|
|
|
|
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_artificial() const;
|
|
|
|
void
|
|
set_artificial(bool f);
|
|
|
|
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) 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
|
|
{
|
|
struct priv;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
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<function_decl::parameter> parameter_sptr;
|
|
/// Convenience typedef for a vector of @ref parameter_sptr
|
|
typedef std::vector<parameter_sptr> parameters;
|
|
|
|
priv_sptr 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;
|
|
|
|
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) 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
priv_sptr 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<function_decl::parameter_sptr>& 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<function_decl::parameter_sptr>& 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) 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
priv_sptr 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<template_parameter_sptr>&
|
|
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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
priv_sptr 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
priv_sptr 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr 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<function_decl> p);
|
|
|
|
shared_ptr<function_decl>
|
|
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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr 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<class_decl>
|
|
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);
|
|
|
|
public:
|
|
/// Hasher.
|
|
struct hash;
|
|
|
|
/// Convenience typedef
|
|
/// @{
|
|
typedef vector<type_base_sptr> member_types;
|
|
typedef vector<var_decl_sptr> data_members;
|
|
typedef vector<method_decl_sptr> member_functions;
|
|
typedef unordered_map<ssize_t, member_functions> virtual_mem_fn_map_type;
|
|
typedef unordered_map<string, method_decl*> string_mem_fn_ptr_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);
|
|
|
|
typedef_decl_sptr
|
|
get_naming_typedef() const;
|
|
|
|
void
|
|
set_naming_typedef(const typedef_decl_sptr&);
|
|
|
|
bool
|
|
get_is_declaration_only() const;
|
|
|
|
void
|
|
set_is_declaration_only(bool f);
|
|
|
|
void
|
|
set_definition_of_declaration(class_or_union_sptr);
|
|
|
|
const class_or_union_sptr
|
|
get_definition_of_declaration() const;
|
|
|
|
const class_or_union*
|
|
get_naked_definition_of_declaration() const;
|
|
|
|
decl_base_sptr
|
|
get_earlier_declaration() const;
|
|
|
|
void
|
|
set_earlier_declaration(decl_base_sptr declaration);
|
|
|
|
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 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);
|
|
|
|
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);
|
|
|
|
/// 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> base_spec_sptr;
|
|
typedef vector<base_spec_sptr> 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);
|
|
|
|
class_decl(const environment* env, const string& name, bool is_struct,
|
|
bool is_declaration_only = true);
|
|
|
|
const class_decl_sptr
|
|
get_definition_of_declaration() const;
|
|
|
|
const class_decl*
|
|
get_naked_definition_of_declaration() const;
|
|
|
|
virtual string
|
|
get_pretty_representation(bool internal = false) const;
|
|
|
|
void
|
|
is_struct(bool f);
|
|
|
|
bool
|
|
is_struct() const;
|
|
|
|
void
|
|
add_base_specifier(shared_ptr<base_spec> 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;
|
|
typedef shared_ptr<priv>priv_sptr;
|
|
|
|
priv_sptr 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);
|
|
|
|
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);
|
|
|
|
union_decl(const environment* env, const string& name,
|
|
bool is_declaration_only = true);
|
|
|
|
virtual string
|
|
get_pretty_representation(bool internal = false) 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);
|
|
|
|
/// 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<function_tdecl> 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_tdecl> 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<type_base> 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<function_tdecl> 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<class_tdecl> 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;
|
|
typedef shared_ptr<priv> priv_sptr;
|
|
|
|
priv_sptr priv_;
|
|
|
|
public:
|
|
|
|
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<function_decl*>::const_iterator a_begin,
|
|
vector<function_decl*>::const_iterator a_end,
|
|
vector<function_decl*>::const_iterator b_begin,
|
|
vector<function_decl*>::const_iterator b_end,
|
|
std::ostream& o);
|
|
|
|
}// end namespace ir
|
|
} // end namespace abigail
|
|
#endif // __ABG_IR_H__
|