diff options
author | John McCall <rjmccall@apple.com> | 2013-01-25 22:31:03 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2013-01-25 22:31:03 +0000 |
commit | d5617eeafc93209a26b9f88276c88cf997c3a0a7 (patch) | |
tree | 43c9295b24bd0ef8787299fa08681e041ef4697b /lib/AST/RecordLayoutBuilder.cpp | |
parent | b8b2c9da87e7d70a1679db026f40548b3192b705 (diff) |
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
Diffstat (limited to 'lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 50 |
1 files changed, 40 insertions, 10 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 08f6d5c54b..72851dfa1e 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -795,8 +795,6 @@ protected: RecordLayoutBuilder(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION; void operator=(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION; -public: - static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD); }; } // end anonymous namespace @@ -2347,8 +2345,8 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, << D->getIdentifier(); } -const CXXMethodDecl * -RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { +static const CXXMethodDecl *computeKeyFunction(ASTContext &Context, + const CXXRecordDecl *RD) { // If a class isn't polymorphic it doesn't have a key function. if (!RD->isPolymorphic()) return 0; @@ -2366,6 +2364,9 @@ RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { TSK == TSK_ExplicitInstantiationDefinition) return 0; + bool allowInlineFunctions = + Context.getTargetInfo().getCXXABI().canKeyFunctionBeInline(); + for (CXXRecordDecl::method_iterator I = RD->method_begin(), E = RD->method_end(); I != E; ++I) { const CXXMethodDecl *MD = *I; @@ -2391,6 +2392,13 @@ RecordLayoutBuilder::ComputeKeyFunction(const CXXRecordDecl *RD) { if (!MD->isUserProvided()) continue; + // In certain ABIs, ignore functions with out-of-line inline definitions. + if (!allowInlineFunctions) { + const FunctionDecl *Def; + if (MD->hasBody(Def) && Def->isInlineSpecified()) + continue; + } + // We found it. return MD; } @@ -2496,15 +2504,37 @@ ASTContext::getASTRecordLayout(const RecordDecl *D) const { return *NewEntry; } -const CXXMethodDecl *ASTContext::getKeyFunction(const CXXRecordDecl *RD) { +const CXXMethodDecl *ASTContext::getCurrentKeyFunction(const CXXRecordDecl *RD) { + assert(RD->getDefinition() && "Cannot get key function for forward decl!"); RD = cast<CXXRecordDecl>(RD->getDefinition()); - assert(RD && "Cannot get key function for forward declarations!"); - const CXXMethodDecl *&Entry = KeyFunctions[RD]; - if (!Entry) - Entry = RecordLayoutBuilder::ComputeKeyFunction(RD); + const CXXMethodDecl *&entry = KeyFunctions[RD]; + if (!entry) { + entry = computeKeyFunction(*this, RD); + } + + return entry; +} + +void ASTContext::setNonKeyFunction(const CXXMethodDecl *method) { + assert(method == method->getFirstDeclaration() && + "not working with method declaration from class definition"); - return Entry; + // Look up the cache entry. Since we're working with the first + // declaration, its parent must be the class definition, which is + // the correct key for the KeyFunctions hash. + llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*>::iterator + i = KeyFunctions.find(method->getParent()); + + // If it's not cached, there's nothing to do. + if (i == KeyFunctions.end()) return; + + // If it is cached, check whether it's the target method, and if so, + // remove it from the cache. + if (i->second == method) { + // FIXME: remember that we did this for module / chained PCH state? + KeyFunctions.erase(i); + } } static uint64_t getFieldOffset(const ASTContext &C, const FieldDecl *FD) { |