From 82713bf35259707c9659f81ec260d75ed6479bb6 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 9 Jan 2017 17:27:17 +0000 Subject: [PATCH] [MS] Mark default args of exported default constructors as used 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. llvm-svn: 291453 --- clang/lib/Sema/SemaDeclCXX.cpp | 22 +++++++++++++++++-- .../CodeGenCXX/dllexport-ctor-closure.cpp | 19 ++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 02b73e9113fa..a70e16cce18c 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5395,13 +5395,31 @@ 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(Member); - if (!CD || !CD->isDefaultConstructor() || !CD->hasAttr()) + if (!CD || !CD->isDefaultConstructor()) continue; + auto *Attr = CD->getAttr(); + 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(), diff --git a/clang/test/CodeGenCXX/dllexport-ctor-closure.cpp b/clang/test/CodeGenCXX/dllexport-ctor-closure.cpp index 24a2ba6bdea2..4fae7e10e8b6 100644 --- a/clang/test/CodeGenCXX/dllexport-ctor-closure.cpp +++ b/clang/test/CodeGenCXX/dllexport-ctor-closure.cpp @@ -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"