Author: majnemer
Date: Tue Dec  6 11:01:02 2016
New Revision: 288826

URL: http://llvm.org/viewvc/llvm-project?rev=288826&view=rev
Log:
[MS ABI] Implement more of the Itanium mangling rules

We didn't implement handle corner cases like:
 - lambdas used to initialize a field
 - lambdas in default argument initializers

This fixes PR31197.

Differential Revision: https://reviews.llvm.org/D27226

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=288826&r1=288825&r2=288826&view=diff
==============================================================================
--- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
+++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Tue Dec  6 11:01:02 2016
@@ -66,6 +66,16 @@ struct msvc_hashing_ostream : public llv
   }
 };
 
+static const DeclContext *
+getLambdaDefaultArgumentDeclContext(const Decl *D) {
+  if (const auto *RD = dyn_cast<CXXRecordDecl>(D))
+    if (RD->isLambda())
+      if (const auto *Parm =
+              dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
+        return Parm->getDeclContext();
+  return nullptr;
+}
+
 /// \brief Retrieve the declaration context that should be used when mangling
 /// the given declaration.
 static const DeclContext *getEffectiveDeclContext(const Decl *D) {
@@ -75,12 +85,8 @@ static const DeclContext *getEffectiveDe
   // not the case: the lambda closure type ends up living in the context
   // where the function itself resides, because the function declaration itself
   // had not yet been created. Fix the context here.
-  if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) {
-    if (RD->isLambda())
-      if (ParmVarDecl *ContextParam =
-              dyn_cast_or_null<ParmVarDecl>(RD->getLambdaContextDecl()))
-        return ContextParam->getDeclContext();
-  }
+  if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(D))
+    return LDADC;
 
   // Perform the same check for block literals.
   if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
@@ -112,14 +118,6 @@ static const FunctionDecl *getStructor(c
   return FD;
 }
 
-static bool isLambda(const NamedDecl *ND) {
-  const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND);
-  if (!Record)
-    return false;
-
-  return Record->isLambda();
-}
-
 /// MicrosoftMangleContextImpl - Overrides the default MangleContext for the
 /// Microsoft Visual C++ ABI.
 class MicrosoftMangleContextImpl : public MicrosoftMangleContext {
@@ -200,9 +198,11 @@ public:
 
     // Lambda closure types are already numbered, give out a phony number so
     // that they demangle nicely.
-    if (isLambda(ND)) {
-      disc = 1;
-      return true;
+    if (const auto *RD = dyn_cast<CXXRecordDecl>(ND)) {
+      if (RD->isLambda()) {
+        disc = 1;
+        return true;
+      }
     }
 
     // Use the canonical number for externally visible decls.
@@ -824,9 +824,24 @@ void MicrosoftCXXNameMangler::mangleUnqu
       if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(TD)) {
         if (Record->isLambda()) {
           llvm::SmallString<10> Name("<lambda_");
+
+          Decl *LambdaContextDecl = Record->getLambdaContextDecl();
+          unsigned LambdaManglingNumber = Record->getLambdaManglingNumber();
           unsigned LambdaId;
-          if (Record->getLambdaManglingNumber())
-            LambdaId = Record->getLambdaManglingNumber();
+          const ParmVarDecl *Parm =
+              dyn_cast_or_null<ParmVarDecl>(LambdaContextDecl);
+          const FunctionDecl *Func =
+              Parm ? dyn_cast<FunctionDecl>(Parm->getDeclContext()) : nullptr;
+
+          if (Func) {
+            unsigned DefaultArgNo =
+                Func->getNumParams() - Parm->getFunctionScopeIndex();
+            Name += llvm::utostr(DefaultArgNo);
+            Name += "_";
+          }
+
+          if (LambdaManglingNumber)
+            LambdaId = LambdaManglingNumber;
           else
             LambdaId = Context.getLambdaId(Record);
 
@@ -834,6 +849,16 @@ void MicrosoftCXXNameMangler::mangleUnqu
           Name += ">";
 
           mangleSourceName(Name);
+
+          // If the context of a closure type is an initializer for a class
+          // member (static or nonstatic), it is encoded in a qualified name.
+          if (LambdaManglingNumber && LambdaContextDecl) {
+            if ((isa<VarDecl>(LambdaContextDecl) ||
+                 isa<FieldDecl>(LambdaContextDecl)) &&
+                LambdaContextDecl->getDeclContext()->isRecord()) {
+              mangleUnqualifiedName(cast<NamedDecl>(LambdaContextDecl));
+            }
+          }
           break;
         }
       }
@@ -937,7 +962,6 @@ void MicrosoftCXXNameMangler::mangleNest
       // for how this should be done.
       Out << "__block_invoke" << Context.getBlockId(BD, false);
       Out << '@';
-      continue;
     } else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) {
       mangleObjCMethodName(Method);
     } else if (isa<NamedDecl>(DC)) {
@@ -945,8 +969,15 @@ void MicrosoftCXXNameMangler::mangleNest
       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
         mangle(FD, "?");
         break;
-      } else
+      } else {
         mangleUnqualifiedName(ND);
+        // Lambdas in default arguments conceptually belong to the function the
+        // parameter corresponds to.
+        if (const auto *LDADC = getLambdaDefaultArgumentDeclContext(ND)) {
+          DC = LDADC;
+          continue;
+        }
+      }
     }
     DC = DC->getParent();
   }

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=288826&r1=288825&r2=288826&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp Tue Dec  6 11:01:02 2016
@@ -318,3 +318,28 @@ void unaligned_foo8_S::unaligned_foo8()
 
 // CHECK-DAG: @"\01?unaligned_foo8@unaligned_foo8_S@@QFCEXXZ"
 
+namespace PR31197 {
+struct A {
+  // CHECK-DAG: define linkonce_odr x86_thiscallcc i32* 
@"\01??R<lambda_1>@x@A@PR31197@@QBE@XZ"(
+  int *x = []() {
+    static int white;
+    // CHECK-DAG: @"\01?white@?1???R<lambda_1>@x@A@PR31197@@QBE@XZ@4HA"
+    return &white;
+  }();
+  // CHECK-DAG: define linkonce_odr x86_thiscallcc i32* 
@"\01??R<lambda_1>@y@A@PR31197@@QBE@XZ"(
+  int *y = []() {
+    static int black;
+    // CHECK-DAG: @"\01?black@?1???R<lambda_1>@y@A@PR31197@@QBE@XZ@4HA"
+    return &black;
+  }();
+  using FPtrTy = void(void);
+  static void default_args(FPtrTy x = [] {}, FPtrTy y = [] {}, int z = [] { 
return 1; }() + [] { return 2; }()) {}
+  // CHECK-DAG: 
@"\01??R<lambda_1_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+  // CHECK-DAG: 
@"\01??R<lambda_1_2>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+  // CHECK-DAG: 
@"\01??R<lambda_2_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+  // CHECK-DAG: 
@"\01??R<lambda_3_1>@?0??default_args@A@PR31197@@SAXP6AXXZ0H@Z@QBE@XZ"(
+};
+A a;
+
+int call_it = (A::default_args(), 1);
+}


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to