peel_qualified_diff(const diff* dif);
const diff*
-peel_pointer_or_qualified_type(const diff*dif);
+peel_pointer_or_qualified_type_diff(const diff* dif);
+
+const diff*
+peel_typedef_or_qualified_type_diff(const diff* dif);
}// end namespace comparison
}// end namespace abigail
enum_type_decl_sptr
is_enum_type(const type_or_decl_base_sptr&);
+const enum_type_decl*
+is_enum_type(const type_or_decl_base*);
+
bool
is_class_type(const type_or_decl_base&);
return false;
}
+/// Test if a diff node carries a harmless change of an enum into an
+/// integer (or vice-versa).
+///
+/// The test takes into account the fact change we care about might be
+/// wrapped into a typedef or qualified type diff.
+///
+/// @param diff the diff node to consider.
+///
+/// @return true if @p diff is a harmless enum to integer change.
+static bool
+has_harmless_enum_to_int_change(const diff* diff)
+{
+ if (!diff)
+ return false;
+
+ diff = peel_typedef_or_qualified_type_diff(diff);
+
+ if (const distinct_diff *d = is_distinct_diff(diff))
+ {
+ const enum_type_decl *enum_type = 0;
+ const type_base *integer_type = 0;
+
+ type_base *first_type =
+ peel_qualified_or_typedef_type(is_type(d->first().get()));
+ type_base *second_type =
+ peel_qualified_or_typedef_type(is_type(d->second().get()));
+
+ if (const enum_type_decl *e = is_enum_type(first_type))
+ enum_type = e;
+ else if (const enum_type_decl *e = is_enum_type(second_type))
+ enum_type = e;
+
+ if (const type_base * i = is_type_decl(first_type))
+ integer_type = i;
+ else if (const type_base *i = is_type_decl(second_type))
+ integer_type = i;
+
+ if (enum_type
+ && integer_type
+ && enum_type->get_size_in_bits() == integer_type->get_size_in_bits())
+ return true;
+ }
+
+ return false;
+}
+
/// Test if an @ref fn_parm_diff node has a top cv qualifier change on
/// the type of the function parameter.
///
|| static_data_member_type_size_changed(f, s))
category |= STATIC_DATA_MEMBER_CHANGE_CATEGORY;
- if (has_enumerator_insertion(d)
- && !has_harmful_enum_change(d))
+ if ((has_enumerator_insertion(d)
+ && !has_harmful_enum_change(d))
+ || has_harmless_enum_to_int_change(d))
category |= HARMLESS_ENUM_CHANGE_CATEGORY;
if (function_name_changed_but_not_symbol(d))
is_diff_of_basic_type(const diff* diff, bool allow_indirect_type)
{
if (allow_indirect_type)
- diff = peel_pointer_or_qualified_type(diff);
+ diff = peel_pointer_or_qualified_type_diff(diff);
return is_diff_of_basic_type(diff);
}
/// @return the underlying diff node of @p dif, or just return @p dif
/// if it's not a pointer, reference or qualified diff node.
const diff*
-peel_pointer_or_qualified_type(const diff*dif)
+peel_pointer_or_qualified_type_diff(const diff*dif)
{
while (true)
{
return dif;
}
+/// If a diff node is about changes between two typedefs or qualified
+/// types, get the diff node about changes between the underlying
+/// types.
+///
+/// Note that this function walks the tree of underlying diff nodes
+/// returns the first diff node about types that are not typedef or
+/// qualified types.
+///
+/// @param dif the dif node to consider.
+///
+/// @return the underlying diff node of @p dif, or just return @p dif
+/// if it's not typedef or qualified diff node.
+const diff*
+peel_typedef_or_qualified_type_diff(const diff *dif)
+{
+ while (true)
+ {
+ if (const typedef_diff *d = is_typedef_diff(dif))
+ dif = peel_typedef_diff(d);
+ else if (const qualified_type_diff *d = is_qualified_type_diff(dif))
+ dif = peel_qualified_diff(d);
+ else
+ break;
+ }
+ return dif;
+}
+
/// Test if a diff node represents a diff between two class or union
/// types.
///
test-diff-filter/test-PR24731-v0.o \
test-diff-filter/test-PR24731-v1.c \
test-diff-filter/test-PR24731-v1.o \
+test-diff-filter/PR24787-libone.so \
+test-diff-filter/PR24787-libtwo.so \
+test-diff-filter/PR24787-one.c \
+test-diff-filter/PR24787-two.c \
+test-diff-filter/PR24787-report-0.txt \
\
test-diff-suppr/test0-type-suppr-v0.cc \
test-diff-suppr/test0-type-suppr-v1.cc \
--- /dev/null
+#include <stdio.h>
+
+
+typedef enum FooFilter {
+ FOO_FILTER_ONE = 1 << 0,
+ FOO_FILTER_TWO = 1 << 1,
+ FOO_FILTER_THREE = 1 << 2,
+} FooFilter;
+
+
+void do_something(FooFilter filter_flags) {
+ printf("%d\n", filter_flags);
+}
--- /dev/null
+Functions changes summary: 0 Removed, 0 Changed (1 filtered out), 0 Added function
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
--- /dev/null
+#include <stdio.h>
+
+
+typedef enum FooFilter {
+ FOO_FILTER_ONE = 1 << 0,
+ FOO_FILTER_TWO = 1 << 1,
+ FOO_FILTER_THREE = 1 << 2,
+} FooFilter;
+
+
+void do_something(unsigned int filter_flags) {
+ printf("%d\n", filter_flags);
+}
"data/test-diff-filter/test-PR24731-report-1.txt",
"output/test-diff-filter/test-PR24731-report-1.txt",
},
+ {
+ "data/test-diff-filter/PR24787-libone.so",
+ "data/test-diff-filter/PR24787-libtwo.so",
+ "--no-default-suppression",
+ "data/test-diff-filter/PR24787-report-0.txt",
+ "output/test-diff-filter/PR24787-report-0.txt",
+ },
// This should be the last entry
{NULL, NULL, NULL, NULL, NULL}
};