/// cv-qualifier change.
FN_RETURN_TYPE_CV_CHANGE_CATEGORY = 1 << 15,
+ /// A diff node in this category carries a change from void pointer
+ /// to non-void pointer.
+ VOID_PTR_TO_PTR_CHANGE_CATEGORY = 1 << 16,
+
/// A special enumerator that is the logical 'or' all the
/// enumerators above.
///
| FN_PARM_TYPE_TOP_CV_CHANGE_CATEGORY
| FN_PARM_TYPE_CV_CHANGE_CATEGORY
| FN_RETURN_TYPE_CV_CHANGE_CATEGORY
+ | VOID_PTR_TO_PTR_CHANGE_CATEGORY
}; // enum diff_category
diff_category
reference_type_def_sptr
is_reference_type(const type_or_decl_base_sptr&);
+const type_base*
+is_void_pointer_type(const type_base*);
+
qualified_type_def*
is_qualified_type(const type_or_decl_base*);
return type_diff_has_cv_qual_change_only(return_type_diff);
}
+/// Test if a diff node carries a void* to pointer type change.
+///
+/// Note that this function looks through typedef and qualifier types
+/// to find the void pointer.
+///
+/// @param dif the diff node to consider.
+///
+/// @return true iff @p dif carries a void* to pointer type change.
+static bool
+has_void_ptr_to_ptr_change(const diff* dif)
+{
+ dif = peel_typedef_diff(dif);
+
+ if (const distinct_diff *d = is_distinct_diff(dif))
+ {
+ const type_base *f = is_type(d->first().get());
+ const type_base *s = is_type(d->second().get());
+
+ f = peel_qualified_or_typedef_type(f);
+ s = peel_qualified_or_typedef_type(s);
+
+ if (is_void_pointer_type(f)
+ && is_pointer_type(s)
+ && !is_void_pointer_type(s)
+ && f->get_size_in_bits() == s->get_size_in_bits())
+ return true;
+ }
+ else if (const pointer_diff *d = is_pointer_diff(dif))
+ {
+ const type_base *f = is_type(d->first_pointer()).get();
+ const type_base *s = is_type(d->second_pointer()).get();
+
+ f = peel_qualified_or_typedef_type(f);
+ s = peel_qualified_or_typedef_type(s);
+
+ if (is_void_pointer_type(f)
+ && is_pointer_type(s)
+ && !is_void_pointer_type(s)
+ && f->get_size_in_bits() == s->get_size_in_bits())
+ return true;
+ }
+ else if (const qualified_type_diff *d = is_qualified_type_diff(dif))
+ {
+ const type_base *f = is_type(d->first_qualified_type()).get();
+ const type_base *s = is_type(d->second_qualified_type()).get();
+
+ f = peel_qualified_or_typedef_type(f);
+ s = peel_qualified_or_typedef_type(s);
+
+ if (is_void_pointer_type(f)
+ && is_pointer_type(s)
+ && !is_void_pointer_type(s)
+ && f->get_size_in_bits() == s->get_size_in_bits())
+ return true;
+ }
+
+ return false;
+}
+
/// Detect if the changes carried by a given diff node are deemed
/// harmless and do categorize the diff node accordingly.
///
if (has_fn_return_type_cv_qual_change(d))
category |= FN_RETURN_TYPE_CV_CHANGE_CATEGORY;
+ if (has_void_ptr_to_ptr_change(d))
+ category |= VOID_PTR_TO_PTR_CHANGE_CATEGORY;
+
if (category)
{
d->add_to_local_and_inherited_categories(category);
| abigail::comparison::CLASS_DECL_ONLY_DEF_CHANGE_CATEGORY
| abigail::comparison::FN_PARM_TYPE_TOP_CV_CHANGE_CATEGORY
| abigail::comparison::FN_PARM_TYPE_CV_CHANGE_CATEGORY
- | abigail::comparison::FN_RETURN_TYPE_CV_CHANGE_CATEGORY);
+ | abigail::comparison::FN_RETURN_TYPE_CV_CHANGE_CATEGORY
+ | abigail::comparison::VOID_PTR_TO_PTR_CHANGE_CATEGORY);
}
/// Getter of a bitmap made of the set of change categories that are
emitted_a_category |= true;
}
+ if (c & VOID_PTR_TO_PTR_CHANGE_CATEGORY)
+ {
+ if (emitted_a_category)
+ o << "|";
+ o << "VOID_PTR_TO_PTR_CHANGE_CATEGORY";
+ emitted_a_category |= true;
+ }
+
return o;
}
is_reference_type(const type_or_decl_base_sptr& t)
{return dynamic_pointer_cast<reference_type_def>(t);}
+/// Test if a type is a pointer to void type.
+///
+/// Note that this looks trough typedefs or CV qualifiers to look for
+/// the void pointer.
+///
+/// @param type the type to consider.
+///
+/// @return the actual void pointer if @p is a void pointer or NULL if
+/// it's not.
+const type_base*
+is_void_pointer_type(const type_base* type)
+{
+ type = peel_qualified_or_typedef_type(type);
+
+ const pointer_type_def * t = is_pointer_type(type);
+ if (!t)
+ return 0;
+
+ if (t->get_environment()->is_void_type(t->get_pointed_to_type()))
+ return t;
+
+ return 0;
+}
+
/// Test whether a type is a reference_type_def.
///
/// @param t the type to test.
test-diff-filter/test46-fn-return-qual-change-v1.c \
test-diff-filter/test46-fn-return-qual-change-v0.o \
test-diff-filter/test46-fn-return-qual-change-v1.o \
+test-diff-filter/test47-filter-void-ptr-change-report-0.txt \
+test-diff-filter/test47-filter-void-ptr-change-v0.c \
+test-diff-filter/test47-filter-void-ptr-change-v1.c \
+test-diff-filter/test47-filter-void-ptr-change-v0.o \
+test-diff-filter/test47-filter-void-ptr-change-v1.o \
\
test-diff-suppr/test0-type-suppr-v0.cc \
test-diff-suppr/test0-type-suppr-v1.cc \
--- /dev/null
+Functions changes summary: 0 Removed, 0 Changed (2 filtered out), 0 Added functions
+Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
+
--- /dev/null
+struct S0
+{
+ void* m0;
+};
+
+typedef const void* POINTER;
+
+struct S1
+{
+ POINTER m0;
+};
+
+void foo(struct S0* a __attribute__((unused)))
+{
+}
+
+void bar(struct S1* a __attribute__((unused)))
+{
+}
--- /dev/null
+struct S0
+{
+ int* m0;
+};
+
+typedef const char* POINTER;
+
+struct S1
+{
+ POINTER m0;
+};
+
+void foo(struct S0* a __attribute__((unused)))
+{
+}
+
+void bar(struct S1* a __attribute__((unused)))
+{
+}
"data/test-diff-filter/libtest45-basic-type-change-report-1.txt",
"output/test-diff-filter/libtest45-basic-type-change-report-1.txt",
},
+ {
+ "data/test-diff-filter/test46-fn-return-qual-change-v0.o",
+ "data/test-diff-filter/test46-fn-return-qual-change-v1.o",
+ "--no-default-suppression",
+ "data/test-diff-filter/test46-fn-return-qual-change-report-0.txt",
+ "output/test-diff-filter/test46-fn-return-qual-change-report-0.txt",
+ },
+ {
+ "data/test-diff-filter/test47-filter-void-ptr-change-v0.o",
+ "data/test-diff-filter/test47-filter-void-ptr-change-v1.o",
+ "--no-default-suppression",
+ "data/test-diff-filter/test47-filter-void-ptr-change-report-0.txt",
+ "output/test-diff-filter/test47-filter-void-ptr-change-report-0.txt",
+ },
// This should be the last entry
{NULL, NULL, NULL, NULL, NULL}
};