[PATCH] [ms-cxxabi] PR15512 - mangle lambda names.

Michael Han fragmentshaders at gmail.com
Thu May 9 11:03:01 PDT 2013


This patch is trying to fix PR15512. For lambda with internal linkage, Itanium ABI would mangle the names as anonymous struct and using a unique mangling number to differentiate between different lambdas. This patch takes a similar approach by maintaining a mangling number for local lambdas in Microsoft mangle context and use the number to differentiate between different lambdas with internal linkage.
The mangled name is prefixed with "lambda" (rather than "unnamed-tag") which seems what MSVC is doing. 

Please review!

http://llvm-reviews.chandlerc.com/D774

Files:
  lib/AST/MicrosoftMangle.cpp
  test/CodeGenCXX/mangle-ms-lambda.cpp

Index: lib/AST/MicrosoftMangle.cpp
===================================================================
--- lib/AST/MicrosoftMangle.cpp
+++ lib/AST/MicrosoftMangle.cpp
@@ -22,6 +22,7 @@
 #include "clang/AST/ExprCXX.h"
 #include "clang/Basic/ABI.h"
 #include "clang/Basic/DiagnosticOptions.h"
+#include "llvm/ADT/StringExtras.h"
 #include <map>
 
 using namespace clang;
@@ -35,10 +36,46 @@
   return fn;
 }
 
+/// MicrosoftMangleContext - Overrides the default MangleContext for the
+/// Microsoft Visual C++ ABI.
+class MicrosoftMangleContext : public MangleContext {
+  typedef llvm::DenseMap<const TagDecl*, unsigned> LocalLambdaManglingNumberTy;
+  LocalLambdaManglingNumberTy LocalLambdaManglingNumbers;
+
+public:
+  MicrosoftMangleContext(ASTContext &Context,
+                   DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }
+  virtual bool shouldMangleDeclName(const NamedDecl *D);
+  virtual void mangleName(const NamedDecl *D, raw_ostream &Out);
+  virtual void mangleThunk(const CXXMethodDecl *MD,
+                           const ThunkInfo &Thunk,
+                           raw_ostream &);
+  virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
+                                  const ThisAdjustment &ThisAdjustment,
+                                  raw_ostream &);
+  virtual void mangleCXXVTable(const CXXRecordDecl *RD,
+                               raw_ostream &);
+  virtual void mangleCXXVTT(const CXXRecordDecl *RD,
+                            raw_ostream &);
+  virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
+                                   const CXXRecordDecl *Type,
+                                   raw_ostream &);
+  virtual void mangleCXXRTTI(QualType T, raw_ostream &);
+  virtual void mangleCXXRTTIName(QualType T, raw_ostream &);
+  virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
+                             raw_ostream &);
+  virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
+                             raw_ostream &);
+  virtual void mangleReferenceTemporary(const clang::VarDecl *,
+                                        raw_ostream &);
+
+  unsigned getLocalLambdaManglingNumber(const TagDecl *TD);
+};
+
 /// MicrosoftCXXNameMangler - Manage the mangling of a single name for the
 /// Microsoft Visual C++ ABI.
 class MicrosoftCXXNameMangler {
-  MangleContext &Context;
+  MicrosoftMangleContext &Context;
   raw_ostream &Out;
 
   /// The "structor" is the top-level declaration being mangled, if
@@ -61,12 +98,12 @@
 public:
   enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result };
 
-  MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_)
+  MicrosoftCXXNameMangler(MicrosoftMangleContext &C, raw_ostream &Out_)
     : Context(C), Out(Out_),
       Structor(0), StructorType(-1),
       UseNameBackReferences(true) { }
 
-  MicrosoftCXXNameMangler(MangleContext &C, raw_ostream &Out_,
+  MicrosoftCXXNameMangler(MicrosoftMangleContext &C, raw_ostream &Out_,
                           const CXXDestructorDecl *D, CXXDtorType Type)
     : Context(C), Out(Out_),
       Structor(getStructor(D)), StructorType(Type),
@@ -127,40 +164,8 @@
 
   void mangleTemplateArgs(const TemplateDecl *TD,
                           const TemplateArgumentList &TemplateArgs);
-
 };
 
-/// MicrosoftMangleContext - Overrides the default MangleContext for the
-/// Microsoft Visual C++ ABI.
-class MicrosoftMangleContext : public MangleContext {
-public:
-  MicrosoftMangleContext(ASTContext &Context,
-                   DiagnosticsEngine &Diags) : MangleContext(Context, Diags) { }
-  virtual bool shouldMangleDeclName(const NamedDecl *D);
-  virtual void mangleName(const NamedDecl *D, raw_ostream &Out);
-  virtual void mangleThunk(const CXXMethodDecl *MD,
-                           const ThunkInfo &Thunk,
-                           raw_ostream &);
-  virtual void mangleCXXDtorThunk(const CXXDestructorDecl *DD, CXXDtorType Type,
-                                  const ThisAdjustment &ThisAdjustment,
-                                  raw_ostream &);
-  virtual void mangleCXXVTable(const CXXRecordDecl *RD,
-                               raw_ostream &);
-  virtual void mangleCXXVTT(const CXXRecordDecl *RD,
-                            raw_ostream &);
-  virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset,
-                                   const CXXRecordDecl *Type,
-                                   raw_ostream &);
-  virtual void mangleCXXRTTI(QualType T, raw_ostream &);
-  virtual void mangleCXXRTTIName(QualType T, raw_ostream &);
-  virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type,
-                             raw_ostream &);
-  virtual void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
-                             raw_ostream &);
-  virtual void mangleReferenceTemporary(const clang::VarDecl *,
-                                        raw_ostream &);
-};
-
 }
 
 static bool isInCLinkageSpecification(const Decl *D) {
@@ -470,6 +475,26 @@
         break;
       }
 
+      const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD);
+      if (Record && Record->isLambda()) {
+        // Mangle lambda that has internal linkage.
+        if (!Record->getLambdaManglingNumber()) {
+          // Get a unique id for the local lambda.
+          unsigned ID = Context.getLocalLambdaManglingNumber(TD);
+
+          // Mangle local lambda in the form
+          // <lambda_n>
+          // where n is the lambda id.
+          SmallString<64> Str;
+          Str += "<lambda_";
+          Str += llvm::utostr(ID);
+          Str += ">";
+          Out << Str.str();
+          break;
+        }
+        // FIXME: mangle lambda that has external linkage.
+      }
+
       // When VC encounters an anonymous type with no tag and no typedef,
       // it literally emits '<unnamed-tag>'.
       Out << "<unnamed-tag>";
@@ -1792,6 +1817,21 @@
   getDiags().Report(VD->getLocation(), DiagID);
 }
 
+unsigned MicrosoftMangleContext::getLocalLambdaManglingNumber(
+  const TagDecl *TD) {
+  LocalLambdaManglingNumberTy::const_iterator I =
+    LocalLambdaManglingNumbers.find(TD);
+
+  if (I != LocalLambdaManglingNumbers.end())
+    return I->second;
+  else {
+    unsigned ID = LocalLambdaManglingNumbers.size();
+    LocalLambdaManglingNumbers.insert(
+      std::make_pair(TD, ID));
+    return ID;
+  }
+}
+
 MangleContext *clang::createMicrosoftMangleContext(ASTContext &Context,
                                                    DiagnosticsEngine &Diags) {
   return new MicrosoftMangleContext(Context, Diags);
Index: test/CodeGenCXX/mangle-ms-lambda.cpp
===================================================================
--- test/CodeGenCXX/mangle-ms-lambda.cpp
+++ test/CodeGenCXX/mangle-ms-lambda.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -std=c++11 -fms-extensions -emit-llvm %s -o - -cxx-abi microsoft -triple=i386-pc-win32 | FileCheck %s
+
+// PR15512 
+// CHECK: "\01??R<lambda_0>?1??main@@@QBEHXZ"
+// CHECK: "\01??R<lambda_0>?1??main@@@QBEHXZ"
+// CHECK: "\01??R<lambda_1>?1??main@@@QBEHXZ"
+// CHECK: "\01??R<lambda_1>?1??main@@@QBEHXZ"
+int main( int argc, char *argv[]) {
+  auto first = [&]() { return argc; };
+  auto second = [&]() { return first();};
+  return second();
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D774.1.patch
Type: text/x-patch
Size: 7373 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130509/c4901fe0/attachment.bin>


More information about the cfe-commits mailing list