[clang] [Clang] Reuse tail-padding for more types that are not POD for the purpose of layout (PR #90462)
John McCall via cfe-commits
cfe-commits at lists.llvm.org
Wed May 22 09:28:16 PDT 2024
================
@@ -2415,46 +2415,112 @@ DiagnosticBuilder ItaniumRecordLayoutBuilder::Diag(SourceLocation Loc,
return Context.getDiagnostics().Report(Loc, DiagID);
}
+/// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#POD
+/// POD for the purpose of layout
+/// In general, a type is considered a POD for the purposes of layout if it is
+/// a POD type (in the sense of ISO C++ [basic.types]). However, a type is not
+/// considered to be a POD for the purpose of layout if it is:
+/// - a POD-struct or POD-union (in the sense of ISO C++ [class]) with a
+/// bit-field whose declared width is wider than the declared type of the
+/// bit-field, or
+/// - an array type whose element type is not a POD for the purpose of
+/// layout, or
+/// - a POD-struct with one or more potentially-overlapping non-static data
+/// members.
+/// Where references to the ISO C++ are made in this paragraph, the Technical
+/// Corrigendum 1 version of the standard is intended.
+///
+/// This function does not check if the type is POD first
+static bool isItaniumPOD(const ASTContext &Context, const CXXRecordDecl *RD) {
+ const auto IsDisqualifying = [&](const FieldDecl *FD) -> bool {
+ if (FD->isBitField())
+ if (FD->getBitWidthValue(Context) > Context.getTypeSize(FD->getType()))
+ return true;
+
+ return FD->isPotentiallyOverlapping();
+ };
+
+ if (llvm::any_of(RD->fields(), IsDisqualifying))
+ return false;
+
+ return RD->forallBases([&](const CXXRecordDecl *Base) -> bool {
+ return llvm::any_of(Base->fields(), IsDisqualifying);
+ });
+}
+
/// Does the target C++ ABI require us to skip over the tail-padding
/// of the given class (considering it as a base class) when allocating
/// objects?
-static bool mustSkipTailPadding(TargetCXXABI ABI, const CXXRecordDecl *RD) {
- switch (ABI.getTailPaddingUseRules()) {
- case TargetCXXABI::AlwaysUseTailPadding:
- return false;
+static bool mustSkipTailPadding(const ASTContext &Context, TargetCXXABI ABI,
+ const CXXRecordDecl *RD) {
+ // This is equivalent to
+ // Context.getTypeDeclType(RD).isCXX11PODType(Context),
+ // but with a lot of abstraction penalty stripped off. This does
+ // assume that these properties are set correctly even in C++98
+ // mode; fortunately, that is true because we want to assign
+ // consistently semantics to the type-traits intrinsics (or at
+ // least as many of them as possible).
+ auto IsCXX11PODType = [&]() -> bool {
+ return RD->isTrivial() && RD->isCXX11StandardLayout();
+ };
+
+ if (Context.getLangOpts().getClangABICompat() <=
+ LangOptions::ClangABI::Ver18) {
+ switch (ABI.getKind()) {
+ // ABIs derived from Itanium: In Clang 18, did not check for over-large
+ // bit-fields or potentially overlapping members
+ case TargetCXXABI::GenericItanium:
+ case TargetCXXABI::GenericAArch64:
+ case TargetCXXABI::GenericARM:
+ case TargetCXXABI::iOS:
+ case TargetCXXABI::GenericMIPS:
+ case TargetCXXABI::XL:
+ return RD->isPOD();
+
+ case TargetCXXABI::AppleARM64:
+ case TargetCXXABI::Fuchsia:
+ case TargetCXXABI::WebAssembly:
+ case TargetCXXABI::WatchOS:
+ return IsCXX11PODType();
+
+ case TargetCXXABI::Microsoft:
+ return true;
+ }
+ llvm_unreachable("bad ABI kind");
+ }
----------------
rjmccall wrote:
I think this would be a lot cleaner overall with a single switch over the C++ ABIs, even if it makes the individual conditions slightly more complex.
https://github.com/llvm/llvm-project/pull/90462
More information about the cfe-commits
mailing list