From: Peter Collingbourne Date: Fri, 7 Aug 2015 23:25:47 +0000 (+0000) Subject: AST: Implement mangling support for function types without a prototype. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=36d9fb5902fe376d3cc5bcf6fb0e94e53a7725d5;p=clang AST: Implement mangling support for function types without a prototype. Function types without prototypes can arise when mangling a function type within an overloadable function in C. We mangle these as the absence of any parameter types (not even an empty parameter list). Differential Revision: http://reviews.llvm.org/D11848 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@244374 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index e51aad9ad8..1fcf466a1f 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -2055,9 +2055,23 @@ void CXXNameMangler::mangleType(const FunctionProtoType *T) { Out << 'E'; } + void CXXNameMangler::mangleType(const FunctionNoProtoType *T) { - llvm_unreachable("Can't mangle K&R function prototypes"); + // Function types without prototypes can arise when mangling a function type + // within an overloadable function in C. We mangle these as the absence of any + // parameter types (not even an empty parameter list). + Out << 'F'; + + FunctionTypeDepthState saved = FunctionTypeDepth.push(); + + FunctionTypeDepth.enterResultType(); + mangleType(T->getReturnType()); + FunctionTypeDepth.leaveResultType(); + + FunctionTypeDepth.pop(saved); + Out << 'E'; } + void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, bool MangleReturnType) { // We should never be mangling something without a prototype. diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 5c2b68cd62..a5f75ec0b1 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -1620,7 +1620,8 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionProtoType *T, Qualifiers, } void MicrosoftCXXNameMangler::mangleType(const FunctionNoProtoType *T, Qualifiers, SourceRange) { - llvm_unreachable("Can't mangle K&R function prototypes"); + Out << "$$A6"; + mangleFunctionType(T); } void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, @@ -1628,7 +1629,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, bool ForceThisQuals) { // ::= // - const FunctionProtoType *Proto = cast(T); + const FunctionProtoType *Proto = dyn_cast(T); SourceRange Range; if (D) Range = D->getSourceRange(); @@ -1699,7 +1700,7 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, } Out << '@'; } else { - QualType ResultType = Proto->getReturnType(); + QualType ResultType = T->getReturnType(); if (const auto *AT = dyn_cast_or_null(ResultType->getContainedAutoType())) { Out << '?'; @@ -1717,7 +1718,12 @@ void MicrosoftCXXNameMangler::mangleFunctionType(const FunctionType *T, // ::= X # void // ::= + @ // ::= * Z # varargs - if (Proto->getNumParams() == 0 && !Proto->isVariadic()) { + if (!Proto) { + // Function types without prototypes can arise when mangling a function type + // within an overloadable function in C. We mangle these as the absence of + // any parameter types (not even an empty parameter list). + Out << '@'; + } else if (Proto->getNumParams() == 0 && !Proto->isVariadic()) { Out << 'X'; } else { // Happens for function pointer type arguments for example. diff --git a/test/CodeGen/mangle-ms.c b/test/CodeGen/mangle-ms.c new file mode 100644 index 0000000000..0ad43d5e06 --- /dev/null +++ b/test/CodeGen/mangle-ms.c @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s + +// CHECK: define void @"\01?f@@$$J0YAXP6AX@Z@Z" +__attribute__((overloadable)) void f(void (*x)()) {} diff --git a/test/CodeGen/overloadable.c b/test/CodeGen/overloadable.c index 8b40e4d734..4946c6d928 100644 --- a/test/CodeGen/overloadable.c +++ b/test/CodeGen/overloadable.c @@ -1,5 +1,6 @@ // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm %s -o - | FileCheck %s // CHECK: _Z1fPA10_1X +// CHECK: _Z1fPFvE int __attribute__((overloadable)) f(int x) { return x; } float __attribute__((overloadable)) f(float x) { return x; } @@ -13,6 +14,8 @@ void __attribute__((overloadable)) f(struct X (*ptr)[10]) { } void __attribute__((overloadable)) f(int x, int y, ...) { } +void __attribute__((overloadable)) f(void (*x)()) {} + int main() { int iv = 17; float fv = 3.0f;