diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 2 |
3 files changed, 26 insertions, 4 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 19da55cd25b..c03d41eb043 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -543,7 +543,7 @@ void Sema::ActOnEndOfTranslationUnit() { 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/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); + } + } + } } } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 515fd91a6b8..448d083aaf2 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11217,7 +11217,7 @@ bool Sema::DefineUsedVTables() { // 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: |