From: Timur Iskhodzhanov Date: Sat, 23 Jun 2012 00:54:17 +0000 (+0000) Subject: [Windows] Fix mangling of repeated types in the presence of bool and function pointer... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3f835687b8f7ad3060fe4c462727b212ed714b30;p=clang [Windows] Fix mangling of repeated types in the presence of bool and function pointers PR13176,PR13177 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159059 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index d2be5e5393..0d42689833 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -31,8 +31,8 @@ class MicrosoftCXXNameMangler { MangleContext &Context; raw_ostream &Out; - typedef llvm::DenseMap BackRefMap; - BackRefMap BackReferences; + typedef llvm::DenseMap BackRefMap; + BackRefMap NameBackReferences, TypeBackReferences; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -66,6 +66,8 @@ private: void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleLocalName(const FunctionDecl *FD); + void mangleTypeRepeated(QualType T, SourceRange Range); + // Declare manglers for every type class. #define ABSTRACT_TYPE(CLASS, PARENT) #define NON_CANONICAL_TYPE(CLASS, PARENT) @@ -644,12 +646,12 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) { // ::= @ - BackRefMap::iterator Found = BackReferences.find(II); - if (Found == BackReferences.end()) { + BackRefMap::iterator Found = NameBackReferences.find((void*)II); + if (Found == NameBackReferences.end()) { Out << II->getName() << '@'; - if (BackReferences.size() < 10) { - size_t Size = BackReferences.size(); - BackReferences[II] = Size; + if (NameBackReferences.size() < 10) { + size_t Size = NameBackReferences.size(); + NameBackReferences[(void*)II] = Size; } } else { Out << Found->second; @@ -852,6 +854,28 @@ void MicrosoftCXXNameMangler::mangleQualifiers(Qualifiers Quals, // FIXME: For now, just drop all extension qualifiers on the floor. } +void MicrosoftCXXNameMangler::mangleTypeRepeated(QualType T, SourceRange Range) { + void *TypePtr = getASTContext().getCanonicalType(T).getAsOpaquePtr(); + BackRefMap::iterator Found = TypeBackReferences.find(TypePtr); + + if (Found == TypeBackReferences.end()) { + size_t OutSizeBefore = Out.GetNumBytesInBuffer(); + + mangleType(T,Range); + + // See if it's worth creating a back reference. + // Only types longer than 1 character are considered + // and only 10 back references slots are available: + bool LongerThanOneChar = (Out.GetNumBytesInBuffer() - OutSizeBefore > 1); + if (LongerThanOneChar && TypeBackReferences.size() < 10) { + size_t Size = TypeBackReferences.size(); + TypeBackReferences[TypePtr] = Size; + } + } else { + Out << Found->second; + } +} + void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range) { // Only operate on the canonical type! T = getASTContext().getCanonicalType(T); @@ -1026,8 +1050,6 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T, if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) { Out << 'X'; } else { - typedef llvm::DenseMap BackRef; - BackRef BackReferences; if (D) { // If we got a decl, use the type-as-written to make sure arrays // get mangled right. Note that we can't rely on the TSI @@ -1036,24 +1058,14 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T, ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) { TypeSourceInfo *TSI = (*Parm)->getTypeSourceInfo(); QualType Type = TSI ? TSI->getType() : (*Parm)->getType(); - CanQualType Canonical = getASTContext().getCanonicalType(Type); - void *TypePtr = Canonical.getAsOpaquePtr(); - BackRef::iterator Found = BackReferences.find(TypePtr); - if (Found == BackReferences.end()) { - mangleType(Type, (*Parm)->getSourceRange()); - if (BackReferences.size() < 10 && (Canonical->getTypeClass() != Type::Builtin)) { - size_t Size = BackReferences.size(); - BackReferences[TypePtr] = Size; - } - } else { - Out << Found->second; - } + mangleTypeRepeated(Type, (*Parm)->getSourceRange()); } } else { + // Happens for function pointer type arguments for example. for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), ArgEnd = Proto->arg_type_end(); Arg != ArgEnd; ++Arg) - mangleType(*Arg, SourceRange()); + mangleTypeRepeated(*Arg, SourceRange()); } // ::= Z # ellipsis if (Proto->isVariadic()) diff --git a/test/CodeGenCXX/mangle-ms-back-references.cpp b/test/CodeGenCXX/mangle-ms-back-references.cpp index fdfb3b5bf2..95ac5bb921 100644 --- a/test/CodeGenCXX/mangle-ms-back-references.cpp +++ b/test/CodeGenCXX/mangle-ms-back-references.cpp @@ -12,17 +12,35 @@ void f3(int a, const char* b, const char* c) {} const char *f4(const char* a, const char* b) {} // CHECK: "\01?f4@@YAPBDPBD0@Z" +void f5(char const* a, unsigned int b, char c, void const* d, char const* e, unsigned int f) {} +// CHECK: "\01?f5@@YAXPBDIDPBX0I@Z" + +void f6(bool a, bool b) {} +// CHECK: "\01?f6@@YAX_N0@Z" + +void f7(int a, int* b, int c, int* d, bool e, bool f, bool* g) {} +// CHECK: "\01?f7@@YAXHPAHH0_N1PA_N@Z" + // FIXME: tests for more than 10 types? -struct S {}; +struct S { + void mbb(bool a, bool b) {} +}; -void g4(const char* a, struct S* b, const char *c, struct S* d) {} -// CHECK: "\01?g4@@YAXPBDPAUS@@01@Z" +void g1(struct S a) {} +// CHECK: "\01?g1@@YAXUS@@@Z" -typedef void (*VoidFunc)(); +void g2(struct S a, struct S b) {} +// CHECK: "\01?g2@@YAXUS@@0@Z" + +void g3(struct S a, struct S b, struct S* c, struct S* d) {} +// CHECK: "\01?g3@@YAXUS@@0PAU1@1@Z" -void foo_ptr(const char* a, const char* b, VoidFunc c, VoidFunc d) {} -// CHECK: @"\01?foo_ptr@@YAXPBD0P6AXXZ1@Z" +void g4(const char* a, struct S* b, const char* c, struct S* d) { +// CHECK: "\01?g4@@YAXPBDPAUS@@01@Z" + b->mbb(false, false); +// CHECK: "\01?mbb@S@@QAEX_N0@Z" +} // Make sure that different aliases of built-in types end up mangled as the // built-ins. @@ -30,3 +48,16 @@ typedef unsigned int uintptr_t; typedef unsigned int size_t; void *h(size_t a, uintptr_t b) {} // CHECK: "\01?h@@YAPAXII@Z" + +// Function pointers might be mangled in a complex way. +typedef void (*VoidFunc)(); +typedef int* (*PInt3Func)(int* a, int* b); + +void h1(const char* a, const char* b, VoidFunc c, VoidFunc d) {} +// CHECK: "\01?h1@@YAXPBD0P6AXXZ1@Z" + +void h2(void (*f_ptr)(void *), void *arg) {} +// CHECK: "\01?h2@@YAXP6AXPAX@Z0@Z" + +PInt3Func h3(PInt3Func x, PInt3Func y, int* z) { return 0; } +// CHECK: "\01?h3@@YAP6APAHPAH0@ZP6APAH00@Z10@Z"