diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Demangle/MicrosoftDemangle.cpp | 72 | ||||
-rw-r--r-- | llvm/test/Demangle/ms-mangle.test | 18 |
2 files changed, 56 insertions, 34 deletions
diff --git a/llvm/lib/Demangle/MicrosoftDemangle.cpp b/llvm/lib/Demangle/MicrosoftDemangle.cpp index d9aed6499fb..cab662f98e8 100644 --- a/llvm/lib/Demangle/MicrosoftDemangle.cpp +++ b/llvm/lib/Demangle/MicrosoftDemangle.cpp @@ -195,7 +195,7 @@ enum class PrimTy : uint8_t { }; // Function classes -enum FuncClass : uint8_t { +enum FuncClass : uint16_t { Public = 1 << 0, Protected = 1 << 1, Private = 1 << 2, @@ -203,6 +203,8 @@ enum FuncClass : uint8_t { Static = 1 << 4, Virtual = 1 << 5, Far = 1 << 6, + ExternC = 1 << 7, + NoPrototype = 1 << 8, }; enum NameBackrefBehavior : uint8_t { @@ -833,6 +835,9 @@ void FunctionType::outputPre(OutputStream &OS, NameResolver &Resolver) { if (FunctionClass & Static) OS << "static "; } + if (FunctionClass & ExternC) { + OS << "extern \"C\" "; + } if (ReturnType) { Type::outputPre(OS, *ReturnType, Resolver); @@ -847,6 +852,10 @@ void FunctionType::outputPre(OutputStream &OS, NameResolver &Resolver) { } void FunctionType::outputPost(OutputStream &OS, NameResolver &Resolver) { + // extern "C" functions don't have a prototype. + if (FunctionClass & NoPrototype) + return; + OS << "("; outputParameterList(OS, Params, Resolver); OS << ")"; @@ -1059,7 +1068,9 @@ Symbol *Demangler::parse(StringView &MangledName) { if (Error) return nullptr; // Read a variable. - if (startsWithDigit(MangledName)) { + if (startsWithDigit(MangledName) && !MangledName.startsWith('9')) { + // 9 is a special marker for an extern "C" function with + // no prototype. S->Category = SymbolCategory::Variable; S->SymbolType = demangleVariableEncoding(MangledName); } else { @@ -1517,47 +1528,53 @@ FuncClass Demangler::demangleFunctionClass(StringView &MangledName) { SwapAndRestore<StringView> RestoreOnError(MangledName, MangledName); RestoreOnError.shouldRestore(false); + FuncClass TempFlags = FuncClass(0); + if (MangledName.consumeFront("$$J0")) + TempFlags = ExternC; + switch (MangledName.popFront()) { + case '9': + return FuncClass(TempFlags | ExternC | NoPrototype); case 'A': return Private; case 'B': - return FuncClass(Private | Far); + return FuncClass(TempFlags | Private | Far); case 'C': - return FuncClass(Private | Static); + return FuncClass(TempFlags | Private | Static); case 'D': - return FuncClass(Private | Static); + return FuncClass(TempFlags | Private | Static); case 'E': - return FuncClass(Private | Virtual); + return FuncClass(TempFlags | Private | Virtual); case 'F': - return FuncClass(Private | Virtual); + return FuncClass(TempFlags | Private | Virtual); case 'I': - return Protected; + return FuncClass(TempFlags | Protected); case 'J': - return FuncClass(Protected | Far); + return FuncClass(TempFlags | Protected | Far); case 'K': - return FuncClass(Protected | Static); + return FuncClass(TempFlags | Protected | Static); case 'L': - return FuncClass(Protected | Static | Far); + return FuncClass(TempFlags | Protected | Static | Far); case 'M': - return FuncClass(Protected | Virtual); + return FuncClass(TempFlags | Protected | Virtual); case 'N': - return FuncClass(Protected | Virtual | Far); + return FuncClass(TempFlags | Protected | Virtual | Far); case 'Q': - return Public; + return FuncClass(TempFlags | Public); case 'R': - return FuncClass(Public | Far); + return FuncClass(TempFlags | Public | Far); case 'S': - return FuncClass(Public | Static); + return FuncClass(TempFlags | Public | Static); case 'T': - return FuncClass(Public | Static | Far); + return FuncClass(TempFlags | Public | Static | Far); case 'U': - return FuncClass(Public | Virtual); + return FuncClass(TempFlags | Public | Virtual); case 'V': - return FuncClass(Public | Virtual | Far); + return FuncClass(TempFlags | Public | Virtual | Far); case 'Y': - return Global; + return FuncClass(TempFlags | Global); case 'Z': - return FuncClass(Global | Far); + return FuncClass(TempFlags | Global | Far); } Error = true; @@ -1768,9 +1785,16 @@ FunctionType *Demangler::demangleFunctionType(StringView &MangledName, Type *Demangler::demangleFunctionEncoding(StringView &MangledName) { FuncClass FC = demangleFunctionClass(MangledName); - - bool HasThisQuals = !(FC & (Global | Static)); - FunctionType *FTy = demangleFunctionType(MangledName, HasThisQuals, false); + FunctionType *FTy = nullptr; + if (FC & NoPrototype) { + // This is an extern "C" function whose full signature hasn't been mangled. + // This happens when we need to mangle a local symbol inside of an extern + // "C" function. + FTy = Arena.alloc<FunctionType>(); + } else { + bool HasThisQuals = !(FC & (Global | Static)); + FTy = demangleFunctionType(MangledName, HasThisQuals, false); + } FTy->FunctionClass = FC; return FTy; diff --git a/llvm/test/Demangle/ms-mangle.test b/llvm/test/Demangle/ms-mangle.test index 981f557a207..b3fe67f4759 100644 --- a/llvm/test/Demangle/ms-mangle.test +++ b/llvm/test/Demangle/ms-mangle.test @@ -268,12 +268,11 @@ ?s6@PR13182@@3PBQBDB ; CHECK: char const *const *PR13182::s6 -; FIXME: We don't properly support extern "C" functions yet. -; ?local@?1??extern_c_func@@9@4HA -; FIXME: int `extern_c_func'::`2'::local +?local@?1??extern_c_func@@9@4HA +; CHECK: int `extern "C" extern_c_func'::`2'::local -; ?local@?1??extern_c_func@@9@4HA -; FIXME: int `extern_c_func'::`2'::local +?local@?1??extern_c_func@@9@4HA +; CHECK: int `extern "C" extern_c_func'::`2'::local ?v@?1??f@@YAHXZ@4U<unnamed-type-v>@?1??1@YAHXZ@A ; CHECK: struct `int __cdecl f(void)'::`2'::<unnamed-type-v> `int __cdecl f(void)'::`2'::v @@ -331,12 +330,11 @@ ?vector_func@@YQXXZ ; CHECK: void __vectorcall vector_func(void) -; FIXME: We don't support extern C funcs currently. -; ??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ -; FIXME: void __cdecl fn_tmpl<&void __cdecl extern_c_func(void)>(void) +??$fn_tmpl@$1?extern_c_func@@YAXXZ@@YAXXZ +; CHECK: void __cdecl fn_tmpl<&void __cdecl extern_c_func(void)>(void) -; ?overloaded_fn@@$$J0YAXXZ -; FIXME-EXTERNC: extern \"C\" void __cdecl overloaded_fn(void) +?overloaded_fn@@$$J0YAXXZ +; CHECK: extern "C" void __cdecl overloaded_fn(void) ?f@UnnamedType@@YAXQAPAU<unnamed-type-T1>@S@1@@Z ; CHECK: void __cdecl UnnamedType::f(struct UnnamedType::S::<unnamed-type-T1> **const) |