Author: rsmith Date: Thu Nov 16 15:54:56 2017 New Revision: 318474 URL: http://llvm.org/viewvc/llvm-project?rev=318474&view=rev Log: PR22763: if a defaulted (non-user-provided) special member function is explicitly instantiated, still emit it with each use.
We don't emit a definition of the member with an explicit instantiation definition (and indeed it appears that we're not allowed to, since an explicit instantiation definition does not constitute an odr-use and only odr-use permits definition for defaulted special members). So we still need to emit a weak definition with each use. This also makes defaulted-in-class declarations behave more like implicitly-declared special members, which matches their design intent. And it matches the way this problem was solved in GCC. Modified: cfe/trunk/include/clang/AST/DeclCXX.h cfe/trunk/lib/AST/ASTContext.cpp cfe/trunk/test/CodeGenCXX/cxx11-special-members.cpp cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp Modified: cfe/trunk/include/clang/AST/DeclCXX.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=318474&r1=318473&r2=318474&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclCXX.h (original) +++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Nov 16 15:54:56 2017 @@ -2061,7 +2061,11 @@ public: /// True if this method is user-declared and was not /// deleted or defaulted on its first declaration. bool isUserProvided() const { - return !(isDeleted() || getCanonicalDecl()->isDefaulted()); + auto *DeclAsWritten = this; + if (auto *Pattern = getTemplateInstantiationPattern()) + DeclAsWritten = cast<CXXMethodDecl>(Pattern); + return !(DeclAsWritten->isDeleted() || + DeclAsWritten->getCanonicalDecl()->isDefaulted()); } void addOverriddenMethod(const CXXMethodDecl *MD); Modified: cfe/trunk/lib/AST/ASTContext.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=318474&r1=318473&r2=318474&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTContext.cpp (original) +++ cfe/trunk/lib/AST/ASTContext.cpp Thu Nov 16 15:54:56 2017 @@ -8963,6 +8963,12 @@ static GVALinkage basicGVALinkageForFunc if (!FD->isExternallyVisible()) return GVA_Internal; + // Non-user-provided functions get emitted as weak definitions with every + // use, no matter whether they've been explicitly instantiated etc. + if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) + if (!MD->isUserProvided()) + return GVA_DiscardableODR; + GVALinkage External; switch (FD->getTemplateSpecializationKind()) { case TSK_Undeclared: Modified: cfe/trunk/test/CodeGenCXX/cxx11-special-members.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx11-special-members.cpp?rev=318474&r1=318473&r2=318474&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/cxx11-special-members.cpp (original) +++ cfe/trunk/test/CodeGenCXX/cxx11-special-members.cpp Thu Nov 16 15:54:56 2017 @@ -39,7 +39,9 @@ void f3() { C<0> a; D b; } -// CHECK: define {{.*}} @_ZN1CILi0EEC1Ev +// Trivial default ctor, might or might not be defined, but we must not expect +// someone else ot define it. +// CHECK-NOT: declare {{.*}} @_ZN1CILi0EEC1Ev // CHECK: define {{.*}} @_ZN1DC1Ev // CHECK: define {{.*}} @_ZN1BC2EOS_( Modified: cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp?rev=318474&r1=318473&r2=318474&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp (original) +++ cfe/trunk/test/CodeGenCXX/explicit-instantiation.cpp Thu Nov 16 15:54:56 2017 @@ -170,3 +170,22 @@ void use() { f<int>(); } } + +namespace DefaultedMembers { + struct B { B(); B(const B&); ~B(); }; + template<typename T> struct A : B { + A() = default; + ~A() = default; + }; + extern template struct A<int>; + + // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiEC2Ev + // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiED2Ev + A<int> ai; + + // CHECK-LABEL: define {{.*}} @_ZN16DefaultedMembers1AIiEC2ERKS1_ + A<int> ai2(ai); + + // CHECK-NOT: @_ZN16DefaultedMembers1AIcE + template struct A<char>; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits