r318474 - PR22763: if a defaulted (non-user-provided) special member function is
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 16 15:54:56 PST 2017
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>;
+}
More information about the cfe-commits
mailing list