[clang] Implement diagnostics for why `std::is_standard_layout` is false (PR #144161)
Samarth Narang via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 13 23:57:28 PDT 2025
================
@@ -2276,6 +2277,134 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef,
SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;
}
+static bool hasMixedAccessSpecifier(const CXXRecordDecl *D) {
+ AccessSpecifier FirstAccess = AS_none;
+ for (const FieldDecl *Field : D->fields()) {
+
+ if (Field->isUnnamedBitField())
+ continue;
+ AccessSpecifier FieldAccess = Field->getAccess();
+ if (FirstAccess == AS_none) {
+ FirstAccess = FieldAccess;
+ } else if (FieldAccess != FirstAccess) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool hasMultipleDataBaseClassesWithFields(const CXXRecordDecl *D) {
+ int NumBasesWithFields = 0;
+ for (const CXXBaseSpecifier &Base : D->bases()) {
+ const CXXRecordDecl *BaseRD = Base.getType()->getAsCXXRecordDecl();
+ if (!BaseRD || BaseRD->isInvalidDecl())
+ continue;
+
+ for (const FieldDecl *Field : BaseRD->fields()) {
+ if (!Field->isUnnamedBitField()) {
+ ++NumBasesWithFields;
+ break; // Only count the base once.
+ }
+ }
+ }
+ return NumBasesWithFields > 1;
+}
+
+static void DiagnoseNonStandardLayoutReason(Sema &SemaRef, SourceLocation Loc,
+ const CXXRecordDecl *D) {
+ for (const CXXBaseSpecifier &B : D->bases()) {
+ assert(B.getType()->getAsCXXRecordDecl() && "invalid base?");
+ if (B.isVirtual()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::VBase << B.getType()
+ << B.getSourceRange();
+ }
+ if (!B.getType()->isStandardLayoutType()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::NonStdLayoutBase << B.getType()
+ << B.getSourceRange();
+ }
+ }
+ if (hasMixedAccessSpecifier(D)) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::MixedAccess;
+ }
+ if (hasMultipleDataBaseClassesWithFields(D)) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::MultipleDataBase;
+ }
+ if (D->isPolymorphic()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::VirtualFunction;
+ }
+ for (const FieldDecl *Field : D->fields()) {
+ if (!Field->getType()->isStandardLayoutType()) {
+ SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason)
+ << diag::TraitNotSatisfiedReason::NonStdLayoutMember << Field
+ << Field->getType() << Field->getSourceRange();
+ }
+ }
+
+ // if this class and an indirect base
+ // both have non-static data members, grab the first such base.
+ if (D->hasDirectFields()) {
+ SmallVector<const CXXRecordDecl *, 4> Records;
+
+ // Recursive lambda to collect all bases that declare fields
+ std::function<void(const CXXRecordDecl *)> collect =
----------------
snarang181 wrote:
Done
https://github.com/llvm/llvm-project/pull/144161
More information about the cfe-commits
mailing list