================
@@ -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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to