diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-21 02:52:27 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-06-21 02:52:27 +0000 |
commit | 06e767d6703fdae9cda21c6c96c79a0135e2567a (patch) | |
tree | d3a7dbb8de666dacff4c7c9887cd7957a14ee003 | |
parent | f96b9ce9d9bc8f11c7ec0ab856e592059c0f830a (diff) |
MS: Mangle rvalue references and nullptr_t, and produce back-references when
appropriate. Patch by João Matos!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158895 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/MicrosoftMangle.cpp | 63 | ||||
-rw-r--r-- | test/CodeGenCXX/mangle-ms-back-references.cpp | 32 | ||||
-rw-r--r-- | test/CodeGenCXX/mangle-ms-cxx11.cpp | 11 | ||||
-rw-r--r-- | test/CodeGenCXX/mangle-ms.cpp | 9 |
4 files changed, 100 insertions, 15 deletions
diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index 4d8d79cbce..29319ff417 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -31,6 +31,9 @@ class MicrosoftCXXNameMangler { MangleContext &Context; raw_ostream &Out; + typedef llvm::DenseMap<const IdentifierInfo*, unsigned> BackRefMap; + BackRefMap BackReferences; + ASTContext &getASTContext() const { return Context.getASTContext(); } public: @@ -641,7 +644,16 @@ void MicrosoftCXXNameMangler::mangleOperatorName(OverloadedOperatorKind OO, void MicrosoftCXXNameMangler::mangleSourceName(const IdentifierInfo *II) { // <source name> ::= <identifier> @ - Out << II->getName() << '@'; + BackRefMap::iterator Found = BackReferences.find(II); + if (Found == BackReferences.end()) { + Out << II->getName() << '@'; + if (BackReferences.size() < 10) { + size_t Size = BackReferences.size(); + BackReferences[II] = Size; + } + } else { + Out << Found->second; + } } void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { @@ -938,17 +950,19 @@ void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, case BuiltinType::ObjCId: Out << "PAUobjc_object@@"; break; case BuiltinType::ObjCClass: Out << "PAUobjc_class@@"; break; case BuiltinType::ObjCSel: Out << "PAUobjc_selector@@"; break; + + case BuiltinType::NullPtr: Out << "$$T"; break; case BuiltinType::Char16: case BuiltinType::Char32: - case BuiltinType::Half: - case BuiltinType::NullPtr: { + case BuiltinType::Half: { DiagnosticsEngine &Diags = Context.getDiags(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "cannot mangle this built-in %0 type yet"); Diags.Report(Range.getBegin(), DiagID) << T->getName(Context.getASTContext().getPrintingPolicy()) << Range; + break; } } } @@ -986,11 +1000,16 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T, // ::= @ # structors (they have no declared return type) if (IsStructor) Out << '@'; - else + else { + QualType Result = Proto->getResultType(); + const Type* RT = Result.getTypePtr(); + if(isa<TagType>(RT) && !RT->isAnyPointerType() && !RT->isReferenceType()) + Out << "?A"; // FIXME: Get the source range for the result type. Or, better yet, // implement the unimplemented stuff so we don't need accurate source // location info anymore :). - mangleType(Proto->getResultType(), SourceRange()); + mangleType(Result, SourceRange()); + } // <argument-list> ::= X # void // ::= <type>+ @ @@ -998,17 +1017,28 @@ void MicrosoftCXXNameMangler::mangleType(const FunctionType *T, if (Proto->getNumArgs() == 0 && !Proto->isVariadic()) { Out << 'X'; } else { + typedef llvm::DenseMap<void*, unsigned> 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 // existing if (for example) the parameter was synthesized. for (FunctionDecl::param_const_iterator Parm = D->param_begin(), ParmEnd = D->param_end(); Parm != ParmEnd; ++Parm) { - if (TypeSourceInfo *typeAsWritten = (*Parm)->getTypeSourceInfo()) - mangleType(typeAsWritten->getType(), - typeAsWritten->getTypeLoc().getSourceRange()); - else - mangleType((*Parm)->getType(), SourceRange()); + 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; + } } } else { for (FunctionProtoType::arg_type_iterator Arg = Proto->arg_type_begin(), @@ -1316,13 +1346,16 @@ void MicrosoftCXXNameMangler::mangleType(const LValueReferenceType *T, mangleType(PointeeTy, Range); } +// <type> ::= <r-value-reference-type> +// <r-value-reference-type> ::= $$Q <cvr-qualifiers> <type> void MicrosoftCXXNameMangler::mangleType(const RValueReferenceType *T, SourceRange Range) { - DiagnosticsEngine &Diags = Context.getDiags(); - unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, - "cannot mangle this r-value reference type yet"); - Diags.Report(Range.getBegin(), DiagID) - << Range; + Out << "$$Q"; + QualType PointeeTy = T->getPointeeType(); + if (!PointeeTy.hasQualifiers()) + // Lack of qualifiers is mangled as 'A'. + Out << 'A'; + mangleType(PointeeTy, Range); } void MicrosoftCXXNameMangler::mangleType(const ComplexType *T, diff --git a/test/CodeGenCXX/mangle-ms-back-references.cpp b/test/CodeGenCXX/mangle-ms-back-references.cpp new file mode 100644 index 0000000000..fdfb3b5bf2 --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-back-references.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -fms-extensions -fblocks -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s + +void f1(const char* a, const char* b) {} +// CHECK: "\01?f1@@YAXPBD0@Z" + +void f2(const char* a, char* b) {} +// CHECK: "\01?f2@@YAXPBDPAD@Z" + +void f3(int a, const char* b, const char* c) {} +// CHECK: "\01?f3@@YAXHPBD0@Z" + +const char *f4(const char* a, const char* b) {} +// CHECK: "\01?f4@@YAPBDPBD0@Z" + +// FIXME: tests for more than 10 types? + +struct S {}; + +void g4(const char* a, struct S* b, const char *c, struct S* d) {} +// CHECK: "\01?g4@@YAXPBDPAUS@@01@Z" + +typedef void (*VoidFunc)(); + +void foo_ptr(const char* a, const char* b, VoidFunc c, VoidFunc d) {} +// CHECK: @"\01?foo_ptr@@YAXPBD0P6AXXZ1@Z" + +// Make sure that different aliases of built-in types end up mangled as the +// built-ins. +typedef unsigned int uintptr_t; +typedef unsigned int size_t; +void *h(size_t a, uintptr_t b) {} +// CHECK: "\01?h@@YAPAXII@Z" diff --git a/test/CodeGenCXX/mangle-ms-cxx11.cpp b/test/CodeGenCXX/mangle-ms-cxx11.cpp new file mode 100644 index 0000000000..6947a53c4d --- /dev/null +++ b/test/CodeGenCXX/mangle-ms-cxx11.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s + +// CHECK: "\01?LRef@@YAXAAH@Z" +void LRef(int& a) { } + +// CHECK: "\01?RRef@@YAH$$QAH@Z" +int RRef(int&& a) { return a; } + +// CHECK: "\01?Null@@YAX$$T@Z" +namespace std { typedef decltype(__nullptr) nullptr_t; } +void Null(std::nullptr_t) {} diff --git a/test/CodeGenCXX/mangle-ms.cpp b/test/CodeGenCXX/mangle-ms.cpp index cf4055f72a..326a848fcb 100644 --- a/test/CodeGenCXX/mangle-ms.cpp +++ b/test/CodeGenCXX/mangle-ms.cpp @@ -132,3 +132,12 @@ typedef double RGB[3]; RGB color1; extern const RGB color2 = {}; extern RGB const ((color3)[5]) = {}; + +// PR12603 +enum E {}; +// CHECK: "\01?fooE@@YA?AW4E@@XZ" +E fooE() { return E(); } + +class X {}; +// CHECK: "\01?fooX@@YA?AVX@@XZ" +X fooX() { return X(); } |