aboutsummaryrefslogtreecommitdiff
path: root/include/clang
diff options
context:
space:
mode:
Diffstat (limited to 'include/clang')
-rw-r--r--include/clang/AST/ASTContext.h23
-rw-r--r--include/clang/Basic/TargetCXXABI.h41
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);