return "";
}
+/* GCC might generate a struct/class without DW_AT_declaration,
+ but that only contains members which have DW_AT_declaration
+ set. We aren't interested in those. PR14434 (GCC bug #54181). */
+static bool
+has_only_decl_members (Dwarf_Die *die)
+{
+ Dwarf_Die child;
+ if (dwarf_child(die, &child) != 0)
+ return false; /* no members */
+
+ do
+ {
+ if (! dwarf_hasattr(&child, DW_AT_declaration))
+ return false; /* real member found. */
+ int tag = dwarf_tag(&child);
+ if ((tag == DW_TAG_namespace
+ || tag == DW_TAG_structure_type
+ || tag == DW_TAG_class_type)
+ && ! has_only_decl_members (&child))
+ return false; /* real grand child member found. */
+ }
+ while (dwarf_siblingof(&child, &child) == 0);
+
+ return true; /* Tried all children and grandchildren. */
+}
+
int
dwflpp::global_alias_caching_callback(Dwarf_Die *die, bool has_inner_types,
const string& prefix, void *arg)
cu_type_cache_t *cache = static_cast<cu_type_cache_t*>(arg);
const char *name = dwarf_diename(die);
- if (!name || dwarf_hasattr(die, DW_AT_declaration))
+ if (!name || dwarf_hasattr(die, DW_AT_declaration)
+ || has_only_decl_members(die))
return DWARF_CB_OK;
int tag = dwarf_tag(die);
--- /dev/null
+set test "partial-class-type"
+
+# PR14434 dwflpp sometimes caches incomplete class_type
+
+proc error_handler { res message } {
+ global verbose test
+ if { $res == 0 } {
+ verbose $message 2
+ fail "$test $message"
+ return 1
+ } else {
+ pass "$test $message"
+ return 0
+ }
+}
+
+set srcpath "$srcdir/$subdir"
+set res [target_compile $srcpath/partial-class-type-heap.cxx "partial-class-type-heap.o" object "additional_flags=-g additional_flags=-O2"]
+if { [error_handler [expr {$res==""}] "partial-class-type-heap.cxx"] } { return }
+
+set res [target_compile $srcpath/partial-class-type-main.cxx "partial-class-type-main.o" object "additional_flags=-g additional_flags=-O2"]
+if { [error_handler [expr {$res==""}] "partial-class-type-main.cxx"] } { return }
+
+set res [target_compile "partial-class-type-main.o partial-class-type-heap.o" "partial-class-type" executable "additional_flags=-g additional_flags=-O2"]
+if { [error_handler [expr {$res==""}] "partial-class-type"] } { return }
+
+set script {"probe process(\"./partial-class-type\").function(\"main\") { printf(\"_size member offset: %d\\n\", &@cast(0, \"Heap\")->_size); }"}
+
+# Try compiling a couple of times, to make sure we always pick the right DIE.
+# See PR14434 for the non-determinism.
+for {set i 0} {$i < 7} {incr i} {
+ stap_compile $test-$i 1 $script -p2
+}