[clang] [clang][NFC] Introduce `LangOptions::isCompatibleWith(ClangABI)` (PR #201067)

via cfe-commits cfe-commits at lists.llvm.org
Tue Jun 2 02:05:41 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-codegen

Author: Yanzuo Liu (zwuis)

<details>
<summary>Changes</summary>

This slightly improves readability and reduces the probability of off-by-one errors.

---
Full diff: https://github.com/llvm/llvm-project/pull/201067.diff


10 Files Affected:

- (modified) clang/include/clang/Basic/LangOptions.h (+4) 
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+1-1) 
- (modified) clang/lib/AST/DeclCXX.cpp (+1-2) 
- (modified) clang/lib/AST/ExprConstant.cpp (+1-1) 
- (modified) clang/lib/AST/ItaniumMangle.cpp (+10-12) 
- (modified) clang/lib/AST/RecordLayoutBuilder.cpp (+10-11) 
- (modified) clang/lib/Basic/TargetInfo.cpp (+3-3) 
- (modified) clang/lib/CodeGen/Targets/ARM.cpp (+1-2) 
- (modified) clang/lib/CodeGen/Targets/X86.cpp (+8-8) 
- (modified) clang/lib/Sema/SemaDeclCXX.cpp (+3-3) 


``````````diff
diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h
index 64b12b6fd72c7..9af036156b1ad 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -668,6 +668,10 @@ class LangOptions : public LangOptionsBase {
            !ObjCSubscriptingLegacyRuntime;
   }
 
+  bool isCompatibleWith(ClangABI Version) const {
+    return getClangABICompat() <= Version;
+  }
+
   bool isCompatibleWithMSVC() const { return MSCompatibilityVersion > 0; }
 
   bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const {
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 774a853950837..25281558dafbf 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -2501,7 +2501,7 @@ bool Compiler<Emitter>::VisitEmbedExpr(const EmbedExpr *E) {
 static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
                              UnaryExprOrTypeTrait Kind) {
   bool AlignOfReturnsPreferred =
-      ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
+      ASTCtx.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver7);
 
   // C++ [expr.alignof]p3:
   //     When alignof is applied to a reference type, the result is the
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 2de8ba8f484f4..fc8a15287f438 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -990,8 +990,7 @@ void CXXRecordDecl::addedMember(Decl *D) {
       //   T is a class type [...] with [...] no unnamed bit-fields of non-zero
       //   length
       if (data().Empty && !Field->isZeroLengthBitField() &&
-          Context.getLangOpts().getClangABICompat() >
-              LangOptions::ClangABI::Ver6)
+          !Context.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver6))
         data().Empty = false;
       return;
     }
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 808c9b4f89ed9..b9635deeccb33 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10243,7 +10243,7 @@ static CharUnits GetAlignOfType(const ASTContext &Ctx, QualType T,
     return CharUnits::One();
 
   const bool AlignOfReturnsPreferred =
-      Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
+      Ctx.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver7);
 
   // __alignof is defined to return the preferred alignment.
   // Before 8, clang returned the preferred alignment for alignof and _Alignof
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 1cb6fa05f22ac..b7afe64027b91 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -381,7 +381,7 @@ class CXXNameMangler {
   ASTContext &getASTContext() const { return Context.getASTContext(); }
 
   bool isCompatibleWith(LangOptions::ClangABI Ver) {
-    return Context.getASTContext().getLangOpts().getClangABICompat() <= Ver;
+    return getASTContext().getLangOpts().isCompatibleWith(Ver);
   }
 
   bool isStd(const NamespaceDecl *NS);
@@ -698,8 +698,8 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) {
       return getASTContext().getTranslationUnitDecl();
   }
 
-  if (const auto *FD = getASTContext().getLangOpts().getClangABICompat() >
-                               LangOptions::ClangABI::Ver19
+  if (const auto *FD = !getASTContext().getLangOpts().isCompatibleWith(
+                           LangOptions::ClangABI::Ver19)
                            ? D->getAsFunction()
                            : dyn_cast<FunctionDecl>(D)) {
     if (FD->isExternC())
@@ -707,8 +707,8 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) {
     // Member-like constrained friends are mangled as if they were members of
     // the enclosing class.
     if (FD->isMemberLikeConstrainedFriend() &&
-        getASTContext().getLangOpts().getClangABICompat() >
-            LangOptions::ClangABI::Ver17)
+        !getASTContext().getLangOpts().isCompatibleWith(
+            LangOptions::ClangABI::Ver17))
       return D->getLexicalDeclContext()->getRedeclContext();
   }
 
@@ -2975,13 +2975,13 @@ static bool isTypeSubstitutable(Qualifiers Quals, const Type *Ty,
     return true;
   // From Clang 18.0 we correctly treat SVE types as substitution candidates.
   if (Ty->isSVESizelessBuiltinType() &&
-      Ctx.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver17)
+      !Ctx.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver17))
     return true;
   if (Ty->isBuiltinType())
     return false;
   // Through to Clang 6.0, we accidentally treated undeduced auto types as
   // substitution candidates.
-  if (Ctx.getLangOpts().getClangABICompat() > LangOptions::ClangABI::Ver6 &&
+  if (!Ctx.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver6) &&
       isa<AutoType>(Ty))
     return false;
   // A placeholder type for class template deduction is substitutable with
@@ -6827,8 +6827,7 @@ void CXXNameMangler::mangleValueInTemplateArg(QualType T, const APValue &V,
       // Clang 11 and before mangled an array subject to array-to-pointer decay
       // as if it were the declaration itself.
       bool IsArrayToPointerDecayMangledAsDecl = false;
-      if (TopLevel && Ctx.getLangOpts().getClangABICompat() <=
-                          LangOptions::ClangABI::Ver11) {
+      if (TopLevel && isCompatibleWith(LangOptions::ClangABI::Ver11)) {
         QualType BType = B.getType();
         IsArrayToPointerDecayMangledAsDecl =
             BType->isArrayType() && V.getLValuePath().size() == 1 &&
@@ -7567,9 +7566,8 @@ void ItaniumMangleContextImpl::mangleCXXCtorVTable(const CXXRecordDecl *RD,
   Mangler.getStream() << "_ZTC";
   // Older versions of clang did not add the record as a substitution candidate
   // here.
-  bool SuppressSubstitution =
-      getASTContext().getLangOpts().getClangABICompat() <=
-      LangOptions::ClangABI::Ver19;
+  bool SuppressSubstitution = getASTContext().getLangOpts().isCompatibleWith(
+      LangOptions::ClangABI::Ver19);
   Mangler.mangleCXXRecordDecl(RD, SuppressSubstitution);
   Mangler.getStream() << Offset;
   Mangler.getStream() << '_';
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp
index f417588accd78..854f88f20b2b6 100644
--- a/clang/lib/AST/RecordLayoutBuilder.cpp
+++ b/clang/lib/AST/RecordLayoutBuilder.cpp
@@ -1213,8 +1213,8 @@ ItaniumRecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) {
   auto getBaseOrPreferredBaseAlignFromUnpacked = [&](CharUnits UnpackedAlign) {
     // Clang <= 6 incorrectly applied the 'packed' attribute to base classes.
     // Per GCC's documentation, it only applies to non-static data members.
-    return (Packed && ((Context.getLangOpts().getClangABICompat() <=
-                        LangOptions::ClangABI::Ver6) ||
+    return (Packed && (Context.getLangOpts().isCompatibleWith(
+                           LangOptions::ClangABI::Ver6) ||
                        Context.getTargetInfo().getTriple().isPS() ||
                        Context.getTargetInfo().getTriple().isOSAIX()))
                ? CharUnits::One()
@@ -1960,13 +1960,13 @@ void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D,
     }
   }
 
-  bool FieldPacked = (Packed && (!FieldClass || FieldClass->isPOD() ||
-                                 FieldClass->hasAttr<PackedAttr>() ||
-                                 Context.getLangOpts().getClangABICompat() <=
-                                     LangOptions::ClangABI::Ver15 ||
-                                 Target.isPS() || Target.isOSDarwin() ||
-                                 Target.isOSAIX())) ||
-                     D->hasAttr<PackedAttr>();
+  bool FieldPacked =
+      (Packed &&
+       (!FieldClass || FieldClass->isPOD() ||
+        FieldClass->hasAttr<PackedAttr>() ||
+        Context.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver15) ||
+        Target.isPS() || Target.isOSDarwin() || Target.isOSAIX())) ||
+      D->hasAttr<PackedAttr>();
 
   // When used as part of a typedef, or together with a 'packed' attribute, the
   // 'aligned' attribute can be used to decrease alignment. In that case, it
@@ -2204,8 +2204,7 @@ void ItaniumRecordLayoutBuilder::FinishLayout(const NamedDecl *D) {
     if (Packed && UnpackedAlignment <= Alignment &&
         UnpackedSizeInBits == getSizeInBits() && !HasPackedField &&
         (!CXXRD || CXXRD->isPOD() ||
-         Context.getLangOpts().getClangABICompat() <=
-             LangOptions::ClangABI::Ver15))
+         Context.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver15)))
       Diag(D->getLocation(), diag::warn_unnecessary_packed)
           << Context.getCanonicalTagType(RD);
   }
diff --git a/clang/lib/Basic/TargetInfo.cpp b/clang/lib/Basic/TargetInfo.cpp
index f3ec9a8dd0df8..854d23cadaea2 100644
--- a/clang/lib/Basic/TargetInfo.cpp
+++ b/clang/lib/Basic/TargetInfo.cpp
@@ -635,20 +635,20 @@ TargetInfo::getCallingConvKind(bool ClangABICompat4) const {
 bool TargetInfo::callGlobalDeleteInDeletingDtor(
     const LangOptions &LangOpts) const {
   if (getCXXABI() == TargetCXXABI::Microsoft &&
-      LangOpts.getClangABICompat() > LangOptions::ClangABI::Ver21)
+      !LangOpts.isCompatibleWith(LangOptions::ClangABI::Ver21))
     return true;
   return false;
 }
 
 bool TargetInfo::emitVectorDeletingDtors(const LangOptions &LangOpts) const {
   if (getCXXABI() == TargetCXXABI::Microsoft &&
-      LangOpts.getClangABICompat() > LangOptions::ClangABI::Ver21)
+      !LangOpts.isCompatibleWith(LangOptions::ClangABI::Ver21))
     return true;
   return false;
 }
 
 bool TargetInfo::areDefaultedSMFStillPOD(const LangOptions &LangOpts) const {
-  return LangOpts.getClangABICompat() > LangOptions::ClangABI::Ver15;
+  return !LangOpts.isCompatibleWith(LangOptions::ClangABI::Ver15);
 }
 
 void TargetInfo::setDependentOpenCLOpts() {
diff --git a/clang/lib/CodeGen/Targets/ARM.cpp b/clang/lib/CodeGen/Targets/ARM.cpp
index 4d05217cafb79..c6435dd6f5a8b 100644
--- a/clang/lib/CodeGen/Targets/ARM.cpp
+++ b/clang/lib/CodeGen/Targets/ARM.cpp
@@ -353,8 +353,7 @@ bool ARMABIInfo::shouldIgnoreEmptyArg(QualType Ty) const {
     return true;
 
   // Clang 19.0 and earlier always ignored empty struct arguments in C++ mode.
-  if (getContext().getLangOpts().getClangABICompat() <=
-      LangOptions::ClangABI::Ver19)
+  if (getContext().getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver19))
     return true;
 
   // Otherwise, they are passed as if they have a size of 1 byte.
diff --git a/clang/lib/CodeGen/Targets/X86.cpp b/clang/lib/CodeGen/Targets/X86.cpp
index 4a57ca7767bd2..cccc68cbf13d9 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1329,8 +1329,8 @@ class X86_64ABIInfo : public ABIInfo {
   /// classify it as INTEGER (for compatibility with older clang compilers).
   bool classifyIntegerMMXAsSSE() const {
     // Clang <= 3.8 did not do this.
-    if (getContext().getLangOpts().getClangABICompat() <=
-        LangOptions::ClangABI::Ver3_8)
+    if (getContext().getLangOpts().isCompatibleWith(
+            LangOptions::ClangABI::Ver3_8))
       return false;
 
     const llvm::Triple &Triple = getTarget().getTriple();
@@ -1342,8 +1342,8 @@ class X86_64ABIInfo : public ABIInfo {
   // GCC classifies vectors of __int128 as memory.
   bool passInt128VectorsInMem() const {
     // Clang <= 9.0 did not do this.
-    if (getContext().getLangOpts().getClangABICompat() <=
-        LangOptions::ClangABI::Ver9)
+    if (getContext().getLangOpts().isCompatibleWith(
+            LangOptions::ClangABI::Ver9))
       return false;
 
     const llvm::Triple &T = getTarget().getTriple();
@@ -1352,8 +1352,8 @@ class X86_64ABIInfo : public ABIInfo {
 
   bool returnCXXRecordGreaterThan128InMem() const {
     // Clang <= 20.0 did not do this, and PlayStation does not do this.
-    if (getContext().getLangOpts().getClangABICompat() <=
-            LangOptions::ClangABI::Ver20 ||
+    if (getContext().getLangOpts().isCompatibleWith(
+            LangOptions::ClangABI::Ver20) ||
         getTarget().getTriple().isPS())
       return false;
 
@@ -2100,8 +2100,8 @@ void X86_64ABIInfo::classify(QualType Ty, uint64_t OffsetBase, Class &Lo,
 
     // Classify the fields one at a time, merging the results.
     unsigned idx = 0;
-    bool UseClang11Compat = getContext().getLangOpts().getClangABICompat() <=
-                                LangOptions::ClangABI::Ver11 ||
+    bool UseClang11Compat = getContext().getLangOpts().isCompatibleWith(
+                                LangOptions::ClangABI::Ver11) ||
                             getContext().getTargetInfo().getTriple().isPS();
     bool IsUnion = RT->isUnionType() && !UseClang11Compat;
 
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 9bbe99df064c3..418ff01f3d98a 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7417,7 +7417,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
   checkClassLevelCodeSegAttribute(Record);
 
   bool ClangABICompat4 =
-      Context.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver4;
+      Context.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver4);
   TargetInfo::CallingConvKind CCK =
       Context.getTargetInfo().getCallingConvKind(ClangABICompat4);
   bool CanPass = canPassInRegisters(*this, Record, CCK);
@@ -10444,8 +10444,8 @@ bool Sema::SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMemberKind CSM,
     // Otherwise, if ClangABICompat14 is false, All copy constructors can be
     // trivial, if they are not user-provided, regardless of the qualifiers on
     // the reference type.
-    const bool ClangABICompat14 = Context.getLangOpts().getClangABICompat() <=
-                                  LangOptions::ClangABI::Ver14;
+    const bool ClangABICompat14 =
+        Context.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver14);
     if (!RT ||
         ((RT->getPointeeType().getCVRQualifiers() != Qualifiers::Const) &&
          ClangABICompat14)) {

``````````

</details>


https://github.com/llvm/llvm-project/pull/201067


More information about the cfe-commits mailing list