GP-6394 - Gnu Demangler - Added legacy support for the static qualifier

This commit is contained in:
dragonmacher
2026-02-03 18:10:10 -05:00
parent a945505ee0
commit 5dd4b43b13
3 changed files with 75 additions and 17 deletions

View File

@@ -41,7 +41,9 @@ Update January 2026
Fixed a bug seen in older mangled symbols that use an 'F' character for functions. We added a Fixed a bug seen in older mangled symbols that use an 'F' character for functions. We added a
function to handle this case, isQualifiersAndFunc(). This function called from inside the function to handle this case, isQualifiersAndFunc(). This function called from inside the
demangle_signature() function. demangle_signature() function. The output also makes use of the added TYPE_QUAL_STATIC define.
cp-demangle.c * cp-demangle.c *

View File

@@ -463,6 +463,7 @@ static int snarf_numeric_literal (const char **, string *);
#define TYPE_QUAL_CONST 0x1 #define TYPE_QUAL_CONST 0x1
#define TYPE_QUAL_VOLATILE 0x2 #define TYPE_QUAL_VOLATILE 0x2
#define TYPE_QUAL_RESTRICT 0x4 #define TYPE_QUAL_RESTRICT 0x4
#define TYPE_QUAL_STATIC 0x8
static int code_for_qualifier (int); static int code_for_qualifier (int);
@@ -573,6 +574,9 @@ code_for_qualifier (int c)
case 'C': case 'C':
return TYPE_QUAL_CONST; return TYPE_QUAL_CONST;
case 'S':
return TYPE_QUAL_STATIC;
case 'V': case 'V':
return TYPE_QUAL_VOLATILE; return TYPE_QUAL_VOLATILE;
@@ -601,22 +605,34 @@ qualifier_string (int type_quals)
case TYPE_QUAL_CONST: case TYPE_QUAL_CONST:
return "const"; return "const";
case TYPE_QUAL_STATIC:
return "static";
case TYPE_QUAL_VOLATILE: case TYPE_QUAL_VOLATILE:
return "volatile"; return "volatile";
case TYPE_QUAL_RESTRICT: case TYPE_QUAL_RESTRICT:
return "__restrict"; return "__restrict";
case TYPE_QUAL_CONST | TYPE_QUAL_STATIC:
return "const static";
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE: case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE:
return "const volatile"; return "const volatile";
case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT: case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT:
return "const __restrict"; return "const __restrict";
case TYPE_QUAL_STATIC | TYPE_QUAL_VOLATILE:
return "static volatile";
case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
return "volatile __restrict"; return "volatile __restrict";
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: case TYPE_QUAL_CONST | TYPE_QUAL_STATIC | TYPE_QUAL_VOLATILE:
return "static const volatile";
case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT:
return "const volatile __restrict"; return "const volatile __restrict";
default: default:
@@ -819,33 +835,33 @@ cplus_demangle_name_to_style (const char *name)
return unknown_demangling; return unknown_demangling;
} }
/* Scans to see if mangled is a set of optional qualifiers and a function. */ /* Scans to see if mangled is a set of optional qualifiers and a function. */
static int /* bool */ static int /* bool */
isQualifiersAndFunc(const char *mangled) isQualifiersAndFunc(const char *mangled)
{ {
int i = 0; int i = 0;
while (1) while (1)
{ {
switch (mangled[i++]) switch (mangled[i++])
{ {
case 'C': case 'C':
case 'V': case 'S':
case 'u': case 'V':
/*qualifier*/ case 'u':
break; /* qualifier */
case 'F': break;
/* function */ case 'F':
return 1; /* function */
default: return 1;
/* anything else is not a qualifier or function */ default:
return 0; /* anything else is not a qualifier or function */
return 0;
} }
} }
} }
/* char *cplus_demangle (const char *mangled, int options) /* char *cplus_demangle (const char *mangled, int options)
If MANGLED is a mangled function name produced by GNU C++, then If MANGLED is a mangled function name produced by GNU C++, then

View File

@@ -198,6 +198,46 @@ public class GnuDemanglerParserTest extends AbstractGenericTest {
assertEquals("undefined Foo::foo(unsigned char,unsigned char)", object.getSignature()); assertEquals("undefined Foo::foo(unsigned char,unsigned char)", object.getSignature());
} }
@Test
public void testLegacy_DemangedFunctionCharacter_Qualifiers() throws Exception {
// This is only supported in the older v24 demangler. The 'F' character was not being
// correctly demangled along with some qualifier characters. The native demangler was
// updated to fix this.
process = GnuDemanglerNativeProcess
.getDemanglerNativeProcess(GnuDemanglerOptions.GNU_DEMANGLER_V2_24);
//@formatter:off
assertLegacyDemangled("foo__03FooCF",
"Foo::foo(void) const",
"undefined Foo::foo(void)");
assertLegacyDemangled("foo__03FooSF",
"Foo::foo(void) static",
"undefined Foo::foo(void)");
assertLegacyDemangled("foo__03FooSFUcT1",
"Foo::foo(unsigned char, unsigned char) static",
"undefined Foo::foo(unsigned char,unsigned char)");
assertLegacyDemangled("foo__03FooSCFUcT1",
"Foo::foo(unsigned char, unsigned char) static const",
"undefined Foo::foo(unsigned char,unsigned char)");
//@formatter:on
}
private void assertLegacyDemangled(String mangled, String demangledExpected,
String signatureExpected) throws Exception {
String demangledActual = process.demangle(mangled);
assertEquals(demangledExpected, demangledActual);
DemangledObject object = parser.parse(mangled, demangledExpected);
assertType(object, DemangledFunction.class);
assertEquals(signatureExpected, object.getSignature());
}
@Test @Test
public void testTemplates_TemplatedType() throws Exception { public void testTemplates_TemplatedType() throws Exception {
String mangled = String mangled =