)]}'
{
  "commit": "c09ebee0d3ae9148e33aa861cbd857bf2d4100ba",
  "tree": "7683c5c2e9c730d421c835eb56b2192eb480e41a",
  "parents": [
    "a85f1da7a82fef8c74737089b5845bfd2d97996c"
  ],
  "author": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Wed Oct 29 19:39:44 2025 +0000"
  },
  "committer": {
    "name": "Andrew Burgess",
    "email": "aburgess@redhat.com",
    "time": "Thu Nov 13 14:50:18 2025 +0000"
  },
  "message": "gdb: symbol_search objects of different types are not the same\n\nConsider the C construct:\n\n  typedef struct foo\n  {\n    int a;\n    int b;\n  } foo;\n\nGDB will see two types here, \u0027struct foo\u0027 and the typedef \u0027foo\u0027.\nHowever, if we use \u0027info types foo\u0027 we will see this:\n\n  File test.c:\n  18:\tstruct foo;\n\nAt least that\u0027s what I see with current HEAD of master.  However, it\nis really just luck that we see the \u0027struct\u0027 here.  See more below.\n\nWhen searching for symbols matching \u0027foo\u0027 GDB ends up in the function\nglobal_symbol_searcher::add_matching_symbols, where we consider all\npossible matching symbols.  This will include the \u0027struct foo\u0027 and the\ntypedef \u0027foo\u0027.  However, before a new symbols is added to the results,\nwe attempt to remove duplicates with this code:\n\n  /* Match, insert if not already in the results.  */\n  symbol_search ss (block, sym);\n  if (result_set-\u003efind (ss) \u003d\u003d result_set-\u003eend ())\n    result_set-\u003einsert (ss);\n\nIf a symbol is already present in result_set then it will not be added\na second time.\n\nThe symbol_search equality check is done using the function\nsymbol_search::compare_search_syms, this function does a number of\nchecks, but at the end, any two symbols that are in the same block\nwithin the same file, with the same name, are considered the same,\neven if the types of those symbols are different.\n\nThis makes sense in most cases, it usually wouldn\u0027t make sense to have\ntwo symbols within a single block with different types.  But the\n\u0027struct foo\u0027 and typedef \u0027foo\u0027 case is a bit of a strange one.  Within\nDWARF and GDB we consider both of these as just types.  But in C\ntypes and structure names live in different namespaces, and so we can\nhave both in the same block.  I don\u0027t think that GDB should consider\nthese two as the same, especially if we consider something really\nill-advised like this:\n\n  struct foo\n  {\n    int a;\n    int b;\n  };\n\n  typedef int foo;\n\nThis is perfectly valid C code, \u0027struct foo\u0027 and the typedef \u0027foo\u0027 are\nin different namespaces, and can be used within the same block.  But\nplease, never write C code like this.\n\nGiven the above, I think, when asked about \u0027foo\u0027, GDB should, report\nboth \u0027struct foo\u0027 and the typedef \u0027foo\u0027.\n\nTo do this I propose extending symbol_search::compare_search_syms such\nthat if two symbol_search objects are in the same block, within the\nsame file, and they have the same name, then if just one of them is a\ntypedef, the two objects will not be considered equal.  The results\nwill be sorted by line number if the line numbers are different, or,\nif the line numbers are the same, the non-typedef will be sorted\nfirst.  This means that for something like this:\n\n  typedef struct foo { int a; } foo;\n\nWe\u0027ll get an \u0027info types foo\u0027 result like:\n\n  File test.c:\n  18:\tstruct foo;\n  18:\ttypedef struct foo foo;\n\nI mentioned earlier that it is really just luck that we see \u0027struct\nfoo\u0027.  I ran into this problem while working on another patch.  When\ntesting with the \u0027debug-types\u0027 board file I was seeing the typedef\nbeing reported rather than the struct.  In \"normal\" DWARF given the\n\u0027typedef struct foo { ...} foo;\u0027 construct, the compiler will usually\nemit the struct definition first, and then the typedef definition.  So\nwhen GDB parses the DWARF it sees the struct first.  It is the typedef\nthat becomes the duplicate which is not added to the results list.\n\nBut with the \u0027debug-types\u0027 board the compiler moves the struct\ndefinition out to the .debug_types section.  And GDB now parses the CU\ncontaining the typedef first, and then expands the structure\ndefinition from the separate section afterwards.  As a result, it is\nthe structure that is now considered the duplicate, and the typedef is\nthe result that gets reported.\n\nI think this is yet another motivation for this patch.  Changes like\nthis (the use of .debug_types section) shouldn\u0027t impact what results\nGDB shows to the user.\n\nThere is an interesting update to the gdb.base/info-types.exp.tcl test\nscript.  In this case the C results only needed to change to include\nthe typedef.  The C++ results already included both the struct and the\ntypedef in the expected results.  The reason for this is that C places\nboth the struct baz_t and the typedef for baz_t into the global block,\nwhile C++ places the struct in the global block, and the typedef into\nthe static block.  I have no idea why there\u0027s a difference in the\nplacement, but I\u0027m choosing to believe the difference is correct.  But\nthis explains why only the C results needed to change.  If anything\nthis (I think) is yet another justification for this change; having C\nnot show the typedef in this case seems weird when the same source\ncode compiled as C++ does show the typedef.\n\nApproved-By: Tom Tromey \u003ctom@tromey.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "7117e0d7feae70ec38ac3f8b3f653fc41c5fe899",
      "old_mode": 33188,
      "old_path": "gdb/symtab.c",
      "new_id": "1d9a06a52f3a6b96ec497dd21e5ff8dbeb31398f",
      "new_mode": 33188,
      "new_path": "gdb/symtab.c"
    },
    {
      "type": "modify",
      "old_id": "c05837b246e2e6b6be6178b0d86e4af772f5343b",
      "old_mode": 33188,
      "old_path": "gdb/testsuite/gdb.base/info-types.exp.tcl",
      "new_id": "a609ae4c10a9c0af3630d61a737b4596a2f96021",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/info-types.exp.tcl"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "703d7f375ddd3e2f01233b7c4f669d405a638c7d",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/type-and-typedef.c"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1401ee8063caac75280e3cb4082b04b7ded4b614",
      "new_mode": 33188,
      "new_path": "gdb/testsuite/gdb.base/type-and-typedef.exp"
    }
  ]
}
