The standard ARM C++ ABI dictates that inline functions are
never key functions. We did not implement that rule for the
iOS ABI, which was driven by what was implemented in gcc-4.2.
However, implement it now for other ARM-based platforms.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173515 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 19da55c..c03d41e 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -543,7 +543,7 @@
I != E; ++I) {
assert(!(*I)->isDependentType() &&
"Should not see dependent types here!");
- if (const CXXMethodDecl *KeyFunction = Context.getKeyFunction(*I)) {
+ if (const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(*I)) {
const FunctionDecl *Definition = 0;
if (KeyFunction->hasBody(Definition))
MarkVTableUsed(Definition->getLocation(), *I, true);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9efcb52..d584ed8 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -6362,9 +6362,31 @@
}
} else {
- if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions
- NewFD->setAccess(OldDecl->getAccess());
+ // This needs to happen first so that 'inline' propagates.
NewFD->setPreviousDeclaration(cast<FunctionDecl>(OldDecl));
+
+ if (isa<CXXMethodDecl>(NewFD)) {
+ // A valid redeclaration of a C++ method must be out-of-line,
+ // but (unfortunately) it's not necessarily a definition
+ // because of templates, which means that the previous
+ // declaration is not necessarily from the class definition.
+
+ // For just setting the access, that doesn't matter.
+ CXXMethodDecl *oldMethod = cast<CXXMethodDecl>(OldDecl);
+ NewFD->setAccess(oldMethod->getAccess());
+
+ // Update the key-function state if necessary for this ABI.
+ if (NewFD->isInlined() &&
+ !Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
+ // setNonKeyFunction needs to work with the original
+ // declaration from the class definition, and isVirtual() is
+ // just faster in that case, so map back to that now.
+ oldMethod = cast<CXXMethodDecl>(oldMethod->getFirstDeclaration());
+ if (oldMethod->isVirtual()) {
+ Context.setNonKeyFunction(oldMethod);
+ }
+ }
+ }
}
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 515fd91..448d083 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -11217,7 +11217,7 @@
// If this class has a key function, but that key function is
// defined in another translation unit, we don't need to emit the
// vtable even though we're using it.
- const CXXMethodDecl *KeyFunction = Context.getKeyFunction(Class);
+ const CXXMethodDecl *KeyFunction = Context.getCurrentKeyFunction(Class);
if (KeyFunction && !KeyFunction->hasBody()) {
switch (KeyFunction->getTemplateSpecializationKind()) {
case TSK_Undeclared: