================
@@ -292,77 +294,129 @@ Sema::CheckCXX2CRelocatableAndReplaceable(const 
CXXRecordDecl *D) {
       return HasSuitableSMP();
 
     // is a union with no user-declared special member functions, or
-    if (IsUnion())
+    if (IsTrivialUnion())
       return HasSuitableSMP();
 
     // is default-movable.
     return IsDefaultMovable();
   }();
 
+  bool PtrauthMatters = LangOpts.PointerAuthIntrinsics ||
+                        LangOpts.PointerAuthVTPtrAddressDiscrimination;
+  if (PtrauthMatters) {
+    bool IsUnion = D->isUnion();
+    auto RecordPointerAuth = [&](bool HasAddressDiscrimination) {
+      if (HasAddressDiscrimination && IsUnion) {
+        Info.IsRelocatable = false;
+        Info.IsReplaceable = false;
+      }
+    };
+    auto IsBottomRelocationInfo = [](const CXXRecordDeclRelocationInfo &Info) {
+      return !Info.IsReplaceable && !Info.IsRelocatable;
+    };
+
+    if (D->isPolymorphic())
+      
RecordPointerAuth(Context.hasAddressDiscriminatedVTableAuthentication(D));
+    for (auto Base : D->bases()) {
+      if (IsBottomRelocationInfo(Info))
+        break;
+      bool BaseHasPtrauth =
+          Context.containsAddressDiscriminatedPointerAuth(Base.getType());
+      RecordPointerAuth(BaseHasPtrauth);
+    }
+    for (auto *FieldDecl : D->fields()) {
+      if (IsBottomRelocationInfo(Info))
+        break;
+      bool FieldHasPtrauth =
+          
Context.containsAddressDiscriminatedPointerAuth(FieldDecl->getType());
+      RecordPointerAuth(FieldHasPtrauth);
+    }
+  }
+  Context.setRelocationInfoForCXXRecord(D, Info);
   return Info;
 }
 
-bool Sema::IsCXXTriviallyRelocatableType(const CXXRecordDecl &RD) {
-  if (std::optional<ASTContext::CXXRecordDeclRelocationInfo> Info =
-          getASTContext().getRelocationInfoForCXXRecord(&RD))
-    return Info->IsRelocatable;
-  ASTContext::CXXRecordDeclRelocationInfo Info =
-      CheckCXX2CRelocatableAndReplaceable(&RD);
-  getASTContext().setRelocationInfoForCXXRecord(&RD, Info);
-  return Info.IsRelocatable;
-}
+ASTContext::CXXRecordDeclRelocationInfo
+Sema::CheckCXX2CRelocatableAndReplaceable(QualType T) {
+  T = T.getCanonicalType();
+  enum class DirectRelocationInformation { Yes, No, Unknown };
+  DirectRelocationInformation Relocatable =
+      DirectRelocationInformation::Unknown;
+  DirectRelocationInformation Replaceable =
+      DirectRelocationInformation::Unknown;
+  DirectRelocationInformation ContainsAddressDiscriminatedValues =
+      DirectRelocationInformation::Unknown;
+
+  auto UpdateRelocatable = [&](DirectRelocationInformation DRI) {
+    if (Relocatable == DirectRelocationInformation::Unknown ||
+        Relocatable == DirectRelocationInformation::Yes)
+      Relocatable = DRI;
+  };
+  auto UpdateReplaceable = [&](DirectRelocationInformation DRI) {
+    if (Replaceable == DirectRelocationInformation::Unknown ||
+        Replaceable == DirectRelocationInformation::Yes)
+      Replaceable = DRI;
+  };
+  auto UpdateAddressDiscrimination = [&](DirectRelocationInformation DRI) {
+    if (ContainsAddressDiscriminatedValues == DirectRelocationInformation::Yes)
+      Replaceable = DirectRelocationInformation::No;
+  };
 
-bool Sema::IsCXXTriviallyRelocatableType(QualType Type) {
+  if (T->isVariableArrayType()) {
+    UpdateRelocatable(DirectRelocationInformation::No);
+    UpdateReplaceable(DirectRelocationInformation::No);
+  }
 
-  QualType BaseElementType = getASTContext().getBaseElementType(Type);
+  if (T.isConstQualified() || T.isVolatileQualified())
+    UpdateReplaceable(DirectRelocationInformation::No);
 
-  if (Type->isVariableArrayType())
-    return false;
+  if (T.hasAddressDiscriminatedPointerAuth())
+    UpdateAddressDiscrimination(DirectRelocationInformation::Yes);
+
+  QualType BaseElementType =
+      SemaRef.getASTContext().getBaseElementType(T.getUnqualifiedType());
+
+  if (BaseElementType->isIncompleteType()) {
+    Relocatable = DirectRelocationInformation::No;
+    Replaceable = DirectRelocationInformation::No;
+  }
 
   if (BaseElementType.hasNonTrivialObjCLifetime())
-    return false;
+    UpdateRelocatable(DirectRelocationInformation::No);
 
-  if (BaseElementType.hasAddressDiscriminatedPointerAuth())
-    return false;
+  if (BaseElementType->isScalarType()) {
+    UpdateRelocatable(DirectRelocationInformation::Yes);
+    UpdateReplaceable(DirectRelocationInformation::Yes);
+    UpdateAddressDiscrimination(DirectRelocationInformation::No);
+  }
 
-  if (BaseElementType->isIncompleteType())
-    return false;
+  if (BaseElementType->isVectorType())
+    UpdateRelocatable(DirectRelocationInformation::Yes);
 
-  if (BaseElementType->isScalarType() || BaseElementType->isVectorType())
-    return true;
+  auto CreateInfo = [=]() -> CXXRecordDeclRelocationInfo {
+    return {Relocatable == DirectRelocationInformation::Yes,
+            Replaceable == DirectRelocationInformation::Yes};
+  };
 
-  if (const auto *RD = BaseElementType->getAsCXXRecordDecl())
-    return IsCXXTriviallyRelocatableType(*RD);
+  if (BaseElementType->isIncompleteType())
+    return CreateInfo();
 
-  return false;
+  const CXXRecordDecl *RD = BaseElementType->getAsCXXRecordDecl();
+  if (!RD)
+    return CreateInfo();
+
+  CXXRecordDeclRelocationInfo Info = CheckCXX2CRelocatableAndReplaceable(RD);
+  Info.IsRelocatable &= Relocatable != DirectRelocationInformation::No;
+  Info.IsReplaceable &= Replaceable != DirectRelocationInformation::No;
+  return Info;
----------------
cor3ntin wrote:

Github ate my comment earlier.
I'm not convinced that trying to merge replaceable and relocatable improves 
readability.
Especially given we compute them lazily, and I suspect needing to know if a 
type is replaceable will be fairly less frequent. I think having to (mentally) 
track these 3 tribools is not easy and we don;t really know how these 
properties will diverge over time.

So I would prefer they remain separate for the time being.
 

https://github.com/llvm/llvm-project/pull/143796
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to