Index: include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h =================================================================== --- include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h +++ include/llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h @@ -31,6 +31,8 @@ void dumpRight(PDBSymDumper &Dumper) const override; void dumpArgList(raw_ostream &OS) const; + bool isCVarArgs() const; + FORWARD_SYMBOL_METHOD(getCallingConvention) FORWARD_SYMBOL_ID_METHOD(getClassParent) FORWARD_SYMBOL_ID_METHOD(getUnmodifiedType) Index: lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp =================================================================== --- lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp +++ lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp @@ -14,6 +14,7 @@ #include "llvm/DebugInfo/PDB/IPDBSession.h" #include "llvm/DebugInfo/PDB/PDBSymDumper.h" #include "llvm/DebugInfo/PDB/PDBSymbol.h" +#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" #include @@ -84,3 +85,21 @@ void PDBSymbolTypeFunctionSig::dumpRight(PDBSymDumper &Dumper) const { Dumper.dumpRight(*this); } + +bool PDBSymbolTypeFunctionSig::isCVarArgs() const { + auto SigArguments = getArguments(); + if (!SigArguments) + return false; + uint32_t NumArgs = SigArguments->getChildCount(); + if (NumArgs == 0) + return false; + auto Last = SigArguments->getChildAtIndex(NumArgs - 1); + if (auto Builtin = llvm::dyn_cast_or_null(Last.get())) { + if (Builtin->getBuiltinType() == PDB_BuiltinType::None) + return true; + } + + // Note that for a variadic template signature, this method always returns + // false since the parameters of the template are specialized. + return false; +} Index: test/tools/llvm-pdbdump/Inputs/PrettyFuncDumperTest.cpp =================================================================== --- /dev/null +++ test/tools/llvm-pdbdump/Inputs/PrettyFuncDumperTest.cpp @@ -0,0 +1,49 @@ +// Compile for x86 (FPO disabled) +// Compile with "cl /c /Zi /GR- PrettyFuncDumperTest.cpp" +// Link with "link PrettyFuncDumperTest.obj /debug /nodefaultlib /entry:main" + +typedef void (*FuncPtrA)(); +FuncPtrA FuncVarA; + +typedef float (*FuncPtrB)(void); +FuncPtrB FuncVarB; + +typedef int(*VariadicFuncPtrTypedef)(char, double, ...); +VariadicFuncPtrTypedef VariadicFuncVar; + +void Func(int array[]) { return; } + +template +void TemplateFunc(T ...Arg) { + return; +} + +namespace { + void Func(int& a, const double b, volatile bool c) { return; } +} + +namespace NS { + void Func(char a, int b, ...) { + return; + } +} + +namespace MemberFuncsTest { + class A { + public: + int FuncA() { return 1; } + void FuncB(int a, ...) {} + }; +} + +int main() { + MemberFuncsTest::A v1; + v1.FuncA(); + v1.FuncB(9, 10, 20); + + NS::Func('c', 2, 10, 100); + + TemplateFunc(10); + TemplateFunc(10, 11, 88); + return 0; +} Index: test/tools/llvm-pdbdump/pretty-func-dumper.test =================================================================== --- /dev/null +++ test/tools/llvm-pdbdump/pretty-func-dumper.test @@ -0,0 +1,25 @@ +; RUN: llvm-pdbutil pretty -all -class-recurse-depth=1 \ +; RUN: %p/Inputs/PrettyFuncDumperTest.pdb > %t +; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBALS_FUNC +; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBALS_DATA +; RUN: FileCheck -input-file=%t %s -check-prefix=TYPEDEF + +; GLOBALS_FUNC: ---GLOBALS--- +; GLOBALS_FUNC-DAG: void __cdecl NS::Func(char a, int b, ...) +; GLOBALS_FUNC-DAG: void __cdecl TemplateFunc<1,int>(int ) +; GLOBALS_FUNC-DAG: void __cdecl TemplateFunc<1,int,int,int>(int , int , int ) +; GLOBALS_FUNC-DAG: void __cdecl `anonymous namespace'::Func(int& a, const double b, volatile bool c) +; GLOBALS_FUNC-DAG: void __cdecl Func(int* array) +; GLOBALS_FUNC-DAG: int MemberFuncsTest::A::FuncA() +; GLOBALS_FUNC-DAG: void __cdecl MemberFuncsTest::A::FuncB(int a, ...) + +; GLOBALS_DATA: ---GLOBALS--- +; GLOBALS_DATA-DAG: void (__cdecl * FuncVarA)() +; GLOBALS_DATA-DAG: float (__cdecl * FuncVarB)() +; GLOBALS_DATA-DAG: int (__cdecl * VariadicFuncVar)(char, double, ...) + +; TYPEDEF: ---TYPES--- +; TYPEDEF: Typedefs: +; TYPEDEF-DAG: typedef void (__cdecl *)() FuncPtrA +; TYPEDEF-DAG: typedef int (__cdecl *)(char, double, ...) VariadicFuncPtrTypedef +; TYPEDEF-DAG: typedef float (__cdecl *)() FuncPtrB Index: tools/llvm-pdbutil/PrettyBuiltinDumper.cpp =================================================================== --- tools/llvm-pdbutil/PrettyBuiltinDumper.cpp +++ tools/llvm-pdbutil/PrettyBuiltinDumper.cpp @@ -87,6 +87,8 @@ return "HRESULT"; case PDB_BuiltinType::BCD: return "HRESULT"; + case PDB_BuiltinType::None: + return "..."; default: return "void"; } Index: tools/llvm-pdbutil/PrettyFunctionDumper.cpp =================================================================== --- tools/llvm-pdbutil/PrettyFunctionDumper.cpp +++ tools/llvm-pdbutil/PrettyFunctionDumper.cpp @@ -189,6 +189,8 @@ if (++Index < Arguments->getChildCount()) Printer << ", "; } + if (Signature->isCVarArgs()) + Printer << ", ..."; } Printer << ")"; if (Symbol.isConstType())