[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Bug 18754 - Add a --no-added-symbols option to abidiff



Hi Dodji,

Thank you for the review. Based on it and our IRC convo, I amended the patch and :

I left show_all_{fns,vars} in. I changed the semantics as agreed. A "abidiff --no-added-syms" to mean show everything but added syms/vars and added unrefed symbols. With any of the --{deleted,changed}_{vars,fns} specified, it will have no further effect (the two tests attached should cover this). However, as we have found out, there is a bug :) , since the unreferenced symbols won't get affected by these options . There is another bug where the output header doesn't recount the suppressed amount but still properly suppresses "classes" of output, so that's minor :).

distcheck passes.

Thanks,

 Ondrej

On 23.12.2016 14:24, Dodji Seketeli wrote:
Hello Ondrej,

Ondrej Oprala <ondrej.oprala@gmail.com> a écrit:


diff --git a/tools/abidiff.cc b/tools/abidiff.cc
index fefcf7d..697d503 100644
--- a/tools/abidiff.cc
+++ b/tools/abidiff.cc
@@ -84,11 +84,10 @@ struct options
    bool			show_deleted_fns;
    bool			show_changed_fns;
    bool			show_added_fns;
-  bool			show_all_fns;
    bool			show_deleted_vars;
    bool			show_changed_vars;
    bool			show_added_vars;
-  bool			show_all_vars;
I think removing show_all_fns and show_all_vars changes the intended
behaviour of the program wrt optionslike --deleted-{fns,vars},
--changed-{fns,vars} etc.

Please keep reading my comments below.

[...]

+  bool			show_added_syms;
[...]

@@ -111,14 +110,13 @@ struct options
        show_relative_offset_changes(true),
        show_stats_only(),
        show_symtabs(),
-      show_deleted_fns(),
-      show_changed_fns(),
-      show_added_fns(),
-      show_all_fns(true),
-      show_deleted_vars(),
-      show_changed_vars(),
-      show_added_vars(),
-      show_all_vars(true),
+      show_deleted_fns(true),
+      show_changed_fns(true),
+      show_added_fns(true),
+      show_deleted_vars(true),
+      show_changed_vars(true),
+      show_added_vars(true),
+      show_added_syms(true),
This change also modifies the behaviour of abidiff, please keep reading.

[...]

      << " --no-unreferenced-symbols  do not display changes "
@@ -292,38 +291,32 @@ parse_command_line(int argc, char* argv[], options& opts)
        else if (!strcmp(argv[i], "--deleted-fns"))
  	{
  	  opts.show_deleted_fns = true;
-	  opts.show_all_fns = false;
-	  opts.show_all_vars = false;
  	}
So, the original intent is that by default, if no --deleted-{fns,vars},
--changed{fns,vars}, --added-{fns, vars} is given, then *all* added,
removed or deleted functions or variables are reported.

But then, if --deleted-fns is given, then *only* the deleted functions
are shown, and all of the other categories of changes are suppressed.  A
similar behaviour is followed for the other options that I talked about
about.  Hence the importance of the options::show_all_{fns,vars} data
members.

Thus, I believe this change modifies that behaviour, and so are the
similar changes that are below.

By the way, the behaviour is documented at
https://sourceware.org/libabigail/manual/abidiff.html for, e.g, the
--deleted-fns option.

By the way, the fact that no regression test did catch this issue is a
hint that I should probably add some tests to catch this.

So, in other words, I think the options::show_all_{fns,vars} should be
kept, and that we shouldn't change the logic related to those data
members.

What do you think?

Cheers,


>From 9b3f33d13f098a3eeb3c5b1dff25a36f174c3c84 Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <ondrej.oprala@gmail.com>
Date: Wed, 4 Jan 2017 00:03:08 +0100
Subject: [PATCH] Bug 18754 - Add the "--no-added-syms" option to abidiff

With this option, abidiff is now able to filter out added
symbols just like abipkgdiff is.

        * tools/abidiff.cc (struct options): Add show_added_syms and
        set it to true by default.
        (display_usage): Document the new options --no-added-syms. If
        this is the only suppression option specified, it is equivalent
        to specifying --show_{changed,deleted}_{fns,vars} as arguments
        to abidiff. If any of those options are specified before
        --no-added-syms, then it has no effect.
        (main): Parse the new option and set show_added_{fns,vars,syms}
        and show_all_{fns,vars} to false if --no-added-syms is
        specified.
        * tests/test-diff-filter.cc: Add a test for the new option.
        * tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt:
        Reference results for the new test.
        * tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt:
        Likewise.
        * tests/data/Makefile.am: Add the above test files to the list of
        test data.

Signed-off-by: Ondrej Oprala <ondrej.oprala@gmail.com>
---
 tests/data/Makefile.am                             |   2 +
 .../test35-pr18754-no-added-syms-report-0.txt      | 455 +++++++++++++++++++++
 .../test35-pr18754-no-added-syms-report-1.txt      | 110 +++++
 tests/test-diff-filter.cc                          |  14 +
 tools/abidiff.cc                                   |  30 ++
 5 files changed, 611 insertions(+)
 create mode 100644 tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt
 create mode 100644 tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt

diff --git a/tests/data/Makefile.am b/tests/data/Makefile.am
index 6884280..32ba8a4 100644
--- a/tests/data/Makefile.am
+++ b/tests/data/Makefile.am
@@ -563,6 +563,8 @@ test-diff-filter/test33-report-0.txt \
 test-diff-filter/test34-libjemalloc.so.2-gcc-6.1.0 \
 test-diff-filter/test34-libjemalloc.so.2-intel-16.0.3 \
 test-diff-filter/test34-report-0.txt \
+test-diff-filter/test35-pr18754-no-added-syms-report-0.txt \
+test-diff-filter/test35-pr18754-no-added-syms-report-1.txt \
 \
 test-diff-suppr/test0-type-suppr-v0.cc	\
 test-diff-suppr/test0-type-suppr-v1.cc	\
diff --git a/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt b/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt
new file mode 100644
index 0000000..792e92e
--- /dev/null
+++ b/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt
@@ -0,0 +1,455 @@
+Functions changes summary: 82 Removed, 7 Changed (13 filtered out), 0 Added functions (1081 filtered out)
+Variables changes summary: 47 Removed, 1 Changed, 0 Added variables (11 filtered out)
+Function symbols changes summary: 7 Removed, 0 Added (76 filtered out) function symbols not referenced by debug info
+Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info
+
+82 Removed functions:
+
+  'function void COI::fini()'
+  'function bool COI::init()'
+  'function void* DL_sym(void*, const char*, const char*)'
+  'method COIRESULT Engine::compute(const std::__cxx11::list<coibuffer*, std::allocator<coibuffer*> >&, void*, uint16_t, void*, uint16_t, uint32_t, const COIEVENT*, COIEVENT*)'
+  'method void FuncList::dump()'
+  'method void* FuncList::find_addr(const char*)'
+  'method const char* FuncList::find_name(void*)'
+  'method int64_t FuncList::max_name_length()'
+  'method MicEnvVar::VarValue* MicEnvVar::CardEnvVars::find_var(char*, int)'
+  'method MicEnvVar::CardEnvVars::~CardEnvVars(int)'
+  'method MicEnvVar::VarValue::~VarValue(int)'
+  'method void MicEnvVar::add_env_var(int, char*, int, char*)'
+  'method void MicEnvVar::analyze_env_var(char*)'
+  'method char** MicEnvVar::create_environ_for_card(int)'
+  'method MicEnvVar::CardEnvVars* MicEnvVar::get_card(int)'
+  'method MicEnvVarKind MicEnvVar::get_env_var_kind(char*, int*, char**, int*, char**)'
+  'method void MicEnvVar::mic_parse_env_var_list(int, char*)'
+  'method MicEnvVar::~MicEnvVar(int)'
+  'method bool MyoWrapper::LoadLibrary()'
+  'function void ORSL::init()'
+  'function void ORSL::release(int)'
+  'function bool ORSL::reserve(int)'
+  'function bool ORSL::try_reserve(int)'
+  'method bool OffloadDescriptor::alloc_ptr_data(PtrData*&, void*, int64_t, int64_t, int64_t, int)'
+  'method bool OffloadDescriptor::compute()'
+  'method bool OffloadDescriptor::find_ptr_data(PtrData*&, void*, int64_t, int64_t, bool)'
+  'method bool OffloadDescriptor::offload(const char*, bool, VarDesc*, VarDesc2*, int, void**, int, void**, int, void*)'
+  'method bool OffloadDescriptor::offload_finish()'
+  'method bool OffloadDescriptor::receive_pointer_data(bool)'
+  'method bool OffloadDescriptor::recieve_noncontiguous_pointer_data(int, char*, COIBUFFER, COIEVENT*)'
+  'method bool OffloadDescriptor::send_noncontiguous_pointer_data(int, PtrData*, PtrData*, COIEVENT*)'
+  'method bool OffloadDescriptor::send_pointer_data(bool)'
+  'method bool OffloadDescriptor::wait_dependencies(void**, int)'
+  'function void Offload_Report_Epilog(OffloadHostTimerData*)'
+  'function void Offload_Report_Prolog(OffloadHostTimerData*)'
+  'function void Offload_Timer_Print()'
+  'method void VarList::dump()'
+  'method void VarList::table_copy(void*, int64_t)'
+  'method void VarList::table_patch_names(int64_t)'
+  'method int64_t VarList::table_size(int64_t&)'
+  'function void __arr_data_offset_and_length(const arr_desc*, int64_t&, int64_t&)'
+  'function void __arr_desc_dump(const char*, const char*, const arr_desc*, bool)'
+  'function void __dump_bytes(int, void*, int)'
+  'function uint64_t __dv_data_length(const ArrDesc*)'
+  'function uint64_t __dv_data_length(const ArrDesc*, int64_t)'
+  'function void __dv_desc_dump(const char*, const ArrDesc*)'
+  'function bool __dv_is_allocated(const ArrDesc*)'
+  'function bool __dv_is_contiguous(const ArrDesc*)'
+  'function void __liboffload_error_support(error_types, ...)'
+  'function int __offload_init_library()'
+  'function void __offload_myoFini()'
+  'function bool __offload_parse_int_string(const char*, int64_t&)'
+  'function bool __offload_parse_size_string(const char*, uint64_t&)'
+  'function int64_t cean_get_transf_size(CeanReadRanges*)'
+  'function bool cean_ranges_match(CeanReadRanges*, CeanReadRanges*)'
+  'function void get_arr_desc_numbers(const arr_desc*, int64_t, int64_t&, int64_t&, int&, CeanReadRanges*&)'
+  'function int64_t get_el_value(char*, int64_t, int64_t)'
+  'function bool get_next_range(CeanReadRanges*, int64_t*)'
+  'function CeanReadRanges* init_read_ranges_arr_desc(const arr_desc*)'
+  'function CeanReadRanges* init_read_ranges_dv(const ArrDesc*)'
+  'function bool is_arr_desc_contiguous(const arr_desc*)'
+  'function arr_desc* make_arr_desc(void*, int64_t, int64_t, int64_t)'
+  'function const char* offload_get_message_str(int)'
+  'function int offload_offload_wrap(OFFLOAD, const char*, int, int, VarDesc*, VarDesc2*, int, void**, void**, int, void*)'
+  'function void offload_report_free_data(OffloadHostTimerData*)'
+  'function void offload_stage_print(int, int, ...)'
+  'function void offload_timer_fill_host_mic_num(OffloadHostTimerData*, int)'
+  'function void offload_timer_fill_host_rdata(OffloadHostTimerData*, uint64_t)'
+  'function void offload_timer_fill_host_sdata(OffloadHostTimerData*, uint64_t)'
+  'function void offload_timer_fill_target_data(OffloadHostTimerData*, void*)'
+  'function OffloadHostTimerData* offload_timer_init(const char*, int)'
+  'function void offload_timer_start(OffloadHostTimerData*, OffloadHostPhase)'
+  'function void offload_timer_stop(OffloadHostTimerData*, OffloadHostPhase)'
+  'function void print_range(const char*, uint64_t, uint64_t, int)'
+  'function const char* report_get_host_stage_str(int)'
+  'function const char* report_get_message_str(error_types)'
+  'function const char* report_get_target_stage_str(int)'
+  'function void std::__adjust_heap<VarList::BufEntry*, long int, VarList::BufEntry, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)> >(VarList::BufEntry*, long int, long int, VarList::BufEntry, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)>)'
+  'function void std::__insertion_sort<VarList::BufEntry*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)> >(VarList::BufEntry*, VarList::BufEntry*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)>)'
+  'function void std::__introsort_loop<VarList::BufEntry*, long int, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)> >(VarList::BufEntry*, VarList::BufEntry*, long int, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)>)'
+  'function void std::__unguarded_linear_insert<VarList::BufEntry*, __gnu_cxx::__ops::_Val_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)> >(VarList::BufEntry*, __gnu_cxx::__ops::_Val_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)>)'
+  'function void write_message(FILE*, int, __va_list_tag*)'
+
+7 functions with some indirect sub-type change:
+
+  [C]'function int ORSLRelease(const int, const int* restrict, const ORSLBusySet* restrict, const restrict ORSLTag)' has some indirect sub-type changes:
+    parameter 2 of type 'const int* restrict' changed:
+      entity changed from 'const int* restrict' to 'const int*'
+      type size hasn't changed
+    parameter 3 of type 'const ORSLBusySet* restrict' changed:
+      entity changed from 'const ORSLBusySet* restrict' to 'const ORSLBusySet*'
+      type size hasn't changed
+    parameter 4 of type 'const restrict ORSLTag' changed:
+      'const restrict ORSLTag' changed to 'const ORSLTag'
+
+  [C]'function int ORSLReservePartial(const ORSLPartialGranularity, const int, const int* restrict, ORSLBusySet* restrict, const restrict ORSLTag)' has some indirect sub-type changes:
+    parameter 3 of type 'const int* restrict' changed:
+      entity changed from 'const int* restrict' to 'const int*'
+      type size hasn't changed
+    parameter 4 of type 'ORSLBusySet* restrict' changed:
+      entity changed from 'ORSLBusySet* restrict' to 'ORSLBusySet*'
+      type size hasn't changed
+    parameter 5 of type 'const restrict ORSLTag' changed:
+      'const restrict ORSLTag' changed to 'const ORSLTag'
+
+  [C]'method void OffloadDescriptor::report_coi_error(error_types, COIRESULT)' has some indirect sub-type changes:
+    parameter 1 of type 'typedef error_types' has sub-type changes:
+      underlying type 'enum __anonymous_enum__' changed:
+        type size hasn't changed
+        21 enumerator insertions:
+          '__anonymous_enum__::c_process_set_cache_size' value '32'
+          '__anonymous_enum__::c_bad_ptr_mem_alloc' value '56'
+          '__anonymous_enum__::c_incorrect_affinity' value '69'
+          '__anonymous_enum__::c_cannot_set_affinity' value '70'
+          '__anonymous_enum__::c_report_myosupportsfeature' value '127'
+          '__anonymous_enum__::c_report_myosharedarenacreate' value '128'
+          '__anonymous_enum__::c_report_myosharedalignedarenamalloc' value '129'
+          '__anonymous_enum__::c_report_myosharedalignedarenafree' value '130'
+          '__anonymous_enum__::c_report_myoarenaacquire' value '131'
+          '__anonymous_enum__::c_report_myoarenarelease' value '132'
+          '__anonymous_enum__::c_in_with_preallocated' value '134'
+          '__anonymous_enum__::c_report_no_host_exe' value '135'
+          '__anonymous_enum__::c_report_path_buff_overflow' value '136'
+          '__anonymous_enum__::c_create_pipeline_for_stream' value '137'
+          '__anonymous_enum__::c_offload_no_stream' value '138'
+          '__anonymous_enum__::c_get_engine_info' value '139'
+          '__anonymous_enum__::c_clear_cpu_mask' value '140'
+          '__anonymous_enum__::c_set_cpu_mask' value '141'
+          '__anonymous_enum__::c_report_state_stream' value '142'
+          '__anonymous_enum__::c_report_stream' value '143'
+          '__anonymous_enum__::c_unload_library' value '144'
+
+        92 enumerator changes:
+          '__anonymous_enum__::c_process_get_func_handles' from value '32' to '33'
+          '__anonymous_enum__::c_process_wait_shutdown' from value '33' to '34'
+          '__anonymous_enum__::c_process_proxy_flush' from value '34' to '35'
+          '__anonymous_enum__::c_load_library' from value '35' to '36'
+          '__anonymous_enum__::c_pipeline_create' from value '36' to '37'
+          '__anonymous_enum__::c_pipeline_run_func' from value '37' to '38'
+          '__anonymous_enum__::c_pipeline_start_run_funcs' from value '38' to '39'
+          '__anonymous_enum__::c_buf_create' from value '39' to '40'
+          '__anonymous_enum__::c_buf_create_out_of_mem' from value '40' to '41'
+          '__anonymous_enum__::c_buf_create_from_mem' from value '41' to '42'
+          '__anonymous_enum__::c_buf_destroy' from value '42' to '43'
+          '__anonymous_enum__::c_buf_map' from value '43' to '44'
+          '__anonymous_enum__::c_buf_unmap' from value '44' to '45'
+          '__anonymous_enum__::c_buf_read' from value '45' to '46'
+          '__anonymous_enum__::c_buf_write' from value '46' to '47'
+          '__anonymous_enum__::c_buf_copy' from value '47' to '48'
+          '__anonymous_enum__::c_buf_get_address' from value '48' to '49'
+          '__anonymous_enum__::c_buf_add_ref' from value '49' to '50'
+          '__anonymous_enum__::c_buf_release_ref' from value '50' to '51'
+          '__anonymous_enum__::c_buf_set_state' from value '51' to '52'
+          '__anonymous_enum__::c_event_wait' from value '52' to '53'
+          '__anonymous_enum__::c_zero_or_neg_ptr_len' from value '53' to '54'
+          '__anonymous_enum__::c_zero_or_neg_transfer_size' from value '54' to '55'
+          '__anonymous_enum__::c_bad_ptr_mem_range' from value '55' to '57'
+          '__anonymous_enum__::c_different_src_and_dstn_sizes' from value '56' to '58'
+          '__anonymous_enum__::c_ranges_dont_match' from value '57' to '59'
+          '__anonymous_enum__::c_destination_is_over' from value '58' to '60'
+          '__anonymous_enum__::c_slice_of_noncont_array' from value '59' to '61'
+          '__anonymous_enum__::c_non_contiguous_dope_vector' from value '60' to '62'
+          '__anonymous_enum__::c_pointer_array_mismatch' from value '61' to '63'
+          '__anonymous_enum__::c_omp_invalid_device_num_env' from value '62' to '64'
+          '__anonymous_enum__::c_omp_invalid_device_num' from value '63' to '65'
+          '__anonymous_enum__::c_unknown_binary_type' from value '64' to '66'
+          '__anonymous_enum__::c_multiple_target_exes' from value '65' to '67'
+          '__anonymous_enum__::c_no_target_exe' from value '66' to '68'
+          '__anonymous_enum__::c_report_host' from value '67' to '71'
+          '__anonymous_enum__::c_report_target' from value '68' to '72'
+          '__anonymous_enum__::c_report_title' from value '69' to '73'
+          '__anonymous_enum__::c_report_from_file' from value '70' to '74'
+          '__anonymous_enum__::c_report_file' from value '71' to '75'
+          '__anonymous_enum__::c_report_line' from value '72' to '76'
+          '__anonymous_enum__::c_report_tag' from value '73' to '77'
+          '__anonymous_enum__::c_report_seconds' from value '74' to '78'
+          '__anonymous_enum__::c_report_bytes' from value '75' to '79'
+          '__anonymous_enum__::c_report_mic' from value '76' to '80'
+          '__anonymous_enum__::c_report_cpu_time' from value '77' to '81'
+          '__anonymous_enum__::c_report_cpu_to_mic_data' from value '78' to '82'
+          '__anonymous_enum__::c_report_mic_time' from value '79' to '83'
+          '__anonymous_enum__::c_report_mic_to_cpu_data' from value '80' to '84'
+          '__anonymous_enum__::c_report_unknown_timer_node' from value '81' to '85'
+          '__anonymous_enum__::c_report_unknown_trace_node' from value '82' to '86'
+          '__anonymous_enum__::c_report_offload' from value '83' to '87'
+          '__anonymous_enum__::c_report_w_tag' from value '84' to '88'
+          '__anonymous_enum__::c_report_state' from value '85' to '89'
+          '__anonymous_enum__::c_report_start' from value '86' to '90'
+          '__anonymous_enum__::c_report_init' from value '87' to '91'
+          '__anonymous_enum__::c_report_logical_card' from value '88' to '92'
+          '__anonymous_enum__::c_report_physical_card' from value '89' to '93'
+          '__anonymous_enum__::c_report_register' from value '90' to '94'
+          '__anonymous_enum__::c_report_init_func' from value '91' to '95'
+          '__anonymous_enum__::c_report_create_buf_host' from value '92' to '96'
+          '__anonymous_enum__::c_report_create_buf_mic' from value '93' to '97'
+          '__anonymous_enum__::c_report_send_pointer_data' from value '94' to '98'
+          '__anonymous_enum__::c_report_sent_pointer_data' from value '95' to '99'
+          '__anonymous_enum__::c_report_gather_copyin_data' from value '96' to '100'
+          '__anonymous_enum__::c_report_copyin_data' from value '97' to '101'
+          '__anonymous_enum__::c_report_state_signal' from value '98' to '102'
+          '__anonymous_enum__::c_report_signal' from value '99' to '103'
+          '__anonymous_enum__::c_report_wait' from value '100' to '104'
+          '__anonymous_enum__::c_report_compute' from value '101' to '105'
+          '__anonymous_enum__::c_report_receive_pointer_data' from value '102' to '106'
+          '__anonymous_enum__::c_report_received_pointer_data' from value '103' to '107'
+          '__anonymous_enum__::c_report_start_target_func' from value '104' to '108'
+          '__anonymous_enum__::c_report_var' from value '105' to '109'
+          '__anonymous_enum__::c_report_scatter_copyin_data' from value '106' to '110'
+          '__anonymous_enum__::c_report_gather_copyout_data' from value '107' to '111'
+          '__anonymous_enum__::c_report_scatter_copyout_data' from value '108' to '112'
+          '__anonymous_enum__::c_report_copyout_data' from value '109' to '113'
+          '__anonymous_enum__::c_report_unregister' from value '110' to '114'
+          '__anonymous_enum__::c_report_destroy' from value '111' to '115'
+          '__anonymous_enum__::c_report_myoinit' from value '112' to '116'
+          '__anonymous_enum__::c_report_myoregister' from value '113' to '117'
+          '__anonymous_enum__::c_report_myofini' from value '114' to '118'
+          '__anonymous_enum__::c_report_mic_myo_shared' from value '115' to '119'
+          '__anonymous_enum__::c_report_mic_myo_fptr' from value '116' to '120'
+          '__anonymous_enum__::c_report_myosharedmalloc' from value '117' to '121'
+          '__anonymous_enum__::c_report_myosharedfree' from value '118' to '122'
+          '__anonymous_enum__::c_report_myosharedalignedmalloc' from value '119' to '123'
+          '__anonymous_enum__::c_report_myosharedalignedfree' from value '120' to '124'
+          '__anonymous_enum__::c_report_myoacquire' from value '121' to '125'
+          '__anonymous_enum__::c_report_myorelease' from value '122' to '126'
+          '__anonymous_enum__::c_coipipe_max_number' from value '123' to '133'
+
+
+  [C]'method bool OffloadDescriptor::setup_descriptors(VarDesc*, VarDesc2*, int, int, void*)' has some indirect sub-type changes:
+    parameter 1 of type 'VarDesc*' has sub-type changes:
+      in pointed to type 'struct VarDesc':
+        type size hasn't changed
+        1 data member change:
+         type of 'VarDesc::__anonymous_union__ VarDesc::flags' changed:
+           type name changed from 'VarDesc::__anonymous_union__' to 'varDescFlags'
+           type size hasn't changed
+
+           1 data member change:
+            type of 'VarDesc::__anonymous_union__::__anonymous_struct__ ' changed:
+              type name changed from 'VarDesc::__anonymous_union__::__anonymous_struct__' to 'varDescFlags::__anonymous_struct__'
+              type size hasn't changed
+
+              6 data member insertions:
+                'uint32_t varDescFlags::__anonymous_struct__::pin', at offset 18 (in bits)
+                'uint32_t varDescFlags::__anonymous_struct__::always_delete', at offset 19 (in bits)
+                'uint32_t varDescFlags::__anonymous_struct__::always_copy', at offset 20 (in bits)
+                'uint32_t varDescFlags::__anonymous_struct__::is_noncont_dst', at offset 21 (in bits)
+                'uint32_t varDescFlags::__anonymous_struct__::is_noncont_src', at offset 22 (in bits)
+                'uint32_t varDescFlags::__anonymous_struct__::alloc_disp', at offset 23 (in bits)
+              no data member changes (8 filtered);
+
+           no data member change (1 filtered);
+
+
+  [C]'function int __offload_offload(OFFLOAD, const char*, int, int, VarDesc*, VarDesc2*, int, void**, void*, int, void*)' has some indirect sub-type changes:
+    parameter 1 of type 'typedef OFFLOAD' has sub-type changes:
+      underlying type 'OffloadDescriptor*' changed:
+        in pointed to type 'struct OffloadDescriptor':
+          type size changed from 2240 to 2368 bits
+          9 data member insertions:
+            'bool OffloadDescriptor::m_wait_all_devices', at offset 320 (in bits)
+            'uint32_t OffloadDescriptor::m_in_deps_allocated', at offset 1824 (in bits)
+            'uint32_t OffloadDescriptor::m_out_deps_allocated', at offset 1952 (in bits)
+            '_Offload_stream OffloadDescriptor::m_stream', at offset 1984 (in bits)
+            'bool OffloadDescriptor::m_initial_need_runfunction', at offset 2248 (in bits)
+            'bool OffloadDescriptor::m_out_with_preallocated', at offset 2256 (in bits)
+            'bool OffloadDescriptor::m_preallocated_alloc', at offset 2264 (in bits)
+            'bool OffloadDescriptor::m_traceback_called', at offset 2272 (in bits)
+            'OffloadDescriptor::OmpAsyncLastEventType OffloadDescriptor::m_omp_async_last_event_type', at offset 2304 (in bits)
+          8 data member changes (2 filtered):
+           type of 'Engine& OffloadDescriptor::m_device' changed:
+             in referenced type 'struct Engine':
+               type size changed from 2752 to 5504 bits
+               1 data member deletion:
+                 'mutex_t Engine::m_ptr_lock', at offset 1344 (in bits)
+
+               7 data member insertions:
+                 'PtrDataTable Engine::m_targetptr_set', at offset 1664 (in bits)
+                 'StreamMap Engine::m_stream_map', at offset 3072 (in bits)
+                 'mutex_t Engine::m_stream_lock', at offset 3456 (in bits)
+                 'int Engine::m_num_cores', at offset 3776 (in bits)
+                 'int Engine::m_num_threads', at offset 3808 (in bits)
+                 'std::bitset<1024ul> Engine::m_cpus', at offset 3840 (in bits)
+                 'DynLibList Engine::m_dyn_libs', at offset 4864 (in bits)
+               4 data member changes:
+                type of 'Engine::PtrSet Engine::m_ptr_set' changed:
+                  entity changed from 'typedef Engine::PtrSet' to compatible type 'class PtrDataTable'
+                    type name changed from 'std::set<PtrData, std::less<PtrData>, std::allocator<PtrData> >' to 'PtrDataTable'
+                    type size changed from 384 to 704 bits
+                    1 data member insertion:
+                      'mutex_t PtrDataTable::m_ptr_lock', at offset 384 (in bits)
+                    1 data member change:
+                     type of 'std::set<PtrData, std::less<PtrData>, std::allocator<PtrData> >::_Rep_type std::set<PtrData, std::less<PtrData>, std::allocator<PtrData> >::_M_t' changed:
+                       underlying type 'class std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >' changed:
+                         type name changed from 'std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >' to 'std::set<PtrData, std::less<PtrData>, std::allocator<PtrData> >'
+                         type size hasn't changed
+
+                         1 data member change:
+                          type of 'std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true> std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_M_impl' changed:
+                            entity changed from 'struct std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>' to compatible type 'typedef std::set<PtrData, std::less<PtrData>, std::allocator<PtrData> >::_Rep_type'
+                              type name changed from 'std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>' to 'std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >'
+                              type size hasn't changed
+
+                              1 base class deletion:
+                                class std::allocator<std::_Rb_tree_node<PtrData> >
+                              2 data member deletions:
+                                'std::_Rb_tree_node_base std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>::_M_header', at offset 64 (in bits)
+
+                                'std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::size_type std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>::_M_node_count', at offset 320 (in bits)
+
+                              1 data member change:
+                               type of 'std::less<PtrData> std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>::_M_key_compare' changed:
+                                 type name changed from 'std::less<PtrData>' to 'std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>'
+                                 type size changed from 8 to 384 bits
+                                 1 base class deletion:
+                                   struct std::binary_function<PtrData, PtrData, bool>
+                                 1 base class insertion:
+                                   class std::allocator<std::_Rb_tree_node<PtrData> >
+                                 3 data member insertions:
+                                   'std::less<PtrData> std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>::_M_key_compare', at offset 0 (in bits)
+                                   'std::_Rb_tree_node_base std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>::_M_header', at offset 64 (in bits)
+                                   'std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::size_type std::_Rb_tree<PtrData, PtrData, std::_Identity<PtrData>, std::less<PtrData>, std::allocator<PtrData> >::_Rb_tree_impl<std::less<PtrData>, true>::_M_node_count', at offset 320 (in bits)
+
+
+
+
+                'Engine::SignalMap Engine::m_signal_map' offset changed from 1664 to 2368 (in bits) (by +704 bits)
+                'mutex_t Engine::m_signal_lock' offset changed from 2048 to 2752 (in bits) (by +704 bits)
+                type of 'coifunction* Engine::m_funcs[6]' changed:
+                  type name changed from 'coifunction*[6]' to 'coifunction*[7]'
+                  array type size changed from 384 to 448 bits:
+                  array type subrange 1 changed length from 6 to 7
+                and offset changed from 2368 to 5056 (in bits) (by +2688 bits)
+
+           'bool OffloadDescriptor::m_is_mandatory' offset changed from 320 to 328 (in bits) (by +8 bits)
+           'const bool OffloadDescriptor::m_is_openmp' offset changed from 328 to 336 (in bits) (by +8 bits)
+           type of 'OffloadDescriptor::VarExtra* OffloadDescriptor::m_vars_extra' changed:
+             in pointed to type 'struct OffloadDescriptor::VarExtra':
+               type size changed from 576 to 640 bits
+               2 data member insertions:
+                 'void* OffloadDescriptor::VarExtra::alloc', at offset 320 (in bits)
+                 'OffloadDescriptor::OmpAsyncLastEventType OffloadDescriptor::VarExtra::omp_last_event_type', at offset 608 (in bits)
+               4 data member changes (3 filtered):
+                'CeanReadRanges* OffloadDescriptor::VarExtra::read_rng_src' offset changed from 320 to 384 (in bits) (by +64 bits)
+                type of 'CeanReadRanges* OffloadDescriptor::VarExtra::read_rng_dst' changed:
+                  in pointed to type 'struct CeanReadRanges':
+                    type size changed from 512 to 576 bits
+                    1 data member insertion:
+                      'Arr_Desc* CeanReadRanges::arr_desc', at offset 0 (in bits)
+                    7 data member changes:
+                     'void* CeanReadRanges::ptr' offset changed from 0 to 64 (in bits) (by +64 bits)
+                     'int64_t CeanReadRanges::current_number' offset changed from 64 to 128 (in bits) (by +64 bits)
+                     'int64_t CeanReadRanges::range_max_number' offset changed from 128 to 192 (in bits) (by +64 bits)
+                     'int64_t CeanReadRanges::range_size' offset changed from 192 to 256 (in bits) (by +64 bits)
+                     'int CeanReadRanges::last_noncont_ind' offset changed from 256 to 320 (in bits) (by +64 bits)
+                     'int64_t CeanReadRanges::init_offset' offset changed from 320 to 384 (in bits) (by +64 bits)
+                     'CeanReadDim CeanReadRanges::Dim[1]' offset changed from 384 to 448 (in bits) (by +64 bits)
+                and offset changed from 384 to 448 (in bits) (by +64 bits)
+                'int64_t OffloadDescriptor::VarExtra::ptr_arr_offset' offset changed from 448 to 512 (in bits) (by +64 bits)
+                'bool OffloadDescriptor::VarExtra::is_arr_ptr_el' offset changed from 512 to 576 (in bits) (by +64 bits)
+
+           'OffloadHostTimerData* OffloadDescriptor::m_timer_data' offset changed from 1984 to 2048 (in bits) (by +64 bits)
+           'uint64_t OffloadDescriptor::m_in_datalen' offset changed from 2048 to 2112 (in bits) (by +64 bits)
+           'uint64_t OffloadDescriptor::m_out_datalen' offset changed from 2112 to 2176 (in bits) (by +64 bits)
+           'bool OffloadDescriptor::m_need_runfunction' offset changed from 2176 to 2240 (in bits) (by +64 bits)
+
+  [C]'function void __offload_register_image(void*)' has some indirect sub-type changes:
+    return type changed:
+      type name changed from 'void' to 'bool'
+      type size changed from 0 to 8 bits
+
+  [C]'method void std::vector<const VarTable::Entry*, std::allocator<const VarTable::Entry*> >::_M_emplace_back_aux<const VarTable::Entry*>(const VarTable::Entry*&&)' has some indirect sub-type changes:
+    Please note that the symbol of this function is _ZNSt6vectorIPKN8VarTable5EntryESaIS3_EE19_M_emplace_back_auxIJS3_EEEvDpOT_
+     and it aliases symbol: _ZNSt6vectorIPKN8VarTable5EntryESaIS3_EE19_M_emplace_back_auxIIS3_EEEvDpOT_
+    parameter 1 of type 'const VarTable::Entry*&&' changed:
+      rvalue reference type 'const VarTable::Entry*&& became an lvalue reference type: 'const VarTable::Entry*&'
+      in referenced type 'const VarTable::Entry*':
+
+
+47 Removed variables:
+
+  'typedef COIRESULT (typedef COIBUFFER, typedef COIBUFFER, typedef uint64_t, typedef uint64_t, typedef uint64_t, typedef COI_COPY_TYPE, typedef uint32_t, const COIEVENT*, COIEVENT*)* COI::BufferCopy'
+  'typedef COIRESULT (typedef uint64_t, typedef COI_BUFFER_TYPE, typedef uint32_t, void*, typedef uint32_t, const COIPROCESS*, COIBUFFER*)* COI::BufferCreate'
+  'typedef COIRESULT (typedef uint64_t, typedef COI_BUFFER_TYPE, typedef uint32_t, void*, typedef uint32_t, const COIPROCESS*, COIBUFFER*)* COI::BufferCreateFromMemory'
+  'typedef COIRESULT (typedef COIBUFFER)* COI::BufferDestroy'
+  'typedef COIRESULT (typedef COIBUFFER, uint64_t*)* COI::BufferGetSinkAddress'
+  'typedef COIRESULT (typedef COIBUFFER, typedef uint64_t, typedef uint64_t, typedef COI_MAP_TYPE, typedef uint32_t, const COIEVENT*, COIEVENT*, COIMAPINSTANCE*, void**)* COI::BufferMap'
+  'typedef COIRESULT (typedef COIBUFFER, typedef uint64_t, void*, typedef uint64_t, typedef COI_COPY_TYPE, typedef uint32_t, const COIEVENT*, COIEVENT*)* COI::BufferRead'
+  'typedef COIRESULT (typedef COIBUFFER, typedef COIPROCESS, typedef COI_BUFFER_STATE, typedef COI_BUFFER_MOVE_FLAG, typedef uint32_t, const COIEVENT*, COIEVENT*)* COI::BufferSetState'
+  'typedef COIRESULT (typedef COIMAPINSTANCE, typedef uint32_t, const COIEVENT*, COIEVENT*)* COI::BufferUnmap'
+  'typedef COIRESULT (typedef COIBUFFER, typedef uint64_t, void*, typedef uint64_t, typedef COI_COPY_TYPE, typedef uint32_t, const COIEVENT*, COIEVENT*)* COI::BufferWrite'
+  'typedef COIRESULT (typedef COI_ISA_TYPE, uint32_t*)* COI::EngineGetCount'
+  'typedef COIRESULT (typedef COI_ISA_TYPE, typedef uint32_t, COIENGINE*)* COI::EngineGetHandle'
+  'typedef COIRESULT (typedef uint16_t, const COIEVENT*, typedef int32_t, typedef uint8_t, uint32_t*, uint32_t*)* COI::EventWait'
+  'typedef uint64_t ()* COI::PerfGetCycleFrequency'
+  'typedef COIRESULT (typedef COIPROCESS, uint64_t*, typedef uint32_t, COIPIPELINE*)* COI::PipelineCreate'
+  'typedef COIRESULT (typedef COIPIPELINE)* COI::PipelineDestroy'
+  'typedef COIRESULT (typedef COIPIPELINE, typedef COIFUNCTION, typedef uint32_t, const COIBUFFER*, const COI_ACCESS_FLAGS*, typedef uint32_t, const COIEVENT*, void*, typedef uint16_t, void*, typedef uint16_t, COIEVENT*)* COI::PipelineRunFunction'
+  'typedef COIRESULT (typedef COIENGINE, const char*, void*, typedef uint64_t, int, const char**, typedef uint8_t, const char**, typedef uint8_t, const char*, typedef uint64_t, const char*, const char*, typedef uint64_t, COIPROCESS*)* COI::ProcessCreateFromMemory'
+  'typedef COIRESULT (typedef COIPROCESS, typedef int32_t, typedef uint8_t, int8_t*, uint32_t*)* COI::ProcessDestroy'
+  'typedef COIRESULT (typedef COIPROCESS, typedef uint32_t, const char**, COIFUNCTION*)* COI::ProcessGetFunctionHandles'
+  'typedef COIRESULT (typedef COIPROCESS, void*, typedef uint64_t, const char*, const char*, const char*, typedef uint64_t, typedef uint32_t, COILIBRARY*)* COI::ProcessLoadLibraryFromMemory'
+  'typedef COIRESULT (typedef uint32_t, void**, const uint64_t*, const char**, const uint64_t*)* COI::ProcessRegisterLibraries'
+  'bool COI::is_available'
+  'static const int MicEnvVar::any_card'
+  'FuncList __offload_entries'
+  'FuncList __offload_funcs'
+  'OffloadInitType __offload_init_type'
+  'uint64_t __offload_use_2mb_buffers'
+  'VarList __offload_vars'
+  'int __omp_device_num'
+  'TargetImage* __target_exe'
+  'int console_enabled'
+  'uint64_t cpu_frequency'
+  'uint64_t mic_buffer_size'
+  'Engine* mic_engines'
+  'uint32_t mic_engines_total'
+  'MicEnvVar mic_env_vars'
+  'char* mic_library_path'
+  'char* mic_proxy_fs_root'
+  'bool mic_proxy_io'
+  'uint32_t mic_stack_size'
+  'pthread_key_t mic_thread_key'
+  'int offload_number'
+  'int offload_report_enabled'
+  'int offload_report_level'
+  'const char* prefix'
+  'int timer_enabled'
+
+1 Changed variable:
+
+  [C]'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]':
+    size of symbol (in bytes) changed from 48 to 56
+    type of variable changed:
+     type name changed from 'const char*[6]' to 'const char*[7]'
+     array type size changed from 384 to 448 bits:
+     array type subrange 1 changed length from 6 to 7
+
+
+7 Removed function symbols not referenced by debug info:
+
+  _ZN7VarListD1Ev
+  _ZN7VarListD2Ev, aliases _ZN7VarListD1Ev
+  _ZN8FuncListD1Ev
+  _ZN8FuncListD2Ev, aliases _ZN8FuncListD1Ev
+  _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED0Ev
+  _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED1Ev, aliases _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED2Ev
+  _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED2Ev
+
diff --git a/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt b/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt
new file mode 100644
index 0000000..d1bcc75
--- /dev/null
+++ b/tests/data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt
@@ -0,0 +1,110 @@
+Functions changes summary: 82 Removed, 7 Changed (13 filtered out), 0 Added functions (1081 filtered out)
+Variables changes summary: 0 Removed (47 filtered out), 1 Changed, 0 Added variables (11 filtered out)
+Function symbols changes summary: 7 Removed, 0 Added (76 filtered out) function symbols not referenced by debug info
+Variable symbols changes summary: 0 Removed, 0 Added variable symbol not referenced by debug info
+
+82 Removed functions:
+
+  'function void COI::fini()'
+  'function bool COI::init()'
+  'function void* DL_sym(void*, const char*, const char*)'
+  'method COIRESULT Engine::compute(const std::__cxx11::list<coibuffer*, std::allocator<coibuffer*> >&, void*, uint16_t, void*, uint16_t, uint32_t, const COIEVENT*, COIEVENT*)'
+  'method void FuncList::dump()'
+  'method void* FuncList::find_addr(const char*)'
+  'method const char* FuncList::find_name(void*)'
+  'method int64_t FuncList::max_name_length()'
+  'method MicEnvVar::VarValue* MicEnvVar::CardEnvVars::find_var(char*, int)'
+  'method MicEnvVar::CardEnvVars::~CardEnvVars(int)'
+  'method MicEnvVar::VarValue::~VarValue(int)'
+  'method void MicEnvVar::add_env_var(int, char*, int, char*)'
+  'method void MicEnvVar::analyze_env_var(char*)'
+  'method char** MicEnvVar::create_environ_for_card(int)'
+  'method MicEnvVar::CardEnvVars* MicEnvVar::get_card(int)'
+  'method MicEnvVarKind MicEnvVar::get_env_var_kind(char*, int*, char**, int*, char**)'
+  'method void MicEnvVar::mic_parse_env_var_list(int, char*)'
+  'method MicEnvVar::~MicEnvVar(int)'
+  'method bool MyoWrapper::LoadLibrary()'
+  'function void ORSL::init()'
+  'function void ORSL::release(int)'
+  'function bool ORSL::reserve(int)'
+  'function bool ORSL::try_reserve(int)'
+  'method bool OffloadDescriptor::alloc_ptr_data(PtrData*&, void*, int64_t, int64_t, int64_t, int)'
+  'method bool OffloadDescriptor::compute()'
+  'method bool OffloadDescriptor::find_ptr_data(PtrData*&, void*, int64_t, int64_t, bool)'
+  'method bool OffloadDescriptor::offload(const char*, bool, VarDesc*, VarDesc2*, int, void**, int, void**, int, void*)'
+  'method bool OffloadDescriptor::offload_finish()'
+  'method bool OffloadDescriptor::receive_pointer_data(bool)'
+  'method bool OffloadDescriptor::recieve_noncontiguous_pointer_data(int, char*, COIBUFFER, COIEVENT*)'
+  'method bool OffloadDescriptor::send_noncontiguous_pointer_data(int, PtrData*, PtrData*, COIEVENT*)'
+  'method bool OffloadDescriptor::send_pointer_data(bool)'
+  'method bool OffloadDescriptor::wait_dependencies(void**, int)'
+  'function void Offload_Report_Epilog(OffloadHostTimerData*)'
+  'function void Offload_Report_Prolog(OffloadHostTimerData*)'
+  'function void Offload_Timer_Print()'
+  'method void VarList::dump()'
+  'method void VarList::table_copy(void*, int64_t)'
+  'method void VarList::table_patch_names(int64_t)'
+  'method int64_t VarList::table_size(int64_t&)'
+  'function void __arr_data_offset_and_length(const arr_desc*, int64_t&, int64_t&)'
+  'function void __arr_desc_dump(const char*, const char*, const arr_desc*, bool)'
+  'function void __dump_bytes(int, void*, int)'
+  'function uint64_t __dv_data_length(const ArrDesc*)'
+  'function uint64_t __dv_data_length(const ArrDesc*, int64_t)'
+  'function void __dv_desc_dump(const char*, const ArrDesc*)'
+  'function bool __dv_is_allocated(const ArrDesc*)'
+  'function bool __dv_is_contiguous(const ArrDesc*)'
+  'function void __liboffload_error_support(error_types, ...)'
+  'function int __offload_init_library()'
+  'function void __offload_myoFini()'
+  'function bool __offload_parse_int_string(const char*, int64_t&)'
+  'function bool __offload_parse_size_string(const char*, uint64_t&)'
+  'function int64_t cean_get_transf_size(CeanReadRanges*)'
+  'function bool cean_ranges_match(CeanReadRanges*, CeanReadRanges*)'
+  'function void get_arr_desc_numbers(const arr_desc*, int64_t, int64_t&, int64_t&, int&, CeanReadRanges*&)'
+  'function int64_t get_el_value(char*, int64_t, int64_t)'
+  'function bool get_next_range(CeanReadRanges*, int64_t*)'
+  'function CeanReadRanges* init_read_ranges_arr_desc(const arr_desc*)'
+  'function CeanReadRanges* init_read_ranges_dv(const ArrDesc*)'
+  'function bool is_arr_desc_contiguous(const arr_desc*)'
+  'function arr_desc* make_arr_desc(void*, int64_t, int64_t, int64_t)'
+  'function const char* offload_get_message_str(int)'
+  'function int offload_offload_wrap(OFFLOAD, const char*, int, int, VarDesc*, VarDesc2*, int, void**, void**, int, void*)'
+  'function void offload_report_free_data(OffloadHostTimerData*)'
+  'function void offload_stage_print(int, int, ...)'
+  'function void offload_timer_fill_host_mic_num(OffloadHostTimerData*, int)'
+  'function void offload_timer_fill_host_rdata(OffloadHostTimerData*, uint64_t)'
+  'function void offload_timer_fill_host_sdata(OffloadHostTimerData*, uint64_t)'
+  'function void offload_timer_fill_target_data(OffloadHostTimerData*, void*)'
+  'function OffloadHostTimerData* offload_timer_init(const char*, int)'
+  'function void offload_timer_start(OffloadHostTimerData*, OffloadHostPhase)'
+  'function void offload_timer_stop(OffloadHostTimerData*, OffloadHostPhase)'
+  'function void print_range(const char*, uint64_t, uint64_t, int)'
+  'function const char* report_get_host_stage_str(int)'
+  'function const char* report_get_message_str(error_types)'
+  'function const char* report_get_target_stage_str(int)'
+  'function void std::__adjust_heap<VarList::BufEntry*, long int, VarList::BufEntry, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)> >(VarList::BufEntry*, long int, long int, VarList::BufEntry, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)>)'
+  'function void std::__insertion_sort<VarList::BufEntry*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)> >(VarList::BufEntry*, VarList::BufEntry*, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)>)'
+  'function void std::__introsort_loop<VarList::BufEntry*, long int, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)> >(VarList::BufEntry*, VarList::BufEntry*, long int, __gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)>)'
+  'function void std::__unguarded_linear_insert<VarList::BufEntry*, __gnu_cxx::__ops::_Val_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)> >(VarList::BufEntry*, __gnu_cxx::__ops::_Val_comp_iter<bool (*)(const VarList::BufEntry&, const VarList::BufEntry&)>)'
+  'function void write_message(FILE*, int, __va_list_tag*)'
+
+1 Changed variable:
+
+  [C]'static const char* Engine::m_func_names[6]' was changed to 'static const char* Engine::m_func_names[7]':
+    size of symbol (in bytes) changed from 48 to 56
+    type of variable changed:
+     type name changed from 'const char*[6]' to 'const char*[7]'
+     array type size changed from 384 to 448 bits:
+     array type subrange 1 changed length from 6 to 7
+
+
+7 Removed function symbols not referenced by debug info:
+
+  _ZN7VarListD1Ev
+  _ZN7VarListD2Ev, aliases _ZN7VarListD1Ev
+  _ZN8FuncListD1Ev
+  _ZN8FuncListD2Ev, aliases _ZN8FuncListD1Ev
+  _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED0Ev
+  _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED1Ev, aliases _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED2Ev
+  _ZNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEED2Ev
+
diff --git a/tests/test-diff-filter.cc b/tests/test-diff-filter.cc
index d2b67cf..94eb88f 100644
--- a/tests/test-diff-filter.cc
+++ b/tests/test-diff-filter.cc
@@ -422,6 +422,20 @@ InOutSpec in_out_specs[] =
     "data/test-diff-filter/test34-report-0.txt",
     "output/test-diff-filter/test34-report-0.txt",
   },
+  {
+    "data/test-diff-filter/test30-pr18904-rvalueref-liba.so",
+    "data/test-diff-filter/test30-pr18904-rvalueref-libb.so",
+    "--no-default-suppression --no-linkage-name --no-show-locs --no-redundant --no-added-syms",
+    "data/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt",
+    "output/test-diff-filter/test35-pr18754-no-added-syms-report-0.txt",
+  },
+  {
+    "data/test-diff-filter/test30-pr18904-rvalueref-liba.so",
+    "data/test-diff-filter/test30-pr18904-rvalueref-libb.so",
+    "--no-default-suppression --no-linkage-name --no-show-locs --no-redundant --deleted-fns --changed-vars --no-added-syms",
+    "data/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt",
+    "output/test-diff-filter/test35-pr18754-no-added-syms-report-1.txt",
+  },
   // This should be the last entry
   {NULL, NULL, NULL, NULL, NULL}
 };
diff --git a/tools/abidiff.cc b/tools/abidiff.cc
index fefcf7d..a822f27 100644
--- a/tools/abidiff.cc
+++ b/tools/abidiff.cc
@@ -84,6 +84,7 @@ struct options
   bool			show_deleted_fns;
   bool			show_changed_fns;
   bool			show_added_fns;
+  bool			show_added_syms;
   bool			show_all_fns;
   bool			show_deleted_vars;
   bool			show_changed_vars;
@@ -114,6 +115,7 @@ struct options
       show_deleted_fns(),
       show_changed_fns(),
       show_added_fns(),
+      show_added_syms(true),
       show_all_fns(true),
       show_deleted_vars(),
       show_changed_vars(),
@@ -156,6 +158,7 @@ display_usage(const string& prog_name, ostream& out)
     << " --deleted-vars  display deleted global public variables\n"
     << " --changed-vars  display changed global public variables\n"
     << " --added-vars  display added global public variables\n"
+    << " --no-added-syms  do not display added functions or variables\n"
     << " --no-linkage-name  do not display linkage names of "
     "added/removed/changed\n"
     << " --no-unreferenced-symbols  do not display changes "
@@ -325,6 +328,31 @@ parse_command_line(int argc, char* argv[], options& opts)
 	  opts.show_all_fns = false;
 	  opts.show_all_vars = false;
 	}
+      else if (!strcmp(argv[i], "--no-added-syms"))
+	{
+	  opts.show_added_syms = false;
+	  opts.show_added_vars = false;
+	  opts.show_added_fns = false;
+
+	  // If any of the {changed,deleted}_{vars,fns}
+	  // is already specified, --no-added-syms has
+	  // no further effect. If it is the only
+	  // option specified (as of the time of parsing it),
+	  // it shall mean "show everything, except added vars, fns
+	  // and unreferenced symbols.
+	  if (!(opts.show_changed_fns || opts.show_changed_vars ||
+	      opts.show_deleted_fns || opts.show_deleted_vars))
+	    {
+	      opts.show_changed_fns = true;
+	      opts.show_changed_vars = true;
+
+	      opts.show_deleted_vars = true;
+	      opts.show_deleted_fns = true;
+	    }
+
+	  opts.show_all_fns = false;
+	  opts.show_all_vars = false;
+	}
       else if (!strcmp(argv[i], "--no-linkage-name"))
 	opts.show_linkage_names = false;
       else if (!strcmp(argv[i], "--no-unreferenced-symbols"))
@@ -525,6 +553,8 @@ set_diff_context_from_opts(diff_context_sptr ctxt,
   ctxt->show_redundant_changes(opts.show_redundant_changes);
   ctxt->show_symbols_unreferenced_by_debug_info
     (opts.show_symbols_not_referenced_by_debug_info);
+  ctxt->show_added_symbols_unreferenced_by_debug_info
+    (opts.show_symbols_not_referenced_by_debug_info && opts.show_added_syms);
 
   if (!opts.show_harmless_changes)
       ctxt->switch_categories_off
-- 
2.7.4