Author: majnemer
Date: Wed Dec 30 23:36:46 2015
New Revision: 256661

URL: http://llvm.org/viewvc/llvm-project?rev=256661&view=rev
Log:
[MSVC Compat] Diagnose multiple default ctors for dllexport'd classes

The MS ABI emits a special default constructor closure thunk if a
default constructor has a weird calling convention or default arguments.

The MS ABI has a quirk: there can be only one such thunk because the
mangling scheme does not have room for distinct manglings.  We must
raise a diagnostic in this eventuality.

N.B.  MSVC sorta gets this right.  Multiple default constructors result
in the default constructor closure getting emitted but they seem to
get confused by which default constructors are reasonable to reference
from the closure.  We try to be a little more careful which results in
mild differences in behavior.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/test/SemaCXX/dllexport.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=256661&r1=256660&r2=256661&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Dec 30 23:36:46 
2015
@@ -2400,6 +2400,8 @@ def warn_attribute_dll_instantiated_base
   "propagating dll attribute to %select{already instantiated|explicitly 
specialized}0 "
   "base class template without dll attribute is not supported">,
   InGroup<DiagGroup<"unsupported-dll-base-class-template">>, DefaultIgnore;
+def err_attribute_dll_ambiguous_default_ctor : Error<
+  "'__declspec(dllexport)' cannot be applied to more than one default 
constructor in %0">;
 def err_attribute_weakref_not_static : Error<
   "weakref declaration must have internal linkage">;
 def err_attribute_weakref_not_global_context : Error<

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=256661&r1=256660&r2=256661&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Dec 30 23:36:46 2015
@@ -9470,6 +9470,10 @@ static void getDefaultArgExprsForConstru
   if (Class->getDescribedClassTemplate())
     return;
 
+  CallingConv ExpectedCallingConv = S.Context.getDefaultCallingConvention(
+      /*IsVariadic=*/false, /*IsCXXMethod=*/true);
+
+  CXXConstructorDecl *LastExportedDefaultCtor = nullptr;
   for (Decl *Member : Class->decls()) {
     auto *CD = dyn_cast<CXXConstructorDecl>(Member);
     if (!CD) {
@@ -9481,7 +9485,25 @@ static void getDefaultArgExprsForConstru
       continue;
     }
 
-    for (unsigned I = 0, E = CD->getNumParams(); I != E; ++I) {
+    CallingConv ActualCallingConv =
+        CD->getType()->getAs<FunctionProtoType>()->getCallConv();
+
+    // Skip default constructors with typical calling conventions and no 
default
+    // arguments.
+    unsigned NumParams = CD->getNumParams();
+    if (ExpectedCallingConv == ActualCallingConv && NumParams == 0)
+      continue;
+
+    if (LastExportedDefaultCtor) {
+      S.Diag(LastExportedDefaultCtor->getLocation(),
+             diag::err_attribute_dll_ambiguous_default_ctor) << Class;
+      S.Diag(CD->getLocation(), diag::note_entity_declared_at)
+          << CD->getDeclName();
+      return;
+    }
+    LastExportedDefaultCtor = CD;
+
+    for (unsigned I = 0; I != NumParams; ++I) {
       // Skip any default arguments that we've already instantiated.
       if (S.Context.getDefaultArgExprForConstructor(CD, I))
         continue;

Modified: cfe/trunk/test/SemaCXX/dllexport.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/dllexport.cpp?rev=256661&r1=256660&r2=256661&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/dllexport.cpp (original)
+++ cfe/trunk/test/SemaCXX/dllexport.cpp Wed Dec 30 23:36:46 2015
@@ -730,7 +730,12 @@ __declspec(dllexport)        int  Member
 __declspec(dllexport) const  int  MemberRedecl::StaticConstField = 1;  // 
expected-error{{redeclaration of 'MemberRedecl::StaticConstField' cannot add 
'dllexport' attribute}}
 __declspec(dllexport) constexpr int MemberRedecl::ConstexprField;      // 
expected-error{{redeclaration of 'MemberRedecl::ConstexprField' cannot add 
'dllexport' attribute}}
 
-
+#ifdef MS
+struct __declspec(dllexport) ClassWithMultipleDefaultCtors {
+  ClassWithMultipleDefaultCtors(int = 40) {} // 
expected-error{{'__declspec(dllexport)' cannot be applied to more than one 
default constructor}}
+  ClassWithMultipleDefaultCtors(int = 30, ...) {} // expected-note{{declared 
here}}
+};
+#endif
 
 
//===----------------------------------------------------------------------===//
 // Class member templates


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

Reply via email to