llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-modules Author: Ian Anderson (ian-twilightcoder) <details> <summary>Changes</summary> rdar://38885683 apple-llvm-split-commit: 40aab84d831ddfc623de95fbbca06de6f0baf0a6 apple-llvm-split-dir: clang/ --- Patch is 121.04 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/218843.diff 33 Files Affected: - (modified) clang/include/clang/AST/DeclBase.h (+14-4) - (modified) clang/include/clang/AST/ExprObjC.h (+12-3) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+3) - (modified) clang/include/clang/Basic/TargetInfo.h (+24) - (modified) clang/include/clang/Sema/DelayedDiagnostic.h (+12-8) - (modified) clang/include/clang/Sema/Sema.h (+7-1) - (modified) clang/lib/AST/DeclBase.cpp (+45-9) - (modified) clang/lib/Basic/Targets/ARM.cpp (+3-1) - (modified) clang/lib/Basic/Targets/OSTargets.cpp (+12-2) - (modified) clang/lib/Basic/Targets/OSTargets.h (+18-4) - (modified) clang/lib/CodeGen/CGExprScalar.cpp (+8-2) - (modified) clang/lib/CodeGen/CGObjC.cpp (+44-11) - (modified) clang/lib/CodeGen/CodeGenFunction.h (+2-1) - (modified) clang/lib/CodeGen/CodeGenModule.h (+2) - (modified) clang/lib/Edit/RewriteObjCFoundationAPI.cpp (+1-1) - (modified) clang/lib/Sema/CodeCompleteConsumer.cpp (+10-2) - (modified) clang/lib/Sema/DelayedDiagnostic.cpp (+7-9) - (modified) clang/lib/Sema/SemaAvailability.cpp (+817-381) - (modified) clang/lib/Sema/SemaDecl.cpp (+3-2) - (modified) clang/lib/Sema/SemaDeclAttr.cpp (+21-4) - (modified) clang/lib/Sema/SemaDeclObjC.cpp (+31-14) - (modified) clang/lib/Sema/SemaExpr.cpp (+2-2) - (modified) clang/lib/Sema/SemaExprObjC.cpp (+12-2) - (modified) clang/lib/Sema/SemaLookup.cpp (+1-1) - (modified) clang/lib/Sema/SemaObjCProperty.cpp (+4-5) - (modified) clang/lib/Sema/SemaTemplateInstantiate.cpp (+6-1) - (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+1) - (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+1) - (added) clang/test/CodeGenObjC/availability-check-zippered.m (+41) - (added) clang/test/FixIt/fixit-availability-zippered.m (+23) - (added) clang/test/Sema/attr-availability-zippered.c (+133) - (added) clang/test/SemaObjC/unguarded-availability-zippered.m (+42) - (modified) clang/tools/libclang/CIndex.cpp (+4-1) ``````````diff diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 9d233be282dbb..bab32734519c9 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -758,6 +758,13 @@ class alignas(8) Decl { VersionTuple EnclosingVersion = VersionTuple(), StringRef *RealizedPlatform = nullptr) const; + /// Determine the availability of the given declaration for the given + /// target platform and its minimum version. + AvailabilityResult getAvailability(StringRef Platform, + const VersionTuple &PlatformMinVersion, + std::string *Message = nullptr, + StringRef *RealizedPlatform = nullptr) const; + /// Retrieve the version of the target platform in which this /// declaration was introduced. /// @@ -766,14 +773,13 @@ class alignas(8) Decl { /// attribute otherwise. VersionTuple getVersionIntroduced() const; - /// Determine whether this declaration is marked 'deprecated'. + /// \brief Determine whether this declaration is marked 'deprecated' in any + /// target platform that we're compiling for. /// /// \param Message If non-NULL and the declaration is deprecated, /// this will be set to the message describing why the declaration /// was deprecated (which may be empty). - bool isDeprecated(std::string *Message = nullptr) const { - return getAvailability(Message) == AR_Deprecated; - } + bool isDeprecatedInAnyTargetPlatform(std::string *Message = nullptr) const; /// Determine whether this declaration is marked 'unavailable'. /// @@ -784,6 +790,10 @@ class alignas(8) Decl { return getAvailability(Message) == AR_Unavailable; } + /// \brief Determine whether this declaration is marked 'deprecated' for + /// all target platforms that we're compiling for. + bool isUnavailabledForAllTargetPlatforms() const; + /// Determine whether this is a weak-imported symbol. /// /// Weak-imported symbols are typically marked with the diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index b424530c8447c..39f22c961ce96 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -1736,13 +1736,18 @@ class ObjCAvailabilityCheckExpr : public Expr { friend class ASTStmtReader; VersionTuple VersionToCheck; + VersionTuple VariantVersionToCheck; SourceLocation AtLoc, RParen; public: - ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc, - SourceLocation RParen, QualType Ty) + ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, + VersionTuple VariantVersionToCheck, + SourceLocation AtLoc, SourceLocation RParen, + QualType Ty) : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_PRValue, OK_Ordinary), - VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) { + VersionToCheck(VersionToCheck), + VariantVersionToCheck(VariantVersionToCheck), AtLoc(AtLoc), + RParen(RParen) { setDependence(ExprDependence::None); } @@ -1757,6 +1762,10 @@ class ObjCAvailabilityCheckExpr : public Expr { bool hasVersion() const { return !VersionToCheck.empty(); } VersionTuple getVersion() const { return VersionToCheck; } + bool hasVariantVersion() const { return !VariantVersionToCheck.empty(); } + + VersionTuple getVariantVersion() const { return VariantVersionToCheck; } + child_range children() { return child_range(child_iterator(), child_iterator()); } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index cfb2ee3368201..c6b237c883a2b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4300,6 +4300,9 @@ def warn_unguarded_availability_new : def warn_unguarded_availability_unavailable_new : Warning<warn_unguarded_availability_unavailable.Summary>, InGroup<UnguardedAvailabilityNew>; +def warn_zippered_unguarded_availability : + Warning<"%0 is only available on %1 %2 and %3 %4 or newer">, + InGroup<UnguardedAvailabilityNew>; def note_decl_unguarded_availability_silence : Note< "annotate %select{%1|anonymous %1}0 with an availability attribute to silence this warning">; def note_unguarded_available_silence : Note< diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 5a541aaf797fe..66a7ba2bd096f 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -260,6 +260,8 @@ class TargetInfo : public TransferrableTargetInfo, mutable StringRef PlatformName; mutable VersionTuple PlatformMinVersion; + mutable StringRef TargetVariantPlatform; + mutable VersionTuple TargetVariantPlatformMinVersion; LLVM_PREFERRED_TYPE(bool) unsigned HasAlignMac68kSupport : 1; @@ -1737,6 +1739,28 @@ class TargetInfo : public TransferrableTargetInfo, /// which the program should be compiled. VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; } + /// Returns true when are building for an auxillary target variant platform. + bool hasTargetVariantPlatform() const { + return !TargetVariantPlatform.empty(); + } + + /// Retrieve the name of the target variant platform as it is used in the + /// availability attribute. + StringRef getTargetVariantPlatform() const { + assert(hasTargetVariantPlatform() && + "no target variant platform specified"); + return TargetVariantPlatform; + } + + /// Retrieve the minimum desired deployment version of the target variant + /// platform, + /// for which the program should be compiled. + VersionTuple getTargetVariantPlatformMinVersion() const { + assert(hasTargetVariantPlatform() && + "no target variant platform specified"); + return TargetVariantPlatformMinVersion; + } + bool isBigEndian() const { return BigEndian; } bool isLittleEndian() const { return !BigEndian; } diff --git a/clang/include/clang/Sema/DelayedDiagnostic.h b/clang/include/clang/Sema/DelayedDiagnostic.h index 0105089a393f1..5e45c3459f151 100644 --- a/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/clang/include/clang/Sema/DelayedDiagnostic.h @@ -134,14 +134,13 @@ class DelayedDiagnostic { void Destroy(); - static DelayedDiagnostic makeAvailability(AvailabilityResult AR, - ArrayRef<SourceLocation> Locs, - const NamedDecl *ReferringDecl, - const NamedDecl *OffendingDecl, - const ObjCInterfaceDecl *UnknownObjCClass, - const ObjCPropertyDecl *ObjCProperty, - StringRef Msg, - bool ObjCPropertyAccess); + static DelayedDiagnostic + makeAvailability(AvailabilityResult AR, ArrayRef<SourceLocation> Locs, + const NamedDecl *ReferringDecl, + const NamedDecl *OffendingDecl, + const ObjCInterfaceDecl *UnknownObjCClass, + const ObjCPropertyDecl *ObjCProperty, StringRef Msg, + bool ObjCPropertyAccess, bool IsTargetVariantPlatform); static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { @@ -232,6 +231,10 @@ class DelayedDiagnostic { return AvailabilityData.ObjCPropertyAccess; } + bool isTargetVariantPlatform() const { + return AvailabilityData.IsTargetVariantPlatform; + } + private: struct AD { const NamedDecl *ReferringDecl; @@ -244,6 +247,7 @@ class DelayedDiagnostic { size_t NumSelectorLocs; AvailabilityResult AR; bool ObjCPropertyAccess; + bool IsTargetVariantPlatform; }; struct FTD { diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index dcf112fd8eaa4..c7e4db0f49a30 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2466,6 +2466,10 @@ class Sema final : public SemaBase { void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); + void handleZipperedDelayedAvailabilityCheck( + sema::DelayedDiagnostic &DD, sema::DelayedDiagnostic &VariantDD, + Decl *Ctx); + /// Retrieve the current function, if any, that should be analyzed for /// potential availability violations. sema::FunctionScopeInfo *getCurFunctionAvailabilityContext(); @@ -2479,7 +2483,9 @@ class Sema final : public SemaBase { void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs); std::pair<AvailabilityResult, const NamedDecl *> - ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, std::string *Message, + ShouldDiagnoseAvailabilityOfDecl(const NamedDecl *D, StringRef Platform, + const VersionTuple &PlatformVersion, + std::string *Message, ObjCInterfaceDecl *ClassReceiver); ///@} diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 70f61fa57a682..b8dd2772977bd 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -674,15 +674,12 @@ static StringRef getRealizedPlatform(const AvailabilityAttr *A, static AvailabilityResult CheckAvailability(ASTContext &Context, const AvailabilityAttr *A, std::string *Message, + StringRef TargetPlatform, VersionTuple EnclosingVersion) { - if (EnclosingVersion.empty()) - EnclosingVersion = Context.getTargetInfo().getPlatformMinVersion(); - if (EnclosingVersion.empty()) return AR_Available; StringRef ActualPlatform = A->getPlatform()->getName(); - StringRef TargetPlatform = Context.getTargetInfo().getPlatformName(); // Match the platform name. if (getRealizedPlatform(A, Context) != TargetPlatform) @@ -779,9 +776,21 @@ static AvailabilityResult CheckAvailability(ASTContext &Context, AvailabilityResult Decl::getAvailability(std::string *Message, VersionTuple EnclosingVersion, StringRef *RealizedPlatform) const { + const TargetInfo &TI = getASTContext().getTargetInfo(); + return getAvailability(TI.getPlatformName(), + EnclosingVersion.empty() ? TI.getPlatformMinVersion() + : EnclosingVersion, + Message, RealizedPlatform); +} + +AvailabilityResult Decl::getAvailability(StringRef Platform, + const VersionTuple &PlatformMinVersion, + std::string *Message, + StringRef *RealizedPlatform) const { if (auto *FTD = dyn_cast<FunctionTemplateDecl>(this)) - return FTD->getTemplatedDecl()->getAvailability(Message, EnclosingVersion, - RealizedPlatform); + return FTD->getTemplatedDecl()->getAvailability( + Platform, PlatformMinVersion, Message, RealizedPlatform); + AvailabilityResult Result = AR_Available; std::string ResultMessage; @@ -806,8 +815,8 @@ AvailabilityResult Decl::getAvailability(std::string *Message, if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { Availability = Availability->getEffectiveAttr(); - AvailabilityResult AR = CheckAvailability(getASTContext(), Availability, - Message, EnclosingVersion); + AvailabilityResult AR = CheckAvailability( + getASTContext(), Availability, Message, Platform, PlatformMinVersion); if (AR == AR_Unavailable) { if (RealizedPlatform) @@ -844,6 +853,26 @@ VersionTuple Decl::getVersionIntroduced() const { return {}; } +bool Decl::isDeprecatedInAnyTargetPlatform(std::string *Message) const { + const TargetInfo &TI = getASTContext().getTargetInfo(); + return getAvailability(TI.getPlatformName(), TI.getPlatformMinVersion()) == + AR_Deprecated || + (TI.hasTargetVariantPlatform() && + getAvailability(TI.getTargetVariantPlatform(), + TI.getTargetVariantPlatformMinVersion()) == + AR_Deprecated); +} + +bool Decl::isUnavailabledForAllTargetPlatforms() const { + const TargetInfo &TI = getASTContext().getTargetInfo(); + return getAvailability(TI.getPlatformName(), TI.getPlatformMinVersion()) == + AR_Unavailable && + (!getASTContext().getTargetInfo().hasTargetVariantPlatform() || + getAvailability(TI.getTargetVariantPlatform(), + TI.getTargetVariantPlatformMinVersion()) == + AR_Unavailable); +} + bool Decl::canBeWeakImported(bool &IsDefinition) const { IsDefinition = false; @@ -878,6 +907,7 @@ bool Decl::isWeakImported() const { if (!canBeWeakImported(IsDefinition)) return false; + const TargetInfo &TI = getASTContext().getTargetInfo(); for (const auto *A : getMostRecentDecl()->attrs()) { if (isa<WeakImportAttr>(A)) return true; @@ -885,7 +915,13 @@ bool Decl::isWeakImported() const { if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { Availability = Availability->getEffectiveAttr(); if (CheckAvailability(getASTContext(), Availability, nullptr, - VersionTuple()) == AR_NotYetIntroduced) + TI.getPlatformName(), TI.getPlatformMinVersion()) == + AR_NotYetIntroduced || + (TI.hasTargetVariantPlatform() && + CheckAvailability(getASTContext(), Availability, nullptr, + TI.getTargetVariantPlatform(), + TI.getTargetVariantPlatformMinVersion()) == + AR_NotYetIntroduced)) return true; } } diff --git a/clang/lib/Basic/Targets/ARM.cpp b/clang/lib/Basic/Targets/ARM.cpp index 8d6e8d6990e80..0cd4b705bbcb9 100644 --- a/clang/lib/Basic/Targets/ARM.cpp +++ b/clang/lib/Basic/Targets/ARM.cpp @@ -1558,5 +1558,7 @@ DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple, void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, MacroBuilder &Builder) const { - getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion); + getDarwinDefines(Builder, Opts, Triple, /*TargetVariantTriple=*/"", + PlatformName, PlatformMinVersion, TargetVariantPlatform, + TargetVariantPlatformMinVersion); } diff --git a/clang/lib/Basic/Targets/OSTargets.cpp b/clang/lib/Basic/Targets/OSTargets.cpp index 04d9e13d3c9a6..91f98595dbbf5 100644 --- a/clang/lib/Basic/Targets/OSTargets.cpp +++ b/clang/lib/Basic/Targets/OSTargets.cpp @@ -55,8 +55,10 @@ void getAppleMachODefines(MacroBuilder &Builder, const LangOptions &Opts, } void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, - const llvm::Triple &Triple, StringRef &PlatformName, - VersionTuple &PlatformMinVersion) { + const llvm::Triple &Triple, StringRef TargetVariantTriple, + StringRef &PlatformName, VersionTuple &PlatformMinVersion, + StringRef &TargetVariantPlatformName, + VersionTuple &TargetVariantPlatformMinVersion) { getAppleMachODefines(Builder, Opts, Triple); // Darwin's libc doesn't have threads.h @@ -67,6 +69,14 @@ void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, if (Triple.isMacOSX()) { Triple.getMacOSXVersion(OsVersion); PlatformName = "macos"; + if (!TargetVariantTriple.empty()) { + llvm::Triple TVT(TargetVariantTriple); + if (TVT.getOS() == llvm::Triple::IOS && + TVT.getEnvironment() == llvm::Triple::MacABI) { + TargetVariantPlatformName = "maccatalyst"; + TargetVariantPlatformMinVersion = TVT.getiOSVersion(); + } + } } else { OsVersion = Triple.getOSVersion(); PlatformName = llvm::Triple::getOSTypeName(Triple.getOS()); diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index fb5c17cefc004..d5aa067d9eabf 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -38,8 +38,10 @@ void getAppleMachODefines(MacroBuilder &Builder, const LangOptions &Opts, const llvm::Triple &Triple); void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts, - const llvm::Triple &Triple, StringRef &PlatformName, - VersionTuple &PlatformMinVersion); + const llvm::Triple &Triple, StringRef TargetVariantTriple, + StringRef &PlatformName, VersionTuple &PlatformMinVersion, + StringRef &TargetVariantPlatformName, + VersionTuple &TargetVariantPlatform); template <typename Target> class LLVM_LIBRARY_VISIBILITY AppleMachOTargetInfo @@ -77,8 +79,10 @@ class LLVM_LIBRARY_VISIBILITY DarwinTargetInfo protected: void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, MacroBuilder &Builder) const override { - getDarwinDefines(Builder, Opts, Triple, this->PlatformName, - this->PlatformMinVersion); + getDarwinDefines(Builder, Opts, Triple, TargetVariantTriple, + this->PlatformName, this->PlatformMinVersion, + this->TargetVariantPlatform, + this->TargetVariantPlatformMinVersion); } public: @@ -87,6 +91,7 @@ class LLVM_LIBRARY_VISIBILITY DarwinTargetInfo // By default, no TLS, and we list permitted architecture/OS // combinations. this->TLSSupported = false; + TargetVariantTriple = Opts.DarwinTargetVariantTriple; if (Triple.isMacOSX()) this->TLSSupported = !Triple.isMacOSXVersionLT(10, 7); @@ -185,6 +190,15 @@ class LLVM_LIBRARY_VISIBILITY DarwinTargetInfo bool areDefaultedSMFStillPOD(const LangOptions &) const override { return false; } + + /// Darwin does not support protected visibility. Darwin's "default" + /// is very similar to ELF's "protected"; Darwin requires a "weak" + /// attribute on declarations that can be dynamically replaced. + bool hasProtectedVisibility() const override { return false; } + +private: + std::string TargetVariantTriple; + }; // DragonFlyBSD Target diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 173931213ce68..5f46849ccc956 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -635,13 +635,19 @@ class ScalarExprEmitter Value *VisitObjCAvailabilityCheckExpr(ObjCAvailabilityCheckExpr *E) { VersionTuple Version = E->getVersion(); + VersionTuple VariantVersion = E->getVariantVersion(); // If we're checking for a platform older than our minimum deployment // target, we can fold the check away. - if (Version <= CGF.CGM.getTarget().getPlatformMinVersion()) + if ((Version.empty() && VariantVersion.empty()) || (!Version.empty() && + Version <= CGF.CGM.getTarget().getPlatformMinVersion() && + (!CGF.CGM.getTarget().hasTargetVariantPlatform() || + (!VariantVersion.empty() && + VariantVersion <= + CGF.CGM.getTarget().getTargetVariantPlatformMinVersion())))) return llvm::ConstantInt::get(Builder.getInt1Ty(), 1); - return CGF.EmitBuiltinAvailable(Version); + return CGF.EmitBuiltinAvailable(Version, VariantVersion); } Value *VisitArraySubscriptExpr(ArraySubscriptExpr *E); diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index b9cbf593fb1c4..73b1cdba09514 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -40... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/218843 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
