From faa64297d58bb2b1c106ca82186ed77d69b2d15b Mon Sep 17 00:00:00 2001
From: Hans Wennborg <hans@hanshq.net>
Date: Tue, 15 Sep 2015 21:05:30 +0000
Subject: [PATCH] MS ABI: Don't allow dllexport/import on lambdas

This is to follow up on David's comment in
http://reviews.llvm.org/D12422#235509

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@247718 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/clang/Basic/DiagnosticSemaKinds.td |  2 ++
 lib/Sema/SemaDeclAttr.cpp                  |  8 ++++++++
 test/SemaCXX/dllexport.cpp                 |  9 +++++++++
 test/SemaCXX/dllimport.cpp                 | 11 +++++++++++
 4 files changed, 30 insertions(+)

diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 71d1ab32e44..9565f67d3e4 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2274,6 +2274,8 @@ def err_attribute_dll_not_extern : Error<
   "%q0 must have external linkage when declared %q1">;
 def err_attribute_dll_thread_local : Error<
   "%q0 cannot be thread local when declared %q1">;
+def err_attribute_dll_lambda : Error<
+  "lambda cannot be declared %0">;
 def warn_attribute_invalid_on_definition : Warning<
   "'%0' attribute cannot be specified on a definition">,
   InGroup<IgnoredAttributes>;
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 31ed9f2434f..947103780c2 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -4335,6 +4335,14 @@ static void handleDLLAttr(Sema &S, Decl *D, const AttributeList &A) {
     }
   }
 
+  if (auto *MD = dyn_cast<CXXMethodDecl>(D)) {
+    if (S.Context.getTargetInfo().getCXXABI().isMicrosoft() &&
+        MD->getParent()->isLambda()) {
+      S.Diag(A.getRange().getBegin(), diag::err_attribute_dll_lambda) << A.getName();
+      return;
+    }
+  }
+
   unsigned Index = A.getAttributeSpellingListIndex();
   Attr *NewAttr = A.getKind() == AttributeList::AT_DLLExport
                       ? (Attr *)S.mergeDLLExportAttr(D, A.getRange(), Index)
diff --git a/test/SemaCXX/dllexport.cpp b/test/SemaCXX/dllexport.cpp
index f7076fb8e86..a32ba44442d 100644
--- a/test/SemaCXX/dllexport.cpp
+++ b/test/SemaCXX/dllexport.cpp
@@ -1083,3 +1083,12 @@ template<typename T> template<typename U> __declspec(dllexport) constexpr int CT
 #endif // __has_feature(cxx_variable_templates)
 
 // FIXME: Precedence rules seem to be different for classes.
+
+//===----------------------------------------------------------------------===//
+// Lambdas
+//===----------------------------------------------------------------------===//
+// The MS ABI doesn't provide a stable mangling for lambdas, so they can't be imported or exported.
+#ifdef MS
+// expected-error@+2{{lambda cannot be declared 'dllexport'}}
+#endif
+auto Lambda = []() __declspec(dllexport) -> bool { return true; };
diff --git a/test/SemaCXX/dllimport.cpp b/test/SemaCXX/dllimport.cpp
index 91ed6b42606..5d8ce78f6cd 100644
--- a/test/SemaCXX/dllimport.cpp
+++ b/test/SemaCXX/dllimport.cpp
@@ -1339,3 +1339,14 @@ struct __declspec(dllimport) DerivedFromExplicitlyImportInstantiatedTemplate : p
 template <typename T> struct ExplicitInstantiationDeclTemplateBase { void func() {} };
 extern template struct ExplicitInstantiationDeclTemplateBase<int>;
 struct __declspec(dllimport) DerivedFromExplicitInstantiationDeclTemplateBase : public ExplicitInstantiationDeclTemplateBase<int> {};
+
+//===----------------------------------------------------------------------===//
+// Lambdas
+//===----------------------------------------------------------------------===//
+// The MS ABI doesn't provide a stable mangling for lambdas, so they can't be imported or exported.
+#ifdef MS
+// expected-error@+4{{lambda cannot be declared 'dllimport'}}
+#else
+// expected-warning@+2{{'dllimport' attribute ignored on inline function}}
+#endif
+auto Lambda = []() __declspec(dllimport) -> bool { return true; };
-- 
GitLab