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::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(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(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() || - Context.getLangOpts().getClangABICompat() <= - LangOptions::ClangABI::Ver15 || - Target.isPS() || Target.isOSDarwin() || - Target.isOSAIX())) || - D->hasAttr(); + bool FieldPacked = + (Packed && + (!FieldClass || FieldClass->isPOD() || + FieldClass->hasAttr() || + Context.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver15) || + Target.isPS() || Target.isOSDarwin() || Target.isOSAIX())) || + D->hasAttr(); // 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)) {