This revision was automatically updated to reflect the committed changes. Closed by commit rGb9d36540a85b: [dllexport] Avoid assert for explicitly defaulted methods in explicit… (authored by hans).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D90849/new/ https://reviews.llvm.org/D90849 Files: clang/lib/Sema/SemaDeclCXX.cpp clang/test/CodeGenCXX/dllexport.cpp Index: clang/test/CodeGenCXX/dllexport.cpp =================================================================== --- clang/test/CodeGenCXX/dllexport.cpp +++ clang/test/CodeGenCXX/dllexport.cpp @@ -915,6 +915,36 @@ // M32-DAG: define dso_local x86_thiscallcc void @"??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ" } +namespace pr47683 { +struct X { X() {} }; + +template <typename> struct S { + S() = default; + X x; +}; +template struct __declspec(dllexport) S<int>; +// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.pr47683::S"* @"??0?$S@H@pr47683@@QAE@XZ" + +template <typename> struct T { + T() = default; + X x; +}; +extern template struct T<int>; +template struct __declspec(dllexport) T<int>; +// 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" + +template <typename> struct U { + U(); + X x; +}; +template <typename T> U<T>::U() = default; +extern template struct U<int>; +template struct __declspec(dllexport) U<int>; +// Same as T, but with out-of-line ctor. +// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.pr47683::U"* @"??0?$U@H@pr47683@@QAE@XZ" +} + //===----------------------------------------------------------------------===// // Classes with template base classes //===----------------------------------------------------------------------===// Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -5895,13 +5895,22 @@ // The function will be passed to the consumer when its definition is // encountered. - } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || + } else if (MD->isExplicitlyDefaulted()) { + // Synthesize and instantiate explicitly defaulted methods. + S.MarkFunctionReferenced(Class->getLocation(), MD); + + if (TSK != TSK_ExplicitInstantiationDefinition) { + // Except for explicit instantiation defs, we will not see the + // definition again later, so pass it to the consumer now. + S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); + } + } else if (!MD->isTrivial() || MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) { - // Synthesize and instantiate non-trivial implicit methods, explicitly - // defaulted methods, and the copy and move assignment operators. The - // latter are exported even if they are trivial, because the address of - // an operator can be taken and should compare equal across libraries. + // Synthesize and instantiate non-trivial implicit methods, and the copy + // and move assignment operators. The latter are exported even if they + // are trivial, because the address of 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
Index: clang/test/CodeGenCXX/dllexport.cpp =================================================================== --- clang/test/CodeGenCXX/dllexport.cpp +++ clang/test/CodeGenCXX/dllexport.cpp @@ -915,6 +915,36 @@ // M32-DAG: define dso_local x86_thiscallcc void @"??$baz@H@?$ExportedClassTemplate2@H@pr34849@@QAEXXZ" } +namespace pr47683 { +struct X { X() {} }; + +template <typename> struct S { + S() = default; + X x; +}; +template struct __declspec(dllexport) S<int>; +// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.pr47683::S"* @"??0?$S@H@pr47683@@QAE@XZ" + +template <typename> struct T { + T() = default; + X x; +}; +extern template struct T<int>; +template struct __declspec(dllexport) T<int>; +// 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" + +template <typename> struct U { + U(); + X x; +}; +template <typename T> U<T>::U() = default; +extern template struct U<int>; +template struct __declspec(dllexport) U<int>; +// Same as T, but with out-of-line ctor. +// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.pr47683::U"* @"??0?$U@H@pr47683@@QAE@XZ" +} + //===----------------------------------------------------------------------===// // Classes with template base classes //===----------------------------------------------------------------------===// Index: clang/lib/Sema/SemaDeclCXX.cpp =================================================================== --- clang/lib/Sema/SemaDeclCXX.cpp +++ clang/lib/Sema/SemaDeclCXX.cpp @@ -5895,13 +5895,22 @@ // The function will be passed to the consumer when its definition is // encountered. - } else if (!MD->isTrivial() || MD->isExplicitlyDefaulted() || + } else if (MD->isExplicitlyDefaulted()) { + // Synthesize and instantiate explicitly defaulted methods. + S.MarkFunctionReferenced(Class->getLocation(), MD); + + if (TSK != TSK_ExplicitInstantiationDefinition) { + // Except for explicit instantiation defs, we will not see the + // definition again later, so pass it to the consumer now. + S.Consumer.HandleTopLevelDecl(DeclGroupRef(MD)); + } + } else if (!MD->isTrivial() || MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()) { - // Synthesize and instantiate non-trivial implicit methods, explicitly - // defaulted methods, and the copy and move assignment operators. The - // latter are exported even if they are trivial, because the address of - // an operator can be taken and should compare equal across libraries. + // Synthesize and instantiate non-trivial implicit methods, and the copy + // and move assignment operators. The latter are exported even if they + // are trivial, because the address of 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
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits