[dllexport] Avoid assert for explicitly defaulted methods in explicit instantiation definitions (PR47683)

Clang was asserting due to attempting to codegen such methods twice.

Differential revision: https://reviews.llvm.org/D90849
This commit is contained in:
Hans Wennborg 2020-11-05 13:44:50 +01:00
parent f9265de8c6
commit b9d36540a8
2 changed files with 44 additions and 5 deletions
clang
lib/Sema
test/CodeGenCXX

View File

@ -5895,13 +5895,22 @@ static void ReferenceDllExportedMembers(Sema &S, CXXRecordDecl *Class) {
// 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

View File

@ -915,6 +915,36 @@ template<> template<> void ExportedClassTemplate2<int>::baz<int>() {}
// 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
//===----------------------------------------------------------------------===//