mirror of
git://sourceware.org/git/libabigail.git
synced 2025-01-18 23:30:45 +00:00
Add diff support for typedef_decl and type_decl
* include/abg-ir.h (operator<<(std::ostream&, decl_base::visibility)): Declare new streaming operator. * src/abg-ir.cc (operator<<(std::ostream&, decl_base::visibility)): Define it. (type_decl::{operator==, get_pretty_representation}): Likewise, define these new overloads. (decl_base::{operator==, get_pretty_representation}): New overloads. * include/abg-comparison.h (type_decl_diff type_decl_diff_sptr, typedef_diff, typedef_diff_sptr): Declare new classes and typedefs. * src/abg-comparison.cc (type_decl_diff::{type_decl_diff, first_type_decl, second_type_decl, length, report}): New methods definitions. (compute_diff): New function definition that takes pointers of type_decl. (typedef_diff::{typedef_diff, first_typedef_decl, second_typedef_decl, underlying_type_diff, length, report}): New methods. (compute_diff): New function definition that takes pointers of typedef_decl. (try_to_diff_types): New template function, factorized out of ... (compute_diff_for_types): ... this. Add support diffing type_decl and typedef_decl. (pointer_diff::report): Fix indentation of emitted report. * tools/bidiff.cc (parse_command_line): Fix style. Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
parent
a03d9c0e64
commit
1cdc283b1d
@ -374,6 +374,78 @@ function_decl_diff_sptr
|
||||
compute_diff(const function_decl_sptr first,
|
||||
const function_decl_sptr second);
|
||||
|
||||
class type_decl_diff;
|
||||
typedef shared_ptr<type_decl_diff> type_decl_diff_sptr;
|
||||
|
||||
/// Abstraction of a diff between two basic type declarations.
|
||||
class type_decl_diff : public diff
|
||||
{
|
||||
type_decl_diff();
|
||||
|
||||
public:
|
||||
|
||||
friend type_decl_diff_sptr
|
||||
compute_diff(const type_decl_sptr, const type_decl_sptr);
|
||||
|
||||
type_decl_diff(const type_decl_sptr, const type_decl_sptr);
|
||||
|
||||
const type_decl_sptr
|
||||
first_type_decl() const;
|
||||
|
||||
const type_decl_sptr
|
||||
second_type_decl() const;
|
||||
|
||||
unsigned
|
||||
length() const;
|
||||
|
||||
void
|
||||
report(ostream& out, const string& indent = "") const;
|
||||
};// end type_decl_diff
|
||||
|
||||
type_decl_diff_sptr
|
||||
compute_diff(const type_decl_sptr, const type_decl_sptr);
|
||||
|
||||
class typedef_diff;
|
||||
typedef shared_ptr<typedef_diff> typedef_diff_sptr;
|
||||
|
||||
/// Abstraction of a diff between two typedef_decl.
|
||||
class typedef_diff : public diff
|
||||
{
|
||||
struct priv;
|
||||
shared_ptr<priv> priv_;
|
||||
|
||||
typedef_diff();
|
||||
|
||||
public:
|
||||
|
||||
friend typedef_diff_sptr
|
||||
compute_diff(const typedef_decl_sptr, const typedef_decl_sptr);
|
||||
|
||||
typedef_diff(const typedef_decl_sptr first,
|
||||
const typedef_decl_sptr second);
|
||||
|
||||
const typedef_decl_sptr
|
||||
first_typedef_decl() const;
|
||||
|
||||
const typedef_decl_sptr
|
||||
second_typedef_decl() const;
|
||||
|
||||
const diff_sptr
|
||||
underlying_type_diff() const;
|
||||
|
||||
void
|
||||
underlying_type_diff(const diff_sptr);
|
||||
|
||||
virtual unsigned
|
||||
length() const;
|
||||
|
||||
virtual void
|
||||
report(ostream&, const string& indent = "") const;
|
||||
};// end class typedef_diff
|
||||
|
||||
typedef_diff_sptr
|
||||
compute_diff(const typedef_decl_sptr, const typedef_decl_sptr);
|
||||
|
||||
class translation_unit_diff;
|
||||
typedef shared_ptr<translation_unit_diff> translation_unit_diff_sptr;
|
||||
|
||||
|
@ -267,6 +267,9 @@ public:
|
||||
bool
|
||||
operator==(decl_base_sptr, decl_base_sptr);
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream&, decl_base::visibility);
|
||||
|
||||
typedef shared_ptr<scope_decl> scope_decl_sptr;
|
||||
|
||||
/// A declaration that introduces a scope.
|
||||
@ -433,6 +436,9 @@ public:
|
||||
virtual bool
|
||||
operator==(const decl_base&) const;
|
||||
|
||||
virtual bool
|
||||
operator==(const type_decl&) const;
|
||||
|
||||
void
|
||||
traverse(ir_node_visitor&);
|
||||
|
||||
@ -721,6 +727,9 @@ public:
|
||||
virtual bool
|
||||
operator==(const type_base&) const;
|
||||
|
||||
virtual string
|
||||
get_pretty_representation() const;
|
||||
|
||||
shared_ptr<type_base>
|
||||
get_underlying_type() const;
|
||||
|
||||
|
@ -36,6 +36,34 @@ using std::vector;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
/// Try to compute a diff on two instances of type representation.
|
||||
///
|
||||
/// The function template performs the diff if and only if the type
|
||||
/// representations are of a certain type.
|
||||
///
|
||||
/// @param first the first representation of type to consider in the
|
||||
/// diff computation.
|
||||
///
|
||||
/// @param second the second representation oftype to consider in the
|
||||
/// diff computation.
|
||||
///
|
||||
///@return the diff of the two types @a first and @a second if and
|
||||
///only if they represent the parametrized type DiffType. Otherwise,
|
||||
///returns a NULL pointer value.
|
||||
template<typename DiffType>
|
||||
diff_sptr
|
||||
try_to_diff_types(const decl_base_sptr first, const decl_base_sptr second)
|
||||
{
|
||||
if (shared_ptr<DiffType> f =
|
||||
dynamic_pointer_cast<DiffType>(first))
|
||||
{
|
||||
shared_ptr<DiffType> s =
|
||||
dynamic_pointer_cast<DiffType>(second);
|
||||
return compute_diff(f, s);
|
||||
}
|
||||
return diff_sptr();
|
||||
}
|
||||
|
||||
/// Compute the difference between two types.
|
||||
///
|
||||
/// The function considers every possible types known to libabigail
|
||||
@ -52,29 +80,17 @@ using std::tr1::static_pointer_cast;
|
||||
/// @return the resulting diff. It's a pointer to a descendent of
|
||||
/// abigail::comparison::diff.
|
||||
static diff_sptr
|
||||
compute_diff_for_types(const decl_base_sptr first, decl_base_sptr second)
|
||||
compute_diff_for_types(const decl_base_sptr first, const decl_base_sptr second)
|
||||
{
|
||||
if (class_decl_sptr f = dynamic_pointer_cast<class_decl>(first))
|
||||
{
|
||||
class_decl_sptr s = dynamic_pointer_cast<class_decl>(second);
|
||||
class_diff_sptr d(new class_diff(f, s));
|
||||
return compute_diff(f, s);
|
||||
}
|
||||
else if (pointer_type_def_sptr f =
|
||||
dynamic_pointer_cast<pointer_type_def>(first))
|
||||
{
|
||||
pointer_type_def_sptr s = dynamic_pointer_cast<pointer_type_def>(second);
|
||||
return compute_diff(f, s);
|
||||
}
|
||||
else if (reference_type_def_sptr f =
|
||||
dynamic_pointer_cast<reference_type_def>(first))
|
||||
{
|
||||
reference_type_def_sptr s =
|
||||
dynamic_pointer_cast<reference_type_def>(second);
|
||||
return compute_diff(f, s);
|
||||
}
|
||||
diff_sptr d;
|
||||
|
||||
return diff_sptr();
|
||||
((d = try_to_diff_types<type_decl>(first, second))
|
||||
||(d = try_to_diff_types<class_decl>(first, second))
|
||||
||(d = try_to_diff_types<pointer_type_def>(first, second))
|
||||
||(d = try_to_diff_types<reference_type_def>(first, second))
|
||||
||(d = try_to_diff_types<typedef_decl>(first, second)));
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/// Compute the difference between two types.
|
||||
@ -188,8 +204,7 @@ pointer_diff::report(ostream& out, const string& indent) const
|
||||
{
|
||||
out << indent << "differences in pointed to type ("
|
||||
<< d->first_subject()->get_pretty_representation() << "):\n";
|
||||
out << indent << " ";
|
||||
d->report(out, indent);
|
||||
d->report(out, indent + " ");
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
@ -1691,6 +1706,214 @@ compute_diff(const function_decl_sptr first,
|
||||
|
||||
// </function_decl_diff stuff>
|
||||
|
||||
// <type_decl_diff stuff>
|
||||
|
||||
/// Constructor for type_decl_diff.
|
||||
type_decl_diff::type_decl_diff(const type_decl_sptr first,
|
||||
const type_decl_sptr second)
|
||||
: diff(first, second)
|
||||
{}
|
||||
|
||||
/// Getter for the first subject of the type_decl_diff.
|
||||
///
|
||||
/// @return the first type_decl involved in the diff.
|
||||
const type_decl_sptr
|
||||
type_decl_diff::first_type_decl() const
|
||||
{return dynamic_pointer_cast<type_decl>(first_subject());}
|
||||
|
||||
/// Getter for the second subject of the type_decl_diff.
|
||||
///
|
||||
/// @return the second type_decl involved in the diff.
|
||||
const type_decl_sptr
|
||||
type_decl_diff::second_type_decl() const
|
||||
{return dynamic_pointer_cast<type_decl>(second_subject());}
|
||||
|
||||
/// Getter for the length of the diff.
|
||||
///
|
||||
/// @return 0 if the two type_decl are equal, 1 otherwise.
|
||||
unsigned
|
||||
type_decl_diff::length() const
|
||||
{return *first_type_decl() == *second_type_decl() ? 0 : 1;}
|
||||
|
||||
/// Ouputs a report of the differences between of the two type_decl
|
||||
/// involved in the type_decl_diff.
|
||||
///
|
||||
/// @param out the output stream to emit the report to.
|
||||
///
|
||||
/// @param the string to use for indentatino indent.
|
||||
void
|
||||
type_decl_diff::report(ostream& out, const string& indent) const
|
||||
{
|
||||
if (length() == 0)
|
||||
return;
|
||||
|
||||
type_decl_sptr f = first_type_decl(), s = second_type_decl();
|
||||
if (f->get_name() == s->get_name())
|
||||
out << indent << f->get_pretty_representation() << " changed:\n";
|
||||
else
|
||||
out << indent
|
||||
<< f->get_pretty_representation() << " was replaced by "
|
||||
<< s->get_pretty_representation() << ":\n";
|
||||
|
||||
if (f->get_visibility() != s->get_visibility())
|
||||
out << indent
|
||||
<< "visibility changed from '"
|
||||
<< f->get_visibility() << "' to '" << s->get_visibility() << "'\n";
|
||||
|
||||
if (f->get_size_in_bits() != s->get_size_in_bits())
|
||||
out << indent
|
||||
<< "size changed from "
|
||||
<< f->get_size_in_bits() << " to "
|
||||
<< s->get_size_in_bits() << " bits\n";
|
||||
|
||||
if (f->get_alignment_in_bits() != s->get_alignment_in_bits())
|
||||
out << indent
|
||||
<< "alignment changed from "
|
||||
<< f->get_alignment_in_bits() << " to "
|
||||
<< s->get_alignment_in_bits() << " bits\n";
|
||||
|
||||
if (f->get_mangled_name() != s->get_mangled_name())
|
||||
out << indent
|
||||
<< "mangled name changed from '"
|
||||
<< f->get_mangled_name() << "' to "
|
||||
<< s->get_mangled_name() << "'\n";
|
||||
}
|
||||
|
||||
/// Compute a diff between two type_decl.
|
||||
///
|
||||
/// This function doesn't actually compute a diff. As a type_decl is
|
||||
/// very simple (unlike compound constructs like function_decl or
|
||||
/// class_decl) it's easy to just compare the components of the
|
||||
/// type_decl to know what has changed. Thus this function just
|
||||
/// builds and return a type_decl_diff object. The
|
||||
/// type_decl_diff::report function will just compare the components
|
||||
/// of the the two type_decl and display where and how they differ.
|
||||
///
|
||||
/// @param first a pointer to the first type_decl to
|
||||
/// consider.
|
||||
///
|
||||
/// @param second a pointer to the second type_decl to consider.
|
||||
///
|
||||
/// @return a pointer to the resulting type_decl_diff.
|
||||
type_decl_diff_sptr
|
||||
compute_diff(const type_decl_sptr first, const type_decl_sptr second)
|
||||
{
|
||||
type_decl_diff_sptr result(new type_decl_diff(first, second));
|
||||
|
||||
// We don't need to actually compute a diff here as a type_decl
|
||||
// doesn't have complicated sub-components. type_decl_diff::report
|
||||
// just walks the members of the type_decls and display information
|
||||
// about the ones that have changed. On a similar note,
|
||||
// type_decl_diff::length returns 0 if the two type_decls are equal,
|
||||
// and 1 otherwise.
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// </type_decl_diff stuff>
|
||||
|
||||
// <typedef_diff stuff>
|
||||
|
||||
struct typedef_diff::priv
|
||||
{
|
||||
diff_sptr underlying_type_diff_;
|
||||
};//end struct typedef_diff::priv
|
||||
|
||||
/// Constructor for typedef_diff.
|
||||
typedef_diff::typedef_diff(const typedef_decl_sptr first,
|
||||
const typedef_decl_sptr second)
|
||||
: diff(first, second),
|
||||
priv_(new priv)
|
||||
{}
|
||||
|
||||
/// Getter for the firt typedef_decl involved in the diff.
|
||||
///
|
||||
/// @return the first subject of the diff.
|
||||
const typedef_decl_sptr
|
||||
typedef_diff::first_typedef_decl() const
|
||||
{return dynamic_pointer_cast<typedef_decl>(first_subject());}
|
||||
|
||||
/// Getter for the second typedef_decl involved in the diff.
|
||||
///
|
||||
/// @return the second subject of the diff.
|
||||
const typedef_decl_sptr
|
||||
typedef_diff::second_typedef_decl() const
|
||||
{return dynamic_pointer_cast<typedef_decl>(second_subject());}
|
||||
|
||||
/// Getter for the diff between the two underlying types of the
|
||||
/// typedefs.
|
||||
///
|
||||
/// @return the diff object reprensenting the difference between the
|
||||
/// two underlying types of the typedefs.
|
||||
const diff_sptr
|
||||
typedef_diff::underlying_type_diff() const
|
||||
{return priv_->underlying_type_diff_;}
|
||||
|
||||
/// Setter for the diff between the two underlying types of the
|
||||
/// typedefs.
|
||||
///
|
||||
/// @param d the new diff object reprensenting the difference between
|
||||
/// the two underlying types of the typedefs.
|
||||
void
|
||||
typedef_diff::underlying_type_diff(const diff_sptr d)
|
||||
{priv_->underlying_type_diff_ = d;}
|
||||
|
||||
/// Getter of the length of the diff between the two typedefs.
|
||||
///
|
||||
/// @return 0 if the two typedefs are equal, or an integer
|
||||
/// representing the length of the difference.
|
||||
unsigned
|
||||
typedef_diff::length() const
|
||||
{
|
||||
if (!underlying_type_diff())
|
||||
return 0;
|
||||
return underlying_type_diff()->length();
|
||||
}
|
||||
|
||||
/// Reports the difference between the two subjects of the diff in a
|
||||
/// serialized form.
|
||||
///
|
||||
/// @param out the output stream to emit the repot to.
|
||||
///
|
||||
/// @param indent the indentation string to use.
|
||||
void
|
||||
typedef_diff::report(ostream& out, const string& indent) const
|
||||
{
|
||||
if (length() == 0)
|
||||
return;
|
||||
|
||||
typedef_decl_sptr f = first_typedef_decl(), s = second_typedef_decl();
|
||||
if (f->get_name() != s->get_name())
|
||||
out << indent << "typedef name changed from "
|
||||
<< f->get_name() << " to " << s->get_name();
|
||||
|
||||
if (diff_sptr d = underlying_type_diff())
|
||||
{
|
||||
out << indent << "underlying type changed:\n";
|
||||
d->report(out, indent + " ");
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute a diff between two typedef_decl.
|
||||
///
|
||||
/// @param first a pointer to the first typedef_decl to consider.
|
||||
///
|
||||
/// @param second a pointer to the second typedef_decl to consider.
|
||||
///
|
||||
/// @return a pointer to the the resulting typedef_diff.
|
||||
typedef_diff_sptr
|
||||
compute_diff(const typedef_decl_sptr first, const typedef_decl_sptr second)
|
||||
{
|
||||
diff_sptr d = compute_diff_for_types(first->get_underlying_type(),
|
||||
second->get_underlying_type());
|
||||
typedef_diff_sptr result(new typedef_diff(first, second));
|
||||
result->underlying_type_diff(d);
|
||||
return result;
|
||||
}
|
||||
|
||||
// </typedef_diff stuff>
|
||||
|
||||
// <translation_unit_diff stuff>
|
||||
|
||||
/// Constructor for translation_unit_diff.
|
||||
|
@ -330,6 +330,38 @@ void
|
||||
decl_base::set_scope(scope_decl* scope)
|
||||
{context_ = scope;}
|
||||
|
||||
/// Streaming operator for the decl_base::visibility.
|
||||
///
|
||||
/// @param o the output stream to serialize the visibility to.
|
||||
///
|
||||
/// @param v the visibility to serialize.
|
||||
///
|
||||
/// @return the output stream.
|
||||
std::ostream&
|
||||
operator<<(std::ostream& o, decl_base::visibility v)
|
||||
{
|
||||
string r;
|
||||
switch (v)
|
||||
{
|
||||
case decl_base::VISIBILITY_NONE:
|
||||
r = "none";
|
||||
break;
|
||||
case decl_base::VISIBILITY_DEFAULT:
|
||||
r = "default";
|
||||
break;
|
||||
case decl_base::VISIBILITY_PROTECTED:
|
||||
r = "protected";
|
||||
break;
|
||||
case decl_base::VISIBILITY_HIDDEN:
|
||||
r = "hidden";
|
||||
break;
|
||||
case decl_base::VISIBILITY_INTERNAL:
|
||||
r = "internal";
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
/// Turn equality of shared_ptr of decl_base into a deep equality;
|
||||
/// that is, make it compare the pointed to objects too.
|
||||
///
|
||||
@ -711,6 +743,18 @@ type_decl::operator==(const decl_base& o) const
|
||||
{return false;}
|
||||
}
|
||||
|
||||
/// Return true if both types equals.
|
||||
///
|
||||
/// Note that this does not check the scopes of any of the types.
|
||||
///
|
||||
/// @param o the other type_decl to check against.
|
||||
bool
|
||||
type_decl::operator==(const type_decl& o) const
|
||||
{
|
||||
const decl_base& other = o;
|
||||
return *this == other;
|
||||
}
|
||||
|
||||
/// This implements the traversable_base::traverse pure virtual
|
||||
/// function.
|
||||
///
|
||||
@ -1202,6 +1246,17 @@ typedef_decl::operator==(const type_base& o) const
|
||||
{return false;}
|
||||
}
|
||||
|
||||
/// Build a pretty representation for a typedef_decl.
|
||||
///
|
||||
/// @return a copy of the pretty representation of the current
|
||||
/// instance of typedef_decl.
|
||||
string
|
||||
typedef_decl::get_pretty_representation() const
|
||||
{
|
||||
string result = "typedef " + get_qualified_name();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Getter of the underlying type of the typedef.
|
||||
///
|
||||
/// @return the underlying_type.
|
||||
|
@ -80,7 +80,7 @@ parse_command_line(int argc, char* argv[], options& opts)
|
||||
else
|
||||
return false;
|
||||
}
|
||||
else if (!strcmp (argv[i], "--help"))
|
||||
else if (!strcmp(argv[i], "--help"))
|
||||
return false;
|
||||
else
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user