summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp26
1 files changed, 24 insertions, 2 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 9efcb52d148..d584ed85710 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6362,9 +6362,31 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
}
} 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);
+ }
+ }
+ }
}
}
OpenPOWER on IntegriCloud