Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -5904,9 +5904,14 @@ // an operator can be taken and should compare equal across libraries. S.MarkFunctionReferenced(Class->getLocation(), MD); - // There is no later point when we will see the definition of this - // function, so pass it to the consumer now. - S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); + if (MD->isExplicitlyDefaulted() && + TSK == TSK_ExplicitInstantiationDefinition) { + // MD will get passed to the consumer as part of instantiation. + } else { + // There is no later point when we will see the definition of this + // function, so pass it to the consumer now. + S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); + } } } } Index: clang/test/CodeGenCXX/dllexport.cpp =================================================================== --- clang/test/CodeGenCXX/dllexport.cpp +++ clang/test/CodeGenCXX/dllexport.cpp @@ -915,6 +915,26 @@ // M32-DAG: define dso_local x86_thiscallcc void @"??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ" } +namespace pr47683 { +struct X { X() {} }; + +template struct S { + S() = default; + X x; +}; +template struct __declspec(dllexport) S; +// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.pr47683::S"* @"??0?$S@H@pr47683@@QAE@XZ" + +template struct T { + T() = default; + X x; +}; +extern template struct T; +template struct __declspec(dllexport) T; +// Don't assert about multiple codegen for explicitly defaulted method in explicit instantiation def. +// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.pr47683::T"* @"??0?$T@H@pr47683@@QAE@XZ" +} + //===----------------------------------------------------------------------===// // Classes with template base classes //===----------------------------------------------------------------------===//