]> granicus.if.org Git - clang/commitdiff
[MS] Mark default args of exported default constructors as used
authorReid Kleckner <rnk@google.com>
Mon, 9 Jan 2017 17:27:17 +0000 (17:27 +0000)
committerReid Kleckner <rnk@google.com>
Mon, 9 Jan 2017 17:27:17 +0000 (17:27 +0000)
Fixes a regression introduced in r291045, which would lead to link
errors. While we should no longer encounter unparsed or uninstantiated
default arguments in this codepath, we still need to call
CheckCXXDefaultArgExpr to mark the default argument expressions as
ODR-used.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@291453 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDeclCXX.cpp
test/CodeGenCXX/dllexport-ctor-closure.cpp

index 02b73e9113fa9e343eb4e03a786f2c22a008e406..a70e16cce18ce6f3c9c2df4ada2add590482d4d9 100644 (file)
@@ -5395,14 +5395,32 @@ static void ReferenceDllExportedMethods(Sema &S, CXXRecordDecl *Class) {
   }
 }
 
-static void checkForMultipleExportedDefaultConstructors(Sema &S, CXXRecordDecl *Class) {
+static void checkForMultipleExportedDefaultConstructors(Sema &S,
+                                                        CXXRecordDecl *Class) {
+  // Only the MS ABI has default constructor closures, so we don't need to do
+  // this semantic checking anywhere else.
+  if (!S.Context.getTargetInfo().getCXXABI().isMicrosoft())
+    return;
+
   CXXConstructorDecl *LastExportedDefaultCtor = nullptr;
   for (Decl *Member : Class->decls()) {
     // Look for exported default constructors.
     auto *CD = dyn_cast<CXXConstructorDecl>(Member);
-    if (!CD || !CD->isDefaultConstructor() || !CD->hasAttr<DLLExportAttr>())
+    if (!CD || !CD->isDefaultConstructor())
+      continue;
+    auto *Attr = CD->getAttr<DLLExportAttr>();
+    if (!Attr)
       continue;
 
+    // If the class is non-dependent, mark the default arguments as ODR-used so
+    // that we can properly codegen the constructor closure.
+    if (!Class->isDependentContext()) {
+      for (ParmVarDecl *PD : CD->parameters()) {
+        (void)S.CheckCXXDefaultArgExpr(Attr->getLocation(), CD, PD);
+        S.DiscardCleanupsInEvaluationContext();
+      }
+    }
+
     if (LastExportedDefaultCtor) {
       S.Diag(LastExportedDefaultCtor->getLocation(),
              diag::err_attribute_dll_ambiguous_default_ctor)
index 24a2ba6bdea2027820dbea080abebfe1667dcd5e..4fae7e10e8b6c677046860c1149e1f0e5d7b92c4 100644 (file)
@@ -61,3 +61,22 @@ struct __declspec(dllexport) NestedOuter {
 
 // CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
 // CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FNestedInner@NestedOuter@@QAEXXZ"({{.*}}) {{#[0-9]+}} comdat
+
+struct HasDtor {
+  ~HasDtor();
+  int o;
+};
+struct HasImplicitDtor1 { HasDtor o; };
+struct HasImplicitDtor2 { HasDtor o; };
+struct __declspec(dllexport) CtorClosureInline {
+  CtorClosureInline(const HasImplicitDtor1 &v = {}) {}
+};
+struct __declspec(dllexport) CtorClosureOutOfLine {
+  CtorClosureOutOfLine(const HasImplicitDtor2 &v = {});
+};
+CtorClosureOutOfLine::CtorClosureOutOfLine(const HasImplicitDtor2 &v) {}
+
+// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorClosureInline@@QAEXXZ"
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??1HasImplicitDtor1@@QAE@XZ"
+// CHECK-LABEL: define weak_odr dllexport x86_thiscallcc void @"\01??_FCtorClosureOutOfLine@@QAEXXZ"
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01??1HasImplicitDtor2@@QAE@XZ"