diff options
Diffstat (limited to 'include/clang')
-rw-r--r-- | include/clang/AST/ASTContext.h | 23 | ||||
-rw-r--r-- | include/clang/Basic/TargetCXXABI.h | 41 |
2 files changed, 59 insertions, 5 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 05f818299b..bf0487198d 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -1563,14 +1563,27 @@ public: const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const; - /// \brief Get the key function for the given record decl, or NULL if there - /// isn't one. + /// \brief Get our current best idea for the key function of the + /// given record decl, or NULL if there isn't one. /// /// The key function is, according to the Itanium C++ ABI section 5.2.3: + /// ...the first non-pure virtual function that is not inline at the + /// point of class definition. /// - /// ...the first non-pure virtual function that is not inline at the point - /// of class definition. - const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); + /// Other ABIs use the same idea. However, the ARM C++ ABI ignores + /// virtual functions that are defined 'inline', which means that + /// the result of this computation can change. + const CXXMethodDecl *getCurrentKeyFunction(const CXXRecordDecl *RD); + + /// \brief Observe that the given method cannot be a key function. + /// Checks the key-function cache for the method's class and clears it + /// if matches the given declaration. + /// + /// This is used in ABIs where out-of-line definitions marked + /// inline are not considered to be key functions. + /// + /// \param method should be the declaration from the class definition + void setNonKeyFunction(const CXXMethodDecl *method); /// Get the offset of a FieldDecl or IndirectFieldDecl, in bits. uint64_t getFieldOffset(const ValueDecl *FD) const; diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h index 2a8f5d0df5..1a8e62c16d 100644 --- a/include/clang/Basic/TargetCXXABI.h +++ b/include/clang/Basic/TargetCXXABI.h @@ -142,6 +142,47 @@ public: return isItaniumFamily(); } + /// \brief Can an out-of-line inline function serve as a key function? + /// + /// This flag is only useful in ABIs where type data (for example, + /// v-tables and type_info objects) are emitted only after processing + /// the definition of a special "key" virtual function. (This is safe + /// because the ODR requires that every virtual function be defined + /// somewhere in a program.) This usually permits such data to be + /// emitted in only a single object file, as opposed to redundantly + /// in every object file that requires it. + /// + /// One simple and common definition of "key function" is the first + /// virtual function in the class definition which is not defined there. + /// This rule works very well when that function has a non-inline + /// definition in some non-header file. Unfortunately, when that + /// function is defined inline, this rule requires the type data + /// to be emitted weakly, as if there were no key function. + /// + /// The ARM ABI observes that the ODR provides an additional guarantee: + /// a virtual function is always ODR-used, so if it is defined inline, + /// that definition must appear in every translation unit that defines + /// the class. Therefore, there is no reason to allow such functions + /// to serve as key functions. + /// + /// Because this changes the rules for emitting type data, + /// it can cause type data to be emitted with both weak and strong + /// linkage, which is not allowed on all platforms. Therefore, + /// exploiting this observation requires an ABI break and cannot be + /// done on a generic Itanium platform. + bool canKeyFunctionBeInline() const { + switch (getKind()) { + case GenericARM: + return false; + + case GenericItanium: + case iOS: // old iOS compilers did not follow this rule + case Microsoft: + return true; + } + llvm_unreachable("bad ABI kind"); + } + /// Try to parse an ABI name, returning false on error. bool tryParse(llvm::StringRef name); |