r202962 - MS ABI: Mangle lambdas

David Majnemer david.majnemer at gmail.com
Wed Mar 5 02:35:06 PST 2014


Author: majnemer
Date: Wed Mar  5 04:35:06 2014
New Revision: 202962

URL: http://llvm.org/viewvc/llvm-project?rev=202962&view=rev
Log:
MS ABI: Mangle lambdas

Use a scheme inspired by the Itanium ABI to properly implement the
mangling of lambdas.

N.B.  The incredibly astute observer will notice that we do not generate
external names that are identical, or even compatible with, MSVC.
This is fine because they don't generate names that they can use across
translation units.  Technically, we can generate any name we'd like so
long as that name wouldn't conflict with any other and would be stable
across translation units.

This fixes PR15512.

Modified:
    cfe/trunk/lib/AST/MicrosoftMangle.cpp
    cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp

Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=202962&r1=202961&r2=202962&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Wed Mar  5 04:35:06 2014
@@ -87,6 +87,7 @@ class MicrosoftMangleContextImpl : publi
   typedef std::pair<const DeclContext *, IdentifierInfo *> DiscriminatorKeyTy;
   llvm::DenseMap<DiscriminatorKeyTy, unsigned> Discriminator;
   llvm::DenseMap<const NamedDecl*, unsigned> Uniquifier;
+  llvm::DenseMap<const CXXRecordDecl *, unsigned> LambdaIds;
 
 public:
   MicrosoftMangleContextImpl(ASTContext &Context, DiagnosticsEngine &Diags)
@@ -148,6 +149,16 @@ public:
     return true;
   }
 
+  unsigned getLambdaId(const CXXRecordDecl *RD) {
+    assert(RD->isLambda() && "RD must be a lambda!");
+    assert(!RD->isExternallyVisible() && "RD must not be visible!");
+    assert(RD->getLambdaManglingNumber() == 0 &&
+           "RD must not have a mangling number!");
+    std::pair<llvm::DenseMap<const CXXRecordDecl *, unsigned>::iterator, bool>
+        Result = LambdaIds.insert(std::make_pair(RD, LambdaIds.size()));
+    return Result.first->second;
+  }
+
 private:
   void mangleInitFiniStub(const VarDecl *D, raw_ostream &Out, char CharCode);
 };
@@ -704,6 +715,23 @@ MicrosoftCXXNameMangler::mangleUnqualifi
         break;
       }
 
+      if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
+        if (Record->isLambda()) {
+          llvm::SmallString<10> Name("<lambda_");
+          unsigned LambdaId;
+          if (Record->getLambdaManglingNumber())
+            LambdaId = Record->getLambdaManglingNumber();
+          else
+            LambdaId = Context.getLambdaId(Record);
+
+          Name += llvm::utostr(LambdaId);
+          Name += ">";
+
+          mangleSourceName(Name);
+          break;
+        }
+      }
+
       llvm::SmallString<64> Name("<unnamed-type-");
       if (TD->hasDeclaratorForAnonDecl()) {
         // Anonymous types with no tag or typedef get the name of their
@@ -712,7 +740,7 @@ MicrosoftCXXNameMangler::mangleUnqualifi
       } else {
         // Otherwise, number the types using a $S prefix.
         Name += "$S";
-        Name += llvm::utostr(Context.getAnonymousStructId(TD) + 1);
+        Name += llvm::utostr(Context.getAnonymousStructId(TD));
       }
       Name += ">";
       mangleSourceName(Name.str());
@@ -770,6 +798,9 @@ MicrosoftCXXNameMangler::mangleUnqualifi
 void MicrosoftCXXNameMangler::mangleNestedName(const NamedDecl *ND) {
   // <postfix> ::= <unqualified-name> [<postfix>]
   //           ::= <substitution> [<postfix>]
+  if (isLambda(ND))
+    return;
+
   const DeclContext *DC = ND->getDeclContext();
 
   while (!DC->isTranslationUnit()) {

Modified: cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp?rev=202962&r1=202961&r2=202962&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp Wed Mar  5 04:35:06 2014
@@ -101,3 +101,21 @@ decltype(a) fun(decltype(a) x, decltype(
 // CHECK-DAG: ?fun at PR18022@@YA?AU<unnamed-type-a>@1 at U21@0 at Z
 
 }
+
+inline int define_lambda() {
+  static auto lambda = [] { static int local; ++local; return local; };
+// First, we have the static local variable of type "<lambda_1>" inside of
+// "define_lambda".
+// CHECK-DAG: ?lambda@?1??define_lambda@@YAHXZ at 4V<lambda_1>@@A
+// Next, we have the "operator()" for "<lambda_1>" which is inside of
+// "define_lambda".
+// CHECK-DAG: ??R<lambda_1>@?define_lambda@@YAHXZ at QBEHXZ
+// Finally, we have the local which is inside of "<lambda_1>" which is inside of
+// "define_lambda". Hooray.
+// CHECK-DAG: ?local@?2???R<lambda_1>@?define_lambda@@YAHXZ at QBEHXZ@4HA
+  return lambda();
+}
+
+int call_lambda() {
+  return define_lambda();
+}





More information about the cfe-commits mailing list