From f6bf9662cb7899f1b30cbf7fa4d4ac9ed2219a03 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 6 Mar 2025 10:25:49 -0800 Subject: [PATCH 1/5] Revert "Check that the method ObjCMessageExpr references isn't null before passing it to diagnoseDeclFeatureAvailability" This reverts commit 745ab81ea968c345b3287885f1f1ac7518e26827. --- clang/lib/Sema/SemaFeatureAvailability.cpp | 3 +-- clang/test/SemaObjC/feature-availability.m | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaFeatureAvailability.cpp b/clang/lib/Sema/SemaFeatureAvailability.cpp index cd2e209f6548b..e90cdfc92606f 100644 --- a/clang/lib/Sema/SemaFeatureAvailability.cpp +++ b/clang/lib/Sema/SemaFeatureAvailability.cpp @@ -78,8 +78,7 @@ class DiagnoseUnguardedFeatureAvailability } bool VisitObjCMessageExpr(ObjCMessageExpr *OME) { - if (auto *MD = OME->getMethodDecl()) - diagnoseDeclFeatureAvailability(MD, OME->getBeginLoc()); + diagnoseDeclFeatureAvailability(OME->getMethodDecl(), OME->getBeginLoc()); return true; } diff --git a/clang/test/SemaObjC/feature-availability.m b/clang/test/SemaObjC/feature-availability.m index 586b60b24fb65..6d9acebcd4727 100644 --- a/clang/test/SemaObjC/feature-availability.m +++ b/clang/test/SemaObjC/feature-availability.m @@ -62,7 +62,7 @@ @interface Derived3 : Base7 // expected-error {{use of 'Base0' requires @end __attribute__((availability(domain:feature1, AVAIL))) // expected-note {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} expected-note 2 {{feature attribute __attribute__((availability(domain:feature1, 0)))}} -@interface Derived0 : Base0 { // expected-note {{receiver is instance of class declared here}} +@interface Derived0 : Base0 { struct S1 *ivar4; } @property struct S1 *p0; @@ -81,7 +81,6 @@ -(void)m0 { } -(void)m1 { self.p1 = 1; - [self nonexistentMethod]; // expected-warning {{instance method '-nonexistentMethod' not found (return type defaults to 'id')}} } @end From 1acde3afff4c2a58a20615f0688202cbfe40a648 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 6 Mar 2025 10:25:49 -0800 Subject: [PATCH 2/5] Revert "Don't set HasPotentialFeatureAvailabilityViolations in ActOnLabelStmt" This reverts commit e5e6004114f18234def6c4c2f57b9e81b000ddbc. --- clang/lib/Sema/SemaExprObjC.cpp | 2 -- clang/lib/Sema/SemaStmt.cpp | 3 +++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 07ae6b5f8981b..77e919ca29e16 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -5154,8 +5154,6 @@ ExprResult SemaObjC::ActOnObjCAvailabilityCheckExpr( ASTContext &Context = getASTContext(); if (AvailSpecs.front().isDomainName()) { - if (FunctionScopeInfo *Info = SemaRef.getCurFunctionAvailabilityContext()) - Info->HasPotentialFeatureAvailabilityViolations = true; auto Spec = AvailSpecs.front(); return ObjCAvailabilityCheckExpr::CreateAvailabilityFeatureCheck( AtLoc, RParen, Context.BoolTy, Spec.getDomainName(), Context); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index df6d1f7ff6ccb..2d3312b11fcb0 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -602,6 +602,9 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, } } + if (FunctionScopeInfo *Info = getCurFunctionAvailabilityContext()) + Info->HasPotentialFeatureAvailabilityViolations = true; + return LS; } From 265910eea3d6c46b2cff91f063afd9d2e6ab1f6d Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 6 Mar 2025 10:25:49 -0800 Subject: [PATCH 3/5] Revert "Fix spelling of DomainAvailabilityAttr and specify documentation" This reverts commit b03fbbaa01fa73c70d649f53d4cd8b568f555bd7. --- clang/include/clang/Basic/Attr.td | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 930770601aa5a..e86dfb45b001c 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1127,12 +1127,12 @@ static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environm def DomainAvailability : InheritableAttr { // This attribute has no spellings as it is created implicitly when // __attribute__((availability(domain:...))) is seen. - let Spellings = []; + let Spellings = [Clang<"">]; let Args = [StringArgument<"domain">, BoolArgument<"unavailable">]; let AdditionalMembers = [{ std::string getFeatureAttributeStr() const; }]; - let Documentation = [InternalOnly]; + let Documentation = [Undocumented]; } // This attribute is used to annotate structs of type `_AvailabilityDomain`. From 4953674f7bc5a067d2e6b231ce3dc80729e55485 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 6 Mar 2025 10:25:49 -0800 Subject: [PATCH 4/5] Revert "Check that DomainName is empty in isOtherPlatformSpec" This reverts commit 41a9f5ec0ac47340a9b300838d1a7e425bbfcb14. --- clang/include/clang/AST/Availability.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clang/include/clang/AST/Availability.h b/clang/include/clang/AST/Availability.h index 520a734ec4c28..893504bd6b8fc 100644 --- a/clang/include/clang/AST/Availability.h +++ b/clang/include/clang/AST/Availability.h @@ -60,9 +60,7 @@ class AvailabilitySpec { SourceLocation getEndLoc() const { return EndLoc; } /// Returns true when this represents the '*' case. - bool isOtherPlatformSpec() const { - return Version.empty() && DomainName.empty(); - } + bool isOtherPlatformSpec() const { return Version.empty(); } bool isDomainName() const { return !DomainName.empty(); } StringRef getDomainName() const { return DomainName; } From 48b143c8b3c7224aee335423a431ca46230228b7 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Thu, 6 Mar 2025 10:25:49 -0800 Subject: [PATCH 5/5] Revert "Extend availability attribute to support feature-based availability" This reverts commit 3b005bf512be6ad549cf664179e06aaa6d49b9b1. --- clang/include/clang/AST/ASTContext.h | 30 --- clang/include/clang/AST/Availability.h | 8 - clang/include/clang/AST/ExprObjC.h | 39 +-- clang/include/clang/AST/Stmt.h | 10 - clang/include/clang/Basic/Attr.td | 19 -- .../clang/Basic/DiagnosticFrontendKinds.td | 3 - .../clang/Basic/DiagnosticParseKinds.td | 5 - .../clang/Basic/DiagnosticSemaKinds.td | 22 -- clang/include/clang/Basic/LangOptions.h | 14 -- clang/include/clang/Driver/Options.td | 4 - clang/include/clang/Parse/Parser.h | 6 - clang/include/clang/Sema/DelayedDiagnostic.h | 21 +- clang/include/clang/Sema/ParsedAttr.h | 2 - clang/include/clang/Sema/ScopeInfo.h | 5 +- clang/include/clang/Sema/Sema.h | 13 - clang/lib/AST/ASTContext.cpp | 90 ------- clang/lib/AST/AttrImpl.cpp | 7 - clang/lib/AST/DeclBase.cpp | 6 - clang/lib/AST/ExprConstant.cpp | 24 -- clang/lib/AST/ExprObjC.cpp | 23 -- clang/lib/AST/RecordLayoutBuilder.cpp | 5 - clang/lib/Driver/ToolChains/Clang.cpp | 10 - clang/lib/Frontend/CompilerInvocation.cpp | 31 --- clang/lib/Headers/CMakeLists.txt | 1 - clang/lib/Headers/feature-availability.h | 33 --- clang/lib/Parse/ParseDecl.cpp | 54 ----- clang/lib/Parse/ParseExpr.cpp | 28 +-- clang/lib/Parse/ParseObjc.cpp | 39 +-- clang/lib/Sema/CMakeLists.txt | 1 - clang/lib/Sema/DelayedDiagnostic.cpp | 13 - clang/lib/Sema/ScopeInfo.cpp | 1 - clang/lib/Sema/SemaDecl.cpp | 14 -- clang/lib/Sema/SemaDeclAttr.cpp | 130 ---------- clang/lib/Sema/SemaDeclObjC.cpp | 7 - clang/lib/Sema/SemaExpr.cpp | 5 - clang/lib/Sema/SemaExprObjC.cpp | 7 - clang/lib/Sema/SemaFeatureAvailability.cpp | 229 ------------------ clang/lib/Sema/SemaObjCProperty.cpp | 18 +- clang/lib/Sema/SemaStmt.cpp | 4 - ...a-attribute-supported-attributes-list.test | 1 - clang/test/Sema/feature-availability.c | 221 ----------------- clang/test/SemaObjC/feature-availability.m | 172 ------------- 42 files changed, 27 insertions(+), 1348 deletions(-) delete mode 100644 clang/lib/Headers/feature-availability.h delete mode 100644 clang/lib/Sema/SemaFeatureAvailability.cpp delete mode 100644 clang/test/Sema/feature-availability.c delete mode 100644 clang/test/SemaObjC/feature-availability.m diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 3e85f1a5c30b0..0c5ba11e72c71 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -25,7 +25,6 @@ #include "clang/AST/RawCommentList.h" #include "clang/AST/TemplateName.h" #include "clang/Basic/LLVM.h" -#include "clang/Basic/LangOptions.h" #include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" @@ -802,35 +801,6 @@ class ASTContext : public RefCountedBase { return DiagAllocator; } - struct AvailabilityDomainInfo { - FeatureAvailKind Kind = FeatureAvailKind::None; - ImplicitCastExpr *Call = nullptr; - bool isInvalid() const { return Kind == FeatureAvailKind::None; } - }; - - std::map AvailabilityDomainMap; - - void addAvailabilityDomainMap(StringRef Name, AvailabilityDomainInfo Info) { - AvailabilityDomainMap[Name] = Info; - } - - std::pair - checkNewFeatureAvailability(Decl *D, StringRef DomainName, bool Unavailable); - - bool hasFeatureAvailabilityAttr(const Decl *D) const; - - // Retrieve availability domain information for a feature. - AvailabilityDomainInfo getFeatureAvailInfo(StringRef FeatureName) const; - - // Retrieve feature name and availability domain information on a decl. If the - // decl doesn't have attribute availability_domain on it, the name will be - // empty and AvailabilityDomainInfo::Kind will be set to - // FeatureAvailKind::None. - std::pair - getFeatureAvailInfo(Decl *D) const; - - bool hasUnavailableFeature(const Decl *D) const; - const TargetInfo &getTargetInfo() const { return *Target; } const TargetInfo *getAuxTargetInfo() const { return AuxTarget; } diff --git a/clang/include/clang/AST/Availability.h b/clang/include/clang/AST/Availability.h index 893504bd6b8fc..60ca1383f0a44 100644 --- a/clang/include/clang/AST/Availability.h +++ b/clang/include/clang/AST/Availability.h @@ -37,8 +37,6 @@ class AvailabilitySpec { /// Name of the platform that Version corresponds to. StringRef Platform; - StringRef DomainName; - SourceLocation BeginLoc, EndLoc; public: @@ -47,9 +45,6 @@ class AvailabilitySpec { : Version(Version), Platform(Platform), BeginLoc(BeginLoc), EndLoc(EndLoc) {} - AvailabilitySpec(StringRef DomainName, SourceLocation Loc) - : DomainName(DomainName), BeginLoc(Loc), EndLoc(Loc) {} - /// This constructor is used when representing the '*' case. AvailabilitySpec(SourceLocation StarLoc) : BeginLoc(StarLoc), EndLoc(StarLoc) {} @@ -61,9 +56,6 @@ class AvailabilitySpec { /// Returns true when this represents the '*' case. bool isOtherPlatformSpec() const { return Version.empty(); } - - bool isDomainName() const { return !DomainName.empty(); } - StringRef getDomainName() const { return DomainName; } }; class Decl; diff --git a/clang/include/clang/AST/ExprObjC.h b/clang/include/clang/AST/ExprObjC.h index 552a0768e2201..70bdf6dbba9f2 100644 --- a/clang/include/clang/AST/ExprObjC.h +++ b/clang/include/clang/AST/ExprObjC.h @@ -1693,9 +1693,7 @@ class ObjCBridgedCastExpr final /// be used in the condition of an \c if, but it is also usable as top level /// expressions. /// -class ObjCAvailabilityCheckExpr final - : public Expr, - private llvm::TrailingObjects { +class ObjCAvailabilityCheckExpr : public Expr { public: struct VersionAsWritten { /// Platform version canonicalized for use with availability checks. @@ -1706,24 +1704,10 @@ class ObjCAvailabilityCheckExpr final private: friend class ASTStmtReader; - friend llvm::TrailingObjects; VersionAsWritten VersionToCheck; SourceLocation AtLoc, RParen; - void setHasDomainName(bool V) { - ObjCAvailabilityCheckExprBits.HasDomainName = V; - } - - ObjCAvailabilityCheckExpr(SourceLocation AtLoc, SourceLocation RParen, - QualType Ty, StringRef DomainName) - : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_PRValue, OK_Ordinary), - VersionToCheck(), AtLoc(AtLoc), RParen(RParen) { - setDependence(ExprDependence::None); - setHasDomainName(true); - strcpy(getTrailingObjects(), DomainName.data()); - } - public: ObjCAvailabilityCheckExpr(VersionAsWritten VersionToCheck, SourceLocation AtLoc, @@ -1731,21 +1715,10 @@ class ObjCAvailabilityCheckExpr final : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_PRValue, OK_Ordinary), VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) { setDependence(ExprDependence::None); - setHasDomainName(false); } - static ObjCAvailabilityCheckExpr * - CreateAvailabilityFeatureCheck(SourceLocation AtLoc, SourceLocation RParen, - QualType Ty, StringRef DomainName, - const ASTContext &C); - explicit ObjCAvailabilityCheckExpr(EmptyShell Shell) - : Expr(ObjCAvailabilityCheckExprClass, Shell) { - setHasDomainName(false); - } - - static ObjCAvailabilityCheckExpr * - CreateEmpty(const ASTContext &C, Stmt::EmptyShell Empty, size_t FeaturesLen); + : Expr(ObjCAvailabilityCheckExprClass, Shell) {} SourceLocation getBeginLoc() const { return AtLoc; } SourceLocation getEndLoc() const { return RParen; } @@ -1758,14 +1731,6 @@ class ObjCAvailabilityCheckExpr final return VersionToCheck.SourceVersion; } - bool hasDomainName() const { - return ObjCAvailabilityCheckExprBits.HasDomainName; - } - StringRef getDomainName() const { - assert(hasDomainName()); - return getTrailingObjects(); - } - child_range children() { return child_range(child_iterator(), child_iterator()); } diff --git a/clang/include/clang/AST/Stmt.h b/clang/include/clang/AST/Stmt.h index eed1cb833210e..a32b84c8de0b0 100644 --- a/clang/include/clang/AST/Stmt.h +++ b/clang/include/clang/AST/Stmt.h @@ -1226,15 +1226,6 @@ class alignas(void *) Stmt { unsigned ShouldCopy : 1; }; - class ObjCAvailabilityCheckExprBitfields { - friend class ObjCAvailabilityCheckExpr; - LLVM_PREFERRED_TYPE(ExprBitfields) - unsigned : NumExprBits; - - LLVM_PREFERRED_TYPE(bool) - unsigned HasDomainName : 1; - }; - //===--- Clang Extensions bitfields classes ---===// class OpaqueValueExprBitfields { @@ -1333,7 +1324,6 @@ class alignas(void *) Stmt { // Obj-C Expressions ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits; - ObjCAvailabilityCheckExprBitfields ObjCAvailabilityCheckExprBits; // Clang Extensions OpaqueValueExprBitfields OpaqueValueExprBits; diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index e86dfb45b001c..9f72eaa1bbbc5 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1124,25 +1124,6 @@ static llvm::Triple::EnvironmentType getEnvironmentType(llvm::StringRef Environm let Documentation = [AvailabilityDocs]; } -def DomainAvailability : InheritableAttr { - // This attribute has no spellings as it is created implicitly when - // __attribute__((availability(domain:...))) is seen. - let Spellings = [Clang<"">]; - let Args = [StringArgument<"domain">, BoolArgument<"unavailable">]; - let AdditionalMembers = [{ - std::string getFeatureAttributeStr() const; - }]; - let Documentation = [Undocumented]; -} - -// This attribute is used to annotate structs of type `_AvailabilityDomain`. -def AvailabilityDomain : InheritableAttr { - let Spellings = [Clang<"availability_domain">]; - let Args = [IdentifierArgument<"name">]; - let Subjects = SubjectList<[Var]>; - let Documentation = [Undocumented]; -} - def ExternalSourceSymbol : InheritableAttr { let Spellings = [Clang<"external_source_symbol", /*allowInC=*/1, /*version=*/20230206>]; diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td index 4e4395782924c..0cf7bfffab0ed 100644 --- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td @@ -144,9 +144,6 @@ def err_fe_invalid_exception_model def err_fe_invalid_source_date_epoch : Error< "environment variable 'SOURCE_DATE_EPOCH' ('%0') must be a non-negative decimal integer <= %1">; -def err_feature_availability_flag_invalid_value : Error< - "invalid value '%0' passed to '-ffeature-availability='; expected :">; - def err_fe_incompatible_option_with_remote_cache : Error< "'%0' is incompatible with remote caching backend">; def err_fe_unable_to_load_include_tree : Error< diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index fe600f15809d1..38f9da26c48d2 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1122,11 +1122,6 @@ def err_availability_expected_platform : Error< def err_availability_expected_environment : Error< "expected an environment name, e.g., 'compute'">; -def err_features_domain_name : Error< - "expected a domain name">; -def err_feature_invalid_availability_check : Error< - "cannot pass a domain argument along with other arguments">; - // objc_bridge_related attribute def err_objcbridge_related_expected_related_class : Error< "expected a related Objective-C class name, e.g., 'NSColor'">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 82e2341f5be6f..7be301f2ab056 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3960,28 +3960,6 @@ def err_availability_unexpected_parameter: Error< def warn_unguarded_availability : Warning<"%0 is only available %select{|in %4 environment }3on %1 %2 or newer">, InGroup, DefaultIgnore; -def err_unguarded_feature : Error< - "use of %0 requires feature '%1' to be %select{available|unavailable}2">; -def err_label_in_conditionally_guarded_feature : Error< - "labels cannot appear in regions conditionally guarded by features">; -def err_features_invalid_for_decl : Error< - "feature attributes cannot be applied to %0">; -def err_features_invalid_name : Error< - "cannot find definition of feature attribute '%0'">; -def err_features_invalid__arg : Error< - "invalid argument %0: must evaluate to 0 or 1">; -def err_feature_invalid_for_decl : Error< - "feature attribute '%0(%1)' cannot be applied to this decl">; -def err_feature_merge_incompatible : Error< - "cannot merge incompatible feature attribute to this decl">; -def err_new_feature_redeclaration : Error< - "new feature attributes cannot be added to redeclarations">; -def err_feature_invalid_added : Error< - "cannot add feature availability to this decl">; -def note_feature_incompatible0 : Note< - "feature attribute %0">; -def note_feature_incompatible1 : Note< - "is incompatible with %0">; def warn_unguarded_availability_unavailable : Warning<"%0 is unavailable">, InGroup, DefaultIgnore; diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 290fb355d3130..39a242d4db2b7 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -64,8 +64,6 @@ enum class PointerAuthenticationMode : unsigned { SignAndAuth }; -enum class FeatureAvailKind { None, Available, Unavailable, Dynamic }; - /// Bitfields of LangOptions, split out from LangOptions in order to ensure that /// this large collection of bitfields is a trivial class type. class LangOptionsBase { @@ -546,8 +544,6 @@ class LangOptions : public LangOptionsBase { /// This list is sorted. std::vector ModuleFeatures; - std::vector FeatureAvailability; - /// Options for parsing comments. CommentOptions CommentOpts; @@ -565,16 +561,6 @@ class LangOptions : public LangOptionsBase { /// host code generation. std::string OMPHostIRFile; - llvm::StringMap FeatureAvailabilityMap; - - void setFeatureAvailability(StringRef Feature, FeatureAvailKind Kind) { - FeatureAvailabilityMap[Feature] = Kind; - } - - FeatureAvailKind getFeatureAvailability(StringRef Feature) const { - return FeatureAvailabilityMap.lookup(Feature); - } - /// The user provided compilation unit ID, if non-empty. This is used to /// externalize static variables which is needed to support accessing static /// device variables in host code for single source offloading languages diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index aa7b435a6deba..7d218259fd40e 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3433,10 +3433,6 @@ def fno_builtin : Flag<["-"], "fno-builtin">, Group, def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group, Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>, HelpText<"Disable implicit builtin knowledge of a specific function">; -def ffeature_availability_EQ : Joined<["-"], "ffeature-availability=">, Group, - Visibility<[CC1Option]>, - HelpText<"feature availability">, - MarshallingInfoStringVector>; def fno_common : Flag<["-"], "fno-common">, Group, Visibility<[ClangOption, CC1Option]>, HelpText<"Compile common globals like normal definitions">; diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 52a3eb82165d6..fe4501bd31b1b 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -3127,12 +3127,6 @@ class Parser : public CodeCompletionHandler { void ParseHLSLQualifiers(ParsedAttributes &Attrs); VersionTuple ParseVersionTuple(SourceRange &Range); - void ParseFeatureAvailabilityAttribute( - IdentifierInfo &Availability, SourceLocation AvailabilityLoc, - ParsedAttributes &attrs, SourceLocation *endLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, ParsedAttr::Form Form, - BalancedDelimiterTracker &T); - void ParseAvailabilityAttribute(IdentifierInfo &Availability, SourceLocation AvailabilityLoc, ParsedAttributes &attrs, diff --git a/clang/include/clang/Sema/DelayedDiagnostic.h b/clang/include/clang/Sema/DelayedDiagnostic.h index 93ecae3529231..0105089a393f1 100644 --- a/clang/include/clang/Sema/DelayedDiagnostic.h +++ b/clang/include/clang/Sema/DelayedDiagnostic.h @@ -125,12 +125,7 @@ class AccessedEntity { /// the complete parsing of the current declaration. class DelayedDiagnostic { public: - enum DDKind : unsigned char { - Availability, - FeatureAvailability, - Access, - ForbiddenType - }; + enum DDKind : unsigned char { Availability, Access, ForbiddenType }; DDKind Kind; bool Triggered; @@ -148,9 +143,6 @@ class DelayedDiagnostic { StringRef Msg, bool ObjCPropertyAccess); - static DelayedDiagnostic - makeFeatureAvailability(NamedDecl *D, ArrayRef Locs); - static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { DelayedDiagnostic DD; @@ -209,12 +201,6 @@ class DelayedDiagnostic { return AvailabilityData.AR; } - const NamedDecl *getFeatureAvailabilityDecl() const { - assert(Kind == FeatureAvailability && - "Not a feature availability diagnostic."); - return FeatureAvailabilityData.Decl; - } - /// The diagnostic ID to emit. Used like so: /// Diag(diag.Loc, diag.getForbiddenTypeDiagnostic()) /// << diag.getForbiddenTypeOperand() @@ -260,10 +246,6 @@ class DelayedDiagnostic { bool ObjCPropertyAccess; }; - struct FAD { - const NamedDecl *Decl; - }; - struct FTD { unsigned Diagnostic; unsigned Argument; @@ -272,7 +254,6 @@ class DelayedDiagnostic { union { struct AD AvailabilityData; - struct FAD FeatureAvailabilityData; struct FTD ForbiddenTypeData; /// Access control. diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h index 58b880ee339a8..29ddfada0f937 100644 --- a/clang/include/clang/Sema/ParsedAttr.h +++ b/clang/include/clang/Sema/ParsedAttr.h @@ -363,8 +363,6 @@ class ParsedAttr final return IsProperty; } - bool isAvailabilityAttribute() const { return IsAvailability; } - bool isInvalid() const { return Invalid; } void setInvalid(bool b = true) const { Invalid = b; } diff --git a/clang/include/clang/Sema/ScopeInfo.h b/clang/include/clang/Sema/ScopeInfo.h index 5fcc0de201d38..700e361ef83f1 100644 --- a/clang/include/clang/Sema/ScopeInfo.h +++ b/clang/include/clang/Sema/ScopeInfo.h @@ -144,8 +144,6 @@ class FunctionScopeInfo { /// unavailable. bool HasPotentialAvailabilityViolations : 1; - bool HasPotentialFeatureAvailabilityViolations : 1; - /// A flag that is set when parsing a method that must call super's /// implementation, such as \c -dealloc, \c -finalize, or any method marked /// with \c __attribute__((objc_requires_super)). @@ -396,8 +394,7 @@ class FunctionScopeInfo { HasBranchIntoScope(false), HasIndirectGoto(false), HasMustTail(false), HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false), HasFallthroughStmt(false), UsesFPIntrin(false), - HasPotentialAvailabilityViolations(false), - HasPotentialFeatureAvailabilityViolations(false), ObjCShouldCallSuper(false), + HasPotentialAvailabilityViolations(false), ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false), ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false), ObjCWarnForNoInitDelegation(false), NeedsCoroutineSuspends(true), FoundImmediateEscalatingExpression(false), diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 91d5d12bfc1db..4ed21972c5343 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2179,16 +2179,8 @@ class Sema final : public SemaBase { /// Issue any -Wunguarded-availability warnings in \c FD void DiagnoseUnguardedAvailabilityViolations(Decl *FD); - void DiagnoseUnguardedFeatureAvailabilityViolations(Decl *FD); - void handleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); - void handleDelayedFeatureAvailabilityCheck(sema::DelayedDiagnostic &DD, - Decl *Ctx); - - void DiagnoseFeatureAvailabilityOfDecl(NamedDecl *D, - ArrayRef Locs); - /// Retrieve the current function, if any, that should be analyzed for /// potential availability violations. sema::FunctionScopeInfo *getCurFunctionAvailabilityContext(); @@ -4729,11 +4721,6 @@ class Sema final : public SemaBase { bool CheckAttrTarget(const ParsedAttr &CurrAttr); bool CheckAttrNoArgs(const ParsedAttr &CurrAttr); - void copyFeatureAvailability(Decl *Dst, Decl *Src); - - void copyFeatureAvailabilityCheck(Decl *Dst, NamedDecl *Src, - bool Redeclaration = false); - AvailabilityAttr *mergeAvailabilityAttr( NamedDecl *D, const AttributeCommonInfo &CI, IdentifierInfo *Platform, bool Implicit, VersionTuple Introduced, VersionTuple Deprecated, diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 55b7854090a47..d9bcec2e68d93 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -901,96 +901,6 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, addTranslationUnitDecl(); } -ASTContext::AvailabilityDomainInfo -ASTContext::getFeatureAvailInfo(StringRef FeatureName) const { - FeatureAvailKind Kind = getLangOpts().getFeatureAvailability(FeatureName); - - if (Kind != FeatureAvailKind::None) - return {Kind}; - - auto I = AvailabilityDomainMap.find(FeatureName); - if (I != AvailabilityDomainMap.end()) - return I->second; - - return {}; -} - -std::pair -ASTContext::getFeatureAvailInfo(Decl *D) const { - auto *VD = cast(D); - auto *Attr = VD->getAttr(); - if (!Attr) - return {}; - StringRef Name = Attr->getName()->getName(); - auto *Init = cast(VD->getInit()); - Expr::EvalResult Result; - FeatureAvailKind Kind; - - if (!Init->getInit(0)->IgnoreParenImpCasts()->EvaluateAsInt(Result, *this)) - llvm_unreachable("initializer doesn't evaluate to integer"); - llvm::APSInt Res = Result.Val.getInt(); - unsigned Val = Res.getExtValue(); - switch (Val) { - case 0: - Kind = FeatureAvailKind::Available; - break; - case 1: - Kind = FeatureAvailKind::Unavailable; - break; - case 2: - Kind = FeatureAvailKind::Dynamic; - break; - default: - llvm_unreachable("invalid feature kind"); - } - - ASTContext::AvailabilityDomainInfo Info{Kind, nullptr}; - - if (Kind == FeatureAvailKind::Dynamic) { - Expr *FnExpr = Init->getInit(1); - auto *Call = CallExpr::Create(*this, FnExpr, {}, IntTy, VK_PRValue, - SourceLocation(), FPOptionsOverride()); - Info.Call = - ImplicitCastExpr::Create(*this, BoolTy, CK_IntegralToBoolean, Call, - nullptr, VK_PRValue, FPOptionsOverride()); - } - - return {Name, Info}; -} - -std::pair -ASTContext::checkNewFeatureAvailability(Decl *D, StringRef NewDomainName, - bool NewUnavailable) { - assert(!NewDomainName.empty()); - - for (auto *AA : D->specific_attrs()) { - if (AA->getDomain() != NewDomainName) - continue; - if (AA->getUnavailable() == NewUnavailable) - return {AA, true}; - return {AA, false}; - } - - return {nullptr, true}; -} - -bool ASTContext::hasFeatureAvailabilityAttr(const Decl *D) const { - return !D->specific_attrs().empty(); -} - -bool ASTContext::hasUnavailableFeature(const Decl *D) const { - for (auto *AA : D->specific_attrs()) { - auto FeatureName = AA->getDomain(); - auto FeatureInfo = getFeatureAvailInfo(FeatureName); - if (FeatureInfo.Kind == (AA->getUnavailable() - ? FeatureAvailKind::Available - : FeatureAvailKind::Unavailable)) - return true; - } - - return false; -} - void ASTContext::cleanup() { // Release the DenseMaps associated with DeclContext objects. // FIXME: Is this the ideal solution? diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp index 5d70812155dbc..0a705d8e17116 100644 --- a/clang/lib/AST/AttrImpl.cpp +++ b/clang/lib/AST/AttrImpl.cpp @@ -296,13 +296,6 @@ bool clang::isValidPointerAttrType(QualType T, bool RefOkay) { return T->isAnyPointerType() || T->isBlockPointerType(); } -std::string DomainAvailabilityAttr::getFeatureAttributeStr() const { - assert(!getDomain().empty() && "cannot be called if domain is empty"); - std::string S = "__attribute__((availability(domain:"; - S += getDomain().str() + ", " + (getUnavailable() ? '1' : '0') + ")))"; - return S; -} - StringLiteral *FormatMatchesAttr::getFormatString() const { return cast(getExpectedFormat()); } diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index bc3d01de78298..c4e948a38e264 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -853,12 +853,6 @@ bool Decl::isWeakImported() const { if (CheckAvailability(getASTContext(), Availability, nullptr, VersionTuple()) == AR_NotYetIntroduced) return true; - } else if (const auto *DA = dyn_cast(A)) { - auto DomainName = DA->getDomain(); - auto FeatureInfo = getASTContext().getFeatureAvailInfo(DomainName); - if (FeatureInfo.Kind == FeatureAvailKind::Dynamic) - return true; - continue; } } diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index d89b9ef6548b9..e61497cf14888 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -11986,30 +11986,6 @@ class IntExprEvaluator return Success(E->getValue(), E); } - bool VisitObjCAvailabilityCheckExpr(const ObjCAvailabilityCheckExpr *E) { - if (!E->hasDomainName()) - return false; - auto FeatureName = E->getDomainName(); - auto FeatureInfo = Info.Ctx.getFeatureAvailInfo(FeatureName); - unsigned ResultInt; - - switch (FeatureInfo.Kind) { - case FeatureAvailKind::Available: - ResultInt = 1; - break; - case FeatureAvailKind::Unavailable: - ResultInt = 0; - break; - case FeatureAvailKind::Dynamic: - return false; - case FeatureAvailKind::None: - llvm_unreachable("unexpected feature kind"); - } - - return Success(APSInt(APInt(Info.Ctx.getIntWidth(E->getType()), ResultInt)), - E); - } - bool CheckReferencedDecl(const Expr *E, const Decl *D); bool VisitDeclRefExpr(const DeclRefExpr *E) { if (CheckReferencedDecl(E, E->getDecl())) diff --git a/clang/lib/AST/ExprObjC.cpp b/clang/lib/AST/ExprObjC.cpp index cecfb869cea62..a3222c2da24fd 100644 --- a/clang/lib/AST/ExprObjC.cpp +++ b/clang/lib/AST/ExprObjC.cpp @@ -350,26 +350,3 @@ StringRef ObjCBridgedCastExpr::getBridgeKindName() const { llvm_unreachable("Invalid BridgeKind!"); } - -ObjCAvailabilityCheckExpr *ObjCAvailabilityCheckExpr::CreateEmpty( - const ASTContext &C, Stmt::EmptyShell Empty, size_t FeaturesLen) { - ObjCAvailabilityCheckExpr *E = (ObjCAvailabilityCheckExpr *)C.Allocate( - totalSizeToAlloc(FeaturesLen + 1), - alignof(ObjCAvailabilityCheckExpr)); - new (E) ObjCAvailabilityCheckExpr(Empty); - bzero(E->getTrailingObjects(), FeaturesLen + 1); - return E; -} - -ObjCAvailabilityCheckExpr * -ObjCAvailabilityCheckExpr::CreateAvailabilityFeatureCheck(SourceLocation AtLoc, - SourceLocation RParen, - QualType Ty, - StringRef DomainName, - const ASTContext &C) { - ObjCAvailabilityCheckExpr *E = (ObjCAvailabilityCheckExpr *)C.Allocate( - totalSizeToAlloc(DomainName.size() + 1), - alignof(ObjCAvailabilityCheckExpr)); - new (E) ObjCAvailabilityCheckExpr(AtLoc, RParen, Ty, DomainName); - return E; -} diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 5aa544626ce02..d9bf62c2bbb04 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -1859,9 +1859,6 @@ void ItaniumRecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { void ItaniumRecordLayoutBuilder::LayoutField(const FieldDecl *D, bool InsertExtraPadding) { - if (Context.hasUnavailableFeature(D)) - return; - auto *FieldClass = D->getType()->getAsCXXRecordDecl(); bool IsOverlappingEmptyField = D->isPotentiallyOverlapping() && FieldClass->isEmpty(); @@ -3524,8 +3521,6 @@ uint64_t ASTContext::lookupFieldBitOffset(const ObjCInterfaceDecl *OID, for (const ObjCIvarDecl *IVD = Container->all_declared_ivar_begin(); IVD; IVD = IVD->getNextIvar()) { - if (hasUnavailableFeature(IVD)) - continue; if (Ivar == IVD) break; ++Index; diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 353ca585dbe76..5707554f51f91 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -3902,14 +3902,6 @@ static void RenderBuiltinOptions(const ToolChain &TC, const llvm::Triple &T, CmdArgs.push_back("-fno-math-builtin"); } -static void RenderFeatueAvailabilityOptions(const ArgList &Args, - ArgStringList &CmdArgs) { - for (const Arg *A : Args.filtered(options::OPT_ffeature_availability_EQ)) { - A->claim(); - A->render(Args, CmdArgs); - } -} - bool Driver::getDefaultModuleCachePath(SmallVectorImpl &Result) { if (const char *Str = std::getenv("CLANG_MODULE_CACHE_PATH")) { Twine Path{Str}; @@ -7186,8 +7178,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &Job, } RenderBuiltinOptions(TC, RawTriple, Args, CmdArgs); - RenderFeatueAvailabilityOptions(Args, CmdArgs); - Args.addOptOutFlag(CmdArgs, options::OPT_fassume_sane_operator_new, options::OPT_fno_assume_sane_operator_new); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index ddbd7e07820a5..e40d530313bce 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4131,34 +4131,6 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_frandomize_layout_seed_EQ, Opts.RandstructSeed); } -static bool parseFeatureAvailability(const Arg *A, LangOptions &Opts, - DiagnosticsEngine &Diags) { - llvm::StringRef ArgRef(A->getValue()); - auto Split = ArgRef.split(':'); - llvm::StringRef Feature = Split.first; - std::string StateStr = Split.second.lower(); - - if (Feature.empty() || StateStr.empty()) { - Diags.Report(clang::diag::err_feature_availability_flag_invalid_value) - << ArgRef; - return false; - } - - FeatureAvailKind State; - if (StateStr == "on" || StateStr == "1") { - State = FeatureAvailKind::Available; - } else if (StateStr == "off" || StateStr == "0") { - State = FeatureAvailKind::Unavailable; - } else { - Diags.Report(clang::diag::err_feature_availability_flag_invalid_value) - << ArgRef; - return false; - } - - Opts.setFeatureAvailability(Feature, State); - return true; -} - bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, const llvm::Triple &T, std::vector &Includes, @@ -4183,9 +4155,6 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, return Diags.getNumErrors() == NumErrorsBefore; } - for (const Arg *A : Args.filtered(OPT_ffeature_availability_EQ)) - parseFeatureAvailability(A, Opts, Diags); - // Other LangOpts are only initialized when the input is not AST or LLVM IR. // FIXME: Should we really be parsing this for an Language::Asm input? diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt index 791a90be4e3d4..c86aabe70c16f 100644 --- a/clang/lib/Headers/CMakeLists.txt +++ b/clang/lib/Headers/CMakeLists.txt @@ -36,7 +36,6 @@ set(core_files tgmath.h unwind.h varargs.h - feature-availability.h ) set(arm_common_files diff --git a/clang/lib/Headers/feature-availability.h b/clang/lib/Headers/feature-availability.h deleted file mode 100644 index 31abd2e4e081b..0000000000000 --- a/clang/lib/Headers/feature-availability.h +++ /dev/null @@ -1,33 +0,0 @@ -/*===---- feature_availability.h - Feature Availability --------------------=== - * - * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - * See https://llvm.org/LICENSE.txt for license information. - * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - * - *===-----------------------------------------------------------------------=== - */ - -#ifndef __FEATURE_AVAILABILITY_H -#define __FEATURE_AVAILABILITY_H - -#include - -/// The possible availability domain states. These values are hardcoded in the -/// compiler and reproduced here for convenience when defining domains. - -#define __AVAILABILITY_DOMAIN_ENABLED 0 -#define __AVAILABILITY_DOMAIN_DISABLED 1 -#define __AVAILABILITY_DOMAIN_DYNAMIC 2 - -/// A struct describing availability domain definitions. This struct definition -/// is just a convenience to ensure that a header defining an availability -/// domain can define it with the arguments that Clang expects at parse time. -struct __AvailabilityDomain { - /// The state of the domain (AVAILABLE, UNAVAILABLE, DYNAMIC, etc.). - intptr_t state; - /// An optional function pointer to call to query the availability of a domain - /// at runtime. This should only be non-null for domains in the DYNAMIC state. - int (*const runtimeQuery)(void); -}; - -#endif /* __FEATURE_AVAILABILITY_H */ diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 5f684b09f1fcf..8c51ca6561cf8 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1296,55 +1296,6 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { return VersionTuple(Major, Minor, Subminor); } -void Parser::ParseFeatureAvailabilityAttribute( - IdentifierInfo &Availability, SourceLocation AvailabilityLoc, - ParsedAttributes &attrs, SourceLocation *endLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, ParsedAttr::Form Form, - BalancedDelimiterTracker &T) { - - if (Tok.isNot(tok::colon)) { - Diag(Tok, diag::err_expected) << tok::colon; - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - ConsumeToken(); - - if (Tok.isNot(tok::identifier)) { - Diag(Tok, diag::err_features_domain_name); - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - ArgsVector ArgExprs; - IdentifierLoc *Feature = ParseIdentifierLoc(); - ArgExprs.push_back(Feature); - - if (ExpectAndConsume(tok::comma)) { - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - if (Tok.isNot(tok::numeric_constant)) { - Diag(Tok, diag::err_expected) << tok::numeric_constant; - SkipUntil(tok::r_paren, StopAtSemi); - return; - } - - ExprResult ExprRes(Actions.ActOnNumericConstant(Tok, getCurScope())); - ArgExprs.push_back(ExprRes.get()); - - ConsumeToken(); - - // Closing ')'. - if (T.consumeClose()) - return; - - attrs.addNew(&Availability, - SourceRange(AvailabilityLoc, T.getCloseLocation()), ScopeName, - ScopeLoc, ArgExprs.data(), ArgExprs.size(), Form); -} - /// Parse the contents of the "availability" attribute. /// /// availability-attribute: @@ -1394,11 +1345,6 @@ void Parser::ParseAvailabilityAttribute( } IdentifierLoc *Platform = ParseIdentifierLoc(); if (const IdentifierInfo *const Ident = Platform->Ident) { - if (!Ident->getName().compare("domain")) { - ParseFeatureAvailabilityAttribute(Availability, AvailabilityLoc, attrs, - endLoc, ScopeName, ScopeLoc, Form, T); - return; - } // Disallow xrOS for availability attributes. if (Ident->getName().contains("xrOS") || Ident->getName().contains("xros")) Diag(Platform->Loc, diag::warn_availability_unknown_platform) << Ident; diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index b42a94751eb60..30fe6dc1b8cd1 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -3927,15 +3927,6 @@ static bool CheckAvailabilitySpecList(Parser &P, bool HasOtherPlatformSpec = false; bool Valid = true; for (const auto &Spec : AvailSpecs) { - if (Spec.isDomainName()) { - if (AvailSpecs.size() != 1) { - P.Diag(Spec.getBeginLoc(), - diag::err_feature_invalid_availability_check); - return true; - } - return false; - } - if (Spec.isOtherPlatformSpec()) { if (HasOtherPlatformSpec) { P.Diag(Spec.getBeginLoc(), diag::err_availability_query_repeated_star); @@ -3983,23 +3974,6 @@ std::optional Parser::ParseAvailabilitySpec() { Actions.CodeCompletion().CodeCompleteAvailabilityPlatformName(); return std::nullopt; } - - if (Tok.is(tok::identifier) && GetLookAheadToken(1).is(tok::colon)) { - if (ParseIdentifierLoc()->Ident->getName() != "domain") { - return std::nullopt; - } - - ConsumeToken(); // colon - - if (Tok.isNot(tok::identifier)) { - return std::nullopt; - } - - IdentifierLoc *DomainIdentifier = ParseIdentifierLoc(); - return AvailabilitySpec(DomainIdentifier->Ident->getName(), - DomainIdentifier->Loc); - } - if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_avail_query_expected_platform_name); return std::nullopt; @@ -4250,4 +4224,4 @@ ExprResult Parser::ParseUnsafeTerminatedByFromIndexable() { Terminator.get(), Pointer.get(), PointerToTerminator, KWLoc, T.getCloseLocation()); } -/* TO_UPSTREAM(BoundsSafety) OFF*/ +/* TO_UPSTREAM(BoundsSafety) OFF*/ \ No newline at end of file diff --git a/clang/lib/Parse/ParseObjc.cpp b/clang/lib/Parse/ParseObjc.cpp index 28dac692c9a90..86210ab7bac2b 100644 --- a/clang/lib/Parse/ParseObjc.cpp +++ b/clang/lib/Parse/ParseObjc.cpp @@ -2929,26 +2929,27 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { return ParsePostfixExpressionSuffix(ParseObjCSelectorExpression(AtLoc)); case tok::objc_available: return ParseAvailabilityCheckExpr(AtLoc); - default: { - const char *str = nullptr; - // Only provide the @try/@finally/@autoreleasepool fixit when we're sure - // that this is a proper statement where such directives could actually - // occur. - if (GetLookAheadToken(1).is(tok::l_brace) && - ExprStatementTokLoc == AtLoc) { - char ch = Tok.getIdentifierInfo()->getNameStart()[0]; - str = ch == 't' - ? "try" - : (ch == 'f' ? "finally" - : (ch == 'a' ? "autoreleasepool" : nullptr)); + default: { + const char *str = nullptr; + // Only provide the @try/@finally/@autoreleasepool fixit when we're sure + // that this is a proper statement where such directives could actually + // occur. + if (GetLookAheadToken(1).is(tok::l_brace) && + ExprStatementTokLoc == AtLoc) { + char ch = Tok.getIdentifierInfo()->getNameStart()[0]; + str = + ch == 't' ? "try" + : (ch == 'f' ? "finally" + : (ch == 'a' ? "autoreleasepool" : nullptr)); + } + if (str) { + SourceLocation kwLoc = Tok.getLocation(); + return ExprError(Diag(AtLoc, diag::err_unexpected_at) << + FixItHint::CreateReplacement(kwLoc, str)); + } + else + return ExprError(Diag(AtLoc, diag::err_unexpected_at)); } - if (str) { - SourceLocation kwLoc = Tok.getLocation(); - return ExprError(Diag(AtLoc, diag::err_unexpected_at) - << FixItHint::CreateReplacement(kwLoc, str)); - } else - return ExprError(Diag(AtLoc, diag::err_unexpected_at)); - } } } } diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt index 5d02f7e3737e6..f091d10afbad7 100644 --- a/clang/lib/Sema/CMakeLists.txt +++ b/clang/lib/Sema/CMakeLists.txt @@ -61,7 +61,6 @@ add_clang_library(clangSema SemaExprCXX.cpp SemaExprMember.cpp SemaExprObjC.cpp - SemaFeatureAvailability.cpp SemaFixItUtils.cpp SemaFunctionEffects.cpp SemaHLSL.cpp diff --git a/clang/lib/Sema/DelayedDiagnostic.cpp b/clang/lib/Sema/DelayedDiagnostic.cpp index ff814a0e9b140..cb2721b92090e 100644 --- a/clang/lib/Sema/DelayedDiagnostic.cpp +++ b/clang/lib/Sema/DelayedDiagnostic.cpp @@ -56,18 +56,6 @@ DelayedDiagnostic::makeAvailability(AvailabilityResult AR, return DD; } -DelayedDiagnostic -DelayedDiagnostic::makeFeatureAvailability(NamedDecl *D, - ArrayRef Locs) { - assert(!Locs.empty()); - DelayedDiagnostic DD; - DD.Kind = FeatureAvailability; - DD.Triggered = false; - DD.Loc = Locs.front(); - DD.FeatureAvailabilityData.Decl = D; - return DD; -} - void DelayedDiagnostic::Destroy() { switch (Kind) { case Access: @@ -79,7 +67,6 @@ void DelayedDiagnostic::Destroy() { delete[] AvailabilityData.SelectorLocs; break; - case FeatureAvailability: case ForbiddenType: break; } diff --git a/clang/lib/Sema/ScopeInfo.cpp b/clang/lib/Sema/ScopeInfo.cpp index 86674b9f1d810..12fb706072723 100644 --- a/clang/lib/Sema/ScopeInfo.cpp +++ b/clang/lib/Sema/ScopeInfo.cpp @@ -31,7 +31,6 @@ void FunctionScopeInfo::Clear() { HasFallthroughStmt = false; UsesFPIntrin = false; HasPotentialAvailabilityViolations = false; - HasPotentialFeatureAvailabilityViolations = false; ObjCShouldCallSuper = false; ObjCIsDesignatedInit = false; ObjCWarnForNoDesignatedInitChain = false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a956ec9430350..0a733f00d231b 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3240,9 +3240,6 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, Diag(Old->getLocation(), diag::note_previous_declaration); } - if (auto *ND = dyn_cast(Old)) - copyFeatureAvailabilityCheck(New, ND, true); - if (!Old->hasAttrs()) return; @@ -15649,12 +15646,6 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) { } } - std::pair ADInfo = - getASTContext().getFeatureAvailInfo(VD); - - if (!ADInfo.first.empty()) - getASTContext().addAvailabilityDomainMap(ADInfo.first, ADInfo.second); - const DeclContext *DC = VD->getDeclContext(); // If there's a #pragma GCC visibility in scope, and this isn't a class // member, set the visibility of this variable. @@ -17232,9 +17223,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, if (Body && FSI->HasPotentialAvailabilityViolations) DiagnoseUnguardedAvailabilityViolations(dcl); - if (Body && FSI->HasPotentialFeatureAvailabilityViolations) - DiagnoseUnguardedFeatureAvailabilityViolations(dcl); - assert(!FSI->ObjCShouldCallSuper && "This should only be set for ObjC methods, which should have been " "handled in the block above."); @@ -19617,7 +19605,6 @@ FieldDecl *Sema::CheckFieldDecl(DeclarationName Name, QualType T, if (D) { // FIXME: The current scope is almost... but not entirely... correct here. ProcessDeclAttributes(getCurScope(), NewFD, *D); - copyFeatureAvailabilityCheck(NewFD, Record); if (NewFD->hasAttrs()) CheckAlignasUnderalignment(NewFD); @@ -20772,7 +20759,6 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, // Process attributes. ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); - copyFeatureAvailabilityCheck(New, TheEnumDecl); ProcessAPINotes(New); // Register this decl in the current scope stack. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 57228b5337530..993a1fb662ac7 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2250,72 +2250,7 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr( return nullptr; } -static void handleFeatureAvailabilityAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - if (S.getLangOpts().CPlusPlus) { - S.Diag(AL.getLoc(), diag::warn_attribute_ignored) << AL; - return; - } - - if (!AL.isArgIdent(0)) { - S.Diag(AL.getLoc(), diag::err_attribute_argument_n_type) - << AL << 0 << AANT_ArgumentIdentifier; - return; - } - - StringRef InvalidDecl; - - if (isa(D)) - InvalidDecl = "ObjC class implementations"; - else if (isa(D)) - InvalidDecl = "ObjC category implementations"; - else if (auto *FD = dyn_cast(D)) { - if (FD->getParent()) - InvalidDecl = "struct members"; - } - - if (!InvalidDecl.empty()) { - S.Diag(AL.getLoc(), diag::err_features_invalid_for_decl) << InvalidDecl; - return; - } - - IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; - - if (S.Context.getFeatureAvailInfo(II->getName()).isInvalid()) { - S.Diag(AL.getLoc(), diag::err_features_invalid_name) << II->getName(); - return; - } - - int IsUnavailable = - AL.getArgAsExpr(1)->getIntegerConstantExpr(S.Context)->getExtValue(); - - if (IsUnavailable != 0 && IsUnavailable != 1) { - S.Diag(AL.getArgAsExpr(1)->getExprLoc(), diag::err_features_invalid__arg) - << IsUnavailable; - return; - } - - auto p = - S.Context.checkNewFeatureAvailability(D, II->getName(), IsUnavailable); - if (!p.second) { - auto *AA = DomainAvailabilityAttr::Create(S.Context, II->getName(), - IsUnavailable, AL); - S.Diag(D->getBeginLoc(), diag::err_feature_invalid_added); - S.Diag(AL.getLoc(), diag::note_feature_incompatible0) - << AA->getFeatureAttributeStr(); - S.Diag(p.first->getLocation(), diag::note_feature_incompatible1) - << p.first->getFeatureAttributeStr(); - } else if (!p.first) - D->addAttr(DomainAvailabilityAttr::Create(S.Context, II->getName(), - IsUnavailable, AL)); -} - static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { - if (!AL.isAvailabilityAttribute()) { - handleFeatureAvailabilityAttr(S, D, AL); - return; - } - if (isa( D)) { S.Diag(AL.getRange().getBegin(), diag::warn_deprecated_ignored_on_using) @@ -2588,12 +2523,6 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } -static void handleAvailabilityDomainAttr(Sema &S, Decl *D, - const ParsedAttr &AL) { - IdentifierInfo *II = AL.getArgAsIdent(0)->Ident; - D->addAttr(::new (S.Context) AvailabilityDomainAttr(S.Context, AL, II)); -} - static void handleExternalSourceSymbolAttr(Sema &S, Decl *D, const ParsedAttr &AL) { if (!AL.checkAtLeastNumArgs(S, 1) || !AL.checkAtMostNumArgs(S, 4)) @@ -3610,55 +3539,6 @@ struct FormatAttrCommon { unsigned FormatStringIdx; }; -void Sema::copyFeatureAvailability(Decl *Dst, Decl *Src) { - if (Dst->isInvalidDecl()) - return; - - for (auto *AA : Src->specific_attrs()) { - auto *NewAttr = AA->clone(Context); - NewAttr->setInherited(true); - Dst->addAttr(NewAttr); - } -} - -void Sema::copyFeatureAvailabilityCheck(Decl *Dst, NamedDecl *Src, - bool Redeclaration) { - if (Dst->isInvalidDecl()) - return; - - llvm::SmallDenseMap DstToAttr; - - for (auto *AA : Dst->specific_attrs()) - DstToAttr[AA->getDomain()] = AA; - - for (auto *AA : Src->specific_attrs()) { - auto I = DstToAttr.find(AA->getDomain()); - if (I == DstToAttr.end()) { - auto *NewAttr = AA->clone(Context); - NewAttr->setInherited(true); - Dst->addAttr(NewAttr); - } else { - if (I->second->getUnavailable() != AA->getUnavailable()) { - Diag(Dst->getBeginLoc(), diag::err_feature_merge_incompatible); - Diag(I->second->getLocation(), diag::note_feature_incompatible0) - << I->second->getFeatureAttributeStr(); - Diag(AA->getLocation(), diag::note_feature_incompatible1) - << AA->getFeatureAttributeStr(); - Dst->setInvalidDecl(); - } - DstToAttr.erase(I); - } - } - - if (Redeclaration) { - if (!DstToAttr.empty()) - Dst->setInvalidDecl(); - for (auto &P : DstToAttr) - Diag(P.second->getLocation(), diag::err_new_feature_redeclaration) - << P.second->getFeatureAttributeStr(); - } -} - /// Handle __attribute__((format(type,idx,firstarg))) attributes based on /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html static bool handleFormatAttrCommon(Sema &S, Decl *D, const ParsedAttr &AL, @@ -8840,10 +8720,6 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL, handleSimpleAttribute(S, D, AL); break; - case ParsedAttr::AT_AvailabilityDomain: - handleAvailabilityDomainAttr(S, D, AL); - break; - case ParsedAttr::AT_ArmNew: S.ARM().handleNewAttr(D, AL); break; @@ -9274,12 +9150,6 @@ void Sema::PopParsingDeclaration(ParsingDeclState state, Decl *decl) { handleDelayedAvailabilityCheck(diag, decl); break; - case DelayedDiagnostic::FeatureAvailability: - // Don't bother giving diagnostics if the decl is invalid. - if (!decl->isInvalidDecl()) - handleDelayedFeatureAvailabilityCheck(diag, decl); - break; - case DelayedDiagnostic::Access: // Only produce one access control diagnostic for a structured binding // declaration: we don't need to tell the user that all the fields are diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index a299bb6eb3b77..9ba8f0cc258b1 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -1893,7 +1893,6 @@ ObjCCategoryDecl *SemaObjC::ActOnStartCategoryInterface( // checking for protocol uses. SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, AttrList); SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl); - SemaRef.copyFeatureAvailabilityCheck(CDecl, IDecl); if (NumProtoRefs) { diagnoseUseOfProtocols(SemaRef, CDecl, (ObjCProtocolDecl *const *)ProtoRefs, @@ -1949,8 +1948,6 @@ ObjCCategoryImplDecl *SemaObjC::ActOnStartCategoryImplementation( SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, CDecl, Attrs); SemaRef.AddPragmaAttributes(SemaRef.TUScope, CDecl); - if (CatIDecl) - SemaRef.copyFeatureAvailabilityCheck(CDecl, CatIDecl); // FIXME: PushOnScopeChains? SemaRef.CurContext->addDecl(CDecl); @@ -2085,7 +2082,6 @@ ObjCImplementationDecl *SemaObjC::ActOnStartClassImplementation( SemaRef.ProcessDeclAttributeList(SemaRef.TUScope, IMPDecl, Attrs); SemaRef.AddPragmaAttributes(SemaRef.TUScope, IMPDecl); - SemaRef.copyFeatureAvailabilityCheck(IMPDecl, IDecl); if (CheckObjCDeclScope(IMPDecl)) { ActOnObjCContainerStartDefinition(IMPDecl); @@ -5138,8 +5134,6 @@ Decl *SemaObjC::ActOnMethodDeclaration( // Insert the invisible arguments, self and _cmd! ObjCMethod->createImplicitParams(Context, ObjCMethod->getClassInterface()); - SemaRef.copyFeatureAvailabilityCheck(ObjCMethod, cast(ClassDecl)); - SemaRef.ActOnDocumentableDecl(ObjCMethod); return ObjCMethod; @@ -5714,7 +5708,6 @@ Decl *SemaObjC::ActOnIvar(Scope *S, SourceLocation DeclStart, Declarator &D, // Process attributes attached to the ivar. SemaRef.ProcessDeclAttributes(S, NewID, D); - SemaRef.copyFeatureAvailabilityCheck(NewID, EnclosingContext); if (D.isInvalidType()) NewID->setInvalidDecl(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 153e21f8c85a3..7cf4c71d7d0d3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -369,8 +369,6 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, ArrayRef Locs, DiagnoseAvailabilityOfDecl(D, Locs, UnknownObjCClass, ObjCPropertyAccess, AvoidPartialAvailabilityChecks, ClassReceiver); - DiagnoseFeatureAvailabilityOfDecl(D, Locs); - DiagnoseUnusedOfDecl(*this, D, Loc); diagnoseUseOfInternalDeclInInlineFunction(*this, D, Loc); @@ -19388,9 +19386,6 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (Body && getCurFunction()->HasPotentialAvailabilityViolations) DiagnoseUnguardedAvailabilityViolations(BD); - if (Body && getCurFunction()->HasPotentialFeatureAvailabilityViolations) - DiagnoseUnguardedFeatureAvailabilityViolations(BD); - // Try to apply the named return value optimization. We have to check again // if we can do this, though, because blocks keep return statements around // to deduce an implicit return type. diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 77e919ca29e16..dc281d2bcb97e 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -5152,13 +5152,6 @@ ExprResult SemaObjC::ActOnObjCAvailabilityCheckExpr( llvm::ArrayRef AvailSpecs, SourceLocation AtLoc, SourceLocation RParen) { ASTContext &Context = getASTContext(); - - if (AvailSpecs.front().isDomainName()) { - auto Spec = AvailSpecs.front(); - return ObjCAvailabilityCheckExpr::CreateAvailabilityFeatureCheck( - AtLoc, RParen, Context.BoolTy, Spec.getDomainName(), Context); - } - auto FindSpecVersion = [&](StringRef Platform) -> std::optional { auto Spec = llvm::find_if(AvailSpecs, [&](const AvailabilitySpec &Spec) { diff --git a/clang/lib/Sema/SemaFeatureAvailability.cpp b/clang/lib/Sema/SemaFeatureAvailability.cpp deleted file mode 100644 index e90cdfc92606f..0000000000000 --- a/clang/lib/Sema/SemaFeatureAvailability.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//===--- SemaFeatureAvailability.cpp - Availability attribute handling ----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file processes the feature availability attribute. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/Attr.h" -#include "clang/AST/Decl.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/Sema/DelayedDiagnostic.h" -#include "clang/Sema/ScopeInfo.h" -#include "clang/Sema/Sema.h" -#include "llvm/ADT/SmallSet.h" -#include - -using namespace clang; -using namespace sema; - -static bool isFeatureUseGuarded(const DomainAvailabilityAttr *AA, - const Decl *ContextDecl, ASTContext &Ctx) { - for (auto *Attr : ContextDecl->specific_attrs()) - if (AA->getDomain() == Attr->getDomain()) - return AA->getUnavailable() == Attr->getUnavailable(); - return false; -} - -static void diagnoseDeclFeatureAvailability(const NamedDecl *D, - SourceLocation Loc, - Decl *ContextDecl, Sema &S) { - for (auto *Attr : D->specific_attrs()) - if (!isFeatureUseGuarded(Attr, ContextDecl, S.Context)) - S.Diag(Loc, diag::err_unguarded_feature) - << D << Attr->getDomain().str() << Attr->getUnavailable(); -} - -class DiagnoseUnguardedFeatureAvailability - : public RecursiveASTVisitor { - - typedef RecursiveASTVisitor Base; - - Sema &SemaRef; - const Decl *D; - - struct FeatureAvailInfo { - StringRef Domain; - bool Unavailable; - }; - - SmallVector FeatureStack; - - bool isFeatureUseGuarded(const DomainAvailabilityAttr *Attr) const; - - bool isConditionallyGuardedByFeature() const; - -public: - DiagnoseUnguardedFeatureAvailability(Sema &SemaRef, const Decl *D, - Decl *Ctx = nullptr) - : SemaRef(SemaRef), D(D) {} - - void diagnoseDeclFeatureAvailability(const NamedDecl *D, SourceLocation Loc); - - bool TraverseIfStmt(IfStmt *If); - - bool VisitDeclRefExpr(DeclRefExpr *DRE) { - diagnoseDeclFeatureAvailability(DRE->getDecl(), DRE->getBeginLoc()); - return true; - } - - bool VisitMemberExpr(MemberExpr *ME) { - diagnoseDeclFeatureAvailability(ME->getMemberDecl(), ME->getBeginLoc()); - return true; - } - - bool VisitObjCMessageExpr(ObjCMessageExpr *OME) { - diagnoseDeclFeatureAvailability(OME->getMethodDecl(), OME->getBeginLoc()); - return true; - } - - bool VisitLabelStmt(LabelStmt *LS) { - if (isConditionallyGuardedByFeature()) - SemaRef.Diag(LS->getBeginLoc(), - diag::err_label_in_conditionally_guarded_feature); - return true; - } - - bool VisitTypeLoc(TypeLoc Ty); - - void IssueDiagnostics() { - if (auto *FD = dyn_cast(D)) - TraverseStmt(FD->getBody()); - else if (auto *OMD = dyn_cast(D)) - TraverseStmt(OMD->getBody()); - } -}; - -static std::pair extractFeatureExpr(const Expr *IfCond) { - const auto *E = IfCond; - bool IsNegated = false; - while (true) { - E = E->IgnoreParens(); - if (const auto *AE = dyn_cast(E)) { - if (!AE->hasDomainName()) - return {}; - return {AE->getDomainName(), IsNegated}; - } - - const auto *UO = dyn_cast(E); - if (!UO || UO->getOpcode() != UO_LNot) { - return {}; - } - E = UO->getSubExpr(); - IsNegated = !IsNegated; - } -} - -bool DiagnoseUnguardedFeatureAvailability::isConditionallyGuardedByFeature() - const { - return FeatureStack.size(); -} - -bool DiagnoseUnguardedFeatureAvailability::TraverseIfStmt(IfStmt *If) { - std::pair IfCond; - if (auto *Cond = If->getCond()) - IfCond = extractFeatureExpr(Cond); - if (IfCond.first.empty()) { - // This isn't an availability checking 'if', we can just continue. - return Base::TraverseIfStmt(If); - } - - StringRef FeatureStr = IfCond.first; - auto *Guarded = If->getThen(); - auto *Unguarded = If->getElse(); - if (IfCond.second) { - std::swap(Guarded, Unguarded); - } - - FeatureStack.push_back({FeatureStr, false}); - bool ShouldContinue = TraverseStmt(Guarded); - FeatureStack.pop_back(); - - if (!ShouldContinue) - return false; - - FeatureStack.push_back({FeatureStr, true}); - ShouldContinue = TraverseStmt(Unguarded); - FeatureStack.pop_back(); - return ShouldContinue; -} - -bool DiagnoseUnguardedFeatureAvailability::isFeatureUseGuarded( - const DomainAvailabilityAttr *Attr) const { - auto Domain = Attr->getDomain(); - for (auto &Info : FeatureStack) - if (Info.Domain == Domain && Info.Unavailable == Attr->getUnavailable()) - return true; - return ::isFeatureUseGuarded(Attr, D, SemaRef.Context); -} - -void DiagnoseUnguardedFeatureAvailability::diagnoseDeclFeatureAvailability( - const NamedDecl *D, SourceLocation Loc) { - for (auto *Attr : D->specific_attrs()) { - std::string FeatureUse = Attr->getDomain().str(); - if (!isFeatureUseGuarded(Attr)) - SemaRef.Diag(Loc, diag::err_unguarded_feature) - << D << FeatureUse << Attr->getUnavailable(); - } -} - -bool DiagnoseUnguardedFeatureAvailability::VisitTypeLoc(TypeLoc Ty) { - const Type *TyPtr = Ty.getTypePtr(); - SourceLocation Loc = Ty.getBeginLoc(); - - if (Loc.isInvalid()) - return true; - - if (const auto *TT = dyn_cast(TyPtr)) { - TagDecl *TD = TT->getDecl(); - diagnoseDeclFeatureAvailability(TD, Ty.getBeginLoc()); - } else if (const auto *TD = dyn_cast(TyPtr)) { - TypedefNameDecl *D = TD->getDecl(); - diagnoseDeclFeatureAvailability(D, Ty.getBeginLoc()); - } else if (const auto *ObjCO = dyn_cast(TyPtr)) { - if (NamedDecl *D = ObjCO->getInterface()) - diagnoseDeclFeatureAvailability(D, Ty.getBeginLoc()); - } - - return true; -} - -void Sema::handleDelayedFeatureAvailabilityCheck(DelayedDiagnostic &DD, - Decl *Ctx) { - assert(DD.Kind == DelayedDiagnostic::FeatureAvailability && - "Expected a feature availability diagnostic here"); - - DD.Triggered = true; - diagnoseDeclFeatureAvailability(DD.getFeatureAvailabilityDecl(), DD.Loc, Ctx, - *this); -} - -void Sema::DiagnoseUnguardedFeatureAvailabilityViolations(Decl *D) { - assert((D->getAsFunction() || isa(D)) && - "function or ObjC method decl expected"); - DiagnoseUnguardedFeatureAvailability(*this, D).IssueDiagnostics(); -} - -void Sema::DiagnoseFeatureAvailabilityOfDecl(NamedDecl *D, - ArrayRef Locs) { - if (!Context.hasFeatureAvailabilityAttr(D)) - return; - - if (FunctionScopeInfo *Context = getCurFunctionAvailabilityContext()) { - Context->HasPotentialFeatureAvailabilityViolations = true; - return; - } - - if (DelayedDiagnostics.shouldDelayDiagnostics()) { - DelayedDiagnostics.add(DelayedDiagnostic::makeFeatureAvailability(D, Locs)); - return; - } - - Decl *Ctx = cast(getCurLexicalContext()); - diagnoseDeclFeatureAvailability(D, Locs.front(), Ctx, *this); -} diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index b819f9547b5b9..f1495125b1979 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -632,8 +632,6 @@ ObjCPropertyDecl *SemaObjC::CreatePropertyDecl( SemaRef.ProcessDeclAttributes(S, PDecl, FD.D); - SemaRef.copyFeatureAvailabilityCheck(PDecl, CDecl); - if (Attributes & ObjCPropertyAttribute::kind_readonly) PDecl->setPropertyAttributes(ObjCPropertyAttribute::kind_readonly); @@ -1304,8 +1302,6 @@ Decl *SemaObjC::ActOnPropertyImplDecl( PropertyIvarType, /*TInfo=*/nullptr, ObjCIvarDecl::Private, (Expr *)nullptr, true); - SemaRef.copyFeatureAvailabilityCheck(Ivar, property); - SemaRef.copyFeatureAvailabilityCheck(Ivar, ClassImpDecl); if (SemaRef.RequireNonAbstractType(PropertyIvarLoc, PropertyIvarType, diag::err_abstract_type_in_decl, Sema::AbstractSynthesizedIvarType)) { @@ -1410,9 +1406,6 @@ Decl *SemaObjC::ActOnPropertyImplDecl( : ObjCPropertyImplDecl::Dynamic), Ivar, PropertyIvarLoc); - SemaRef.copyFeatureAvailabilityCheck(PIDecl, property); - SemaRef.copyFeatureAvailabilityCheck(PIDecl, ClassImpDecl); - if (CompleteTypeErr || !compat) PIDecl->setInvalidDecl(); @@ -1424,11 +1417,9 @@ Decl *SemaObjC::ActOnPropertyImplDecl( // If the method hasn't been overridden, create a synthesized implementation. ObjCMethodDecl *OMD = ClassImpDecl->getMethod( getterMethod->getSelector(), getterMethod->isInstanceMethod()); - if (!OMD) { + if (!OMD) OMD = RedeclarePropertyAccessor(Context, IC, getterMethod, AtLoc, PropertyLoc); - SemaRef.copyFeatureAvailability(OMD, PIDecl); - } PIDecl->setGetterMethodDecl(OMD); } @@ -1490,11 +1481,9 @@ Decl *SemaObjC::ActOnPropertyImplDecl( if (Synthesize) { ObjCMethodDecl *OMD = ClassImpDecl->getMethod( setterMethod->getSelector(), setterMethod->isInstanceMethod()); - if (!OMD) { + if (!OMD) OMD = RedeclarePropertyAccessor(Context, IC, setterMethod, AtLoc, PropertyLoc); - SemaRef.copyFeatureAvailability(OMD, PIDecl); - } PIDecl->setSetterMethodDecl(OMD); } @@ -2358,7 +2347,6 @@ static void AddPropertyAttrs(Sema &S, ObjCMethodDecl *PropertyMethod, isa(A)) PropertyMethod->addAttr(A->clone(S.Context)); } - S.copyFeatureAvailabilityCheck(PropertyMethod, Property); } /// ProcessPropertyDecl - Make sure that any user-defined setter/getter methods @@ -2487,7 +2475,6 @@ void SemaObjC::ProcessPropertyDecl(ObjCPropertyDecl *property) { : ObjCImplementationControl::Required); CD->addDecl(GetterMethod); - SemaRef.copyFeatureAvailability(GetterMethod, CD); AddPropertyAttrs(SemaRef, GetterMethod, property); if (property->isDirectProperty()) @@ -2567,7 +2554,6 @@ void SemaObjC::ProcessPropertyDecl(ObjCPropertyDecl *property) { nullptr); SetterMethod->setMethodParams(Context, Argument, std::nullopt); - SemaRef.copyFeatureAvailability(SetterMethod, CD); AddPropertyAttrs(SemaRef, SetterMethod, property); if (property->isDirectProperty()) diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 2d3312b11fcb0..c7c3666971a6a 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -601,10 +601,6 @@ Sema::ActOnLabelStmt(SourceLocation IdentLoc, LabelDecl *TheDecl, TheDecl->setLocation(IdentLoc); } } - - if (FunctionScopeInfo *Info = getCurFunctionAvailabilityContext()) - Info->HasPotentialFeatureAvailabilityViolations = true; - return LS; } diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index a6d6edc6c72ae..baad70cafcb43 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -21,7 +21,6 @@ // CHECK-NEXT: ArmBuiltinAlias (SubjectMatchRule_function) // CHECK-NEXT: AssumeAligned (SubjectMatchRule_objc_method, SubjectMatchRule_function) // CHECK-NEXT: Availability ((SubjectMatchRule_record, SubjectMatchRule_enum, SubjectMatchRule_enum_constant, SubjectMatchRule_field, SubjectMatchRule_function, SubjectMatchRule_namespace, SubjectMatchRule_objc_category, SubjectMatchRule_objc_implementation, SubjectMatchRule_objc_interface, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_objc_protocol, SubjectMatchRule_record, SubjectMatchRule_type_alias, SubjectMatchRule_variable)) -// CHECK-NEXT: AvailabilityDomain (SubjectMatchRule_variable) // CHECK-NEXT: AvailableOnlyInDefaultEvalMethod (SubjectMatchRule_type_alias) // CHECK-NEXT: BPFPreserveAccessIndex (SubjectMatchRule_record) // CHECK-NEXT: BPFPreserveStaticOffset (SubjectMatchRule_record) diff --git a/clang/test/Sema/feature-availability.c b/clang/test/Sema/feature-availability.c deleted file mode 100644 index 4b934950f4190..0000000000000 --- a/clang/test/Sema/feature-availability.c +++ /dev/null @@ -1,221 +0,0 @@ -// RUN: %clang_cc1 -triple arm64-apple-macosx15 -fblocks -ffeature-availability=feature1:1 -ffeature-availability=feature2:0 -ffeature-availability=feature3:on -fsyntax-only -verify %s -// RUN: %clang_cc1 -triple arm64-apple-macosx15 -fblocks -fsyntax-only -verify -DUSE_DOMAIN %s - -#include - -#define AVAIL 0 -#define UNAVAIL 1 -#define INVALID 2 - -#ifdef USE_DOMAIN -int pred1(void); -static struct __AvailabilityDomain __feature1 __attribute__((availability_domain(feature1))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain __feature2 __attribute__((availability_domain(feature2))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; -static struct __AvailabilityDomain __feature3 __attribute__((availability_domain(feature3))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain __feature4 __attribute__((availability_domain(feature4))) = {__AVAILABILITY_DOMAIN_DYNAMIC, pred1}; -#endif - -__attribute__((availability(domain:feature1, AVAIL))) void func12(void); -__attribute__((availability(domain:feature2, AVAIL))) void func13(void); -__attribute__((availability(domain:feature1, AVAIL))) void func6(void); -__attribute__((availability(domain:feature1, UNAVAIL))) void func7(void); -__attribute__((availability(domain:feature2, AVAIL))) void func8(void); -__attribute__((availability(domain:feature2, UNAVAIL))) void func9(void); -__attribute__((availability(domain:feature3, AVAIL))) void func20(void); -__attribute__((availability(domain:feature1, AVAIL))) int g0; -__attribute__((availability(domain:feature1, UNAVAIL))) int g1; -__attribute__((availability(domain:feature2, AVAIL))) int g2; -__attribute__((availability(domain:feature2, UNAVAIL))) int g3; -#ifdef USE_DOMAIN -__attribute__((availability(domain:feature4, AVAIL))) void func10(void); -__attribute__((availability(domain:feature4, UNAVAIL))) void func11(void); -__attribute__((availability(domain:feature4, AVAIL))) int g4; -__attribute__((availability(domain:feature4, UNAVAIL))) int g5; -#endif - -__attribute__((availability(domain:2, AVAIL))) void func5(void); // expected-error {{expected a domain name}} -__attribute__((availability(domain, AVAIL))) void func4(void); // expected-error {{expected ':'}} -__attribute__((availability(domain:, AVAIL))) void func0(void); // expected-error {{expected a domain name}} -__attribute__((availability(domain:nonexistent, AVAIL))) void func1(void); // expected-error {{cannot find definition of feature attribute 'nonexistent'}} -__attribute__((availability(domain:feature1, INVALID))) void func2(void); // expected-error {{invalid argument 2: must evaluate to 0 or 1}} -__attribute__((availability(domain:feature1, "1"))) void func3(void); // expected-error {{expected }} - -__attribute__((availability(domain:feature1, AVAIL), availability(domain:feature1, UNAVAIL))) void func14(void); // expected-error {{cannot add feature availability to this decl}} expected-note {{feature attribute __attribute__((availability(domain:feature1, 1)))}} expected-note {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} -__attribute__((availability(domain:feature1, AVAIL), availability(domain:feature2, AVAIL))) void func15(void); -__attribute__((availability(domain:feature1, AVAIL), availability(domain:feature2, UNAVAIL))) void func16(void); -__attribute__((availability(domain:feature1, UNAVAIL), availability(domain:feature2, AVAIL))) void func17(void); -__attribute__((availability(domain:feature1, UNAVAIL), availability(domain:feature2, UNAVAIL))) void func18(void); - -__attribute__((availability(macosx,introduced=10), availability(domain:feature1, AVAIL))) void func19(void); - -int *g12 = &g0; // expected-error {{use of 'g0' requires feature 'feature1' to be available}} -int g7 = sizeof(g0); // expected-error {{use of 'g0' requires feature 'feature1' to be available}} -__attribute__((availability(domain:feature1, AVAIL))) int g6 = sizeof(g0); -__attribute__((availability(domain:feature1, UNAVAIL))) int g8 = sizeof(g0); // expected-error {{use of 'g0' requires feature 'feature1' to be available}} -__attribute__((availability(domain:feature2, AVAIL))) int g9 = sizeof(g0); // expected-error {{use of 'g0' requires feature 'feature1' to be available}} -void (*fp0)(void) = func6; // expected-error {{use of 'func6' requires feature 'feature1' to be available}} -void (* __attribute__((availability(domain:feature1, AVAIL))) fp1)(void) = func6; -void (* __attribute__((availability(domain:feature1, UNAVAIL))) fp2)(void) = func6; // expected-error {{use of 'func6' requires feature 'feature1' to be available}} -void (* __attribute__((availability(domain:feature2, AVAIL))) fp3)(void) = func6; // expected-error {{use of 'func6' requires feature 'feature1' to be available}} - -void func6(void); -__attribute__((availability(domain:feature1, AVAIL))) void func6(void); // expected-note {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} -__attribute__((availability(domain:feature1, UNAVAIL))) void func6(void); // expected-error {{cannot merge incompatible feature attribute to this decl}} expected-note {{feature attribute __attribute__((availability(domain:feature1, 1)))}} -__attribute__((availability(domain:feature1, AVAIL))) void func8(void); // expected-error {{new feature attributes cannot be added to redeclarations}} - -int g0; -__attribute__((availability(domain:feature1, AVAIL))) int g0; // expected-note {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} -__attribute__((availability(domain:feature1, UNAVAIL))) int g0; // expected-error {{cannot merge incompatible feature attribute to this decl}} expected-note {{feature attribute __attribute__((availability(domain:feature1, 1)))}} -__attribute__((availability(domain:feature1, AVAIL))) int g2;// expected-error {{new feature attributes cannot be added to redeclarations}} - -typedef int INT0 __attribute__((availability(domain:feature2, AVAIL))); -typedef INT0 INT1 __attribute__((availability(domain:feature2, AVAIL))); -typedef INT0 INT2 __attribute__((availability(domain:feature2, UNAVAIL))); // expected-error {{use of 'INT0' requires feature 'feature2' to be available}} -typedef INT0 INT3 __attribute__((availability(domain:feature1, AVAIL))); // expected-error {{use of 'INT0' requires feature 'feature2' to be available}} - -enum __attribute__((availability(domain:feature1, AVAIL))) E { - EA, - EB __attribute__((availability(domain:feature2, AVAIL))), -}; - -struct __attribute__((availability(domain:feature1, AVAIL))) S0 { - int i0; -}; - -struct __attribute__((availability(domain:feature1, AVAIL))) S1 { - struct S0 s0; -}; - -struct S2 { - struct S0 s0; // expected-error {{use of 'S0' requires feature 'feature1' to be available}} - int i0 __attribute__((availability(domain:feature1, AVAIL))); // expected-error {{feature attributes cannot be applied to struct members}} -}; - -struct S0 g10; // expected-error {{use of 'S0' requires feature 'feature1' to be available}} -__attribute__((availability(domain:feature1, AVAIL))) struct S0 g11; - -void test0(void) { - func12(); // expected-error {{use of 'func12' requires feature 'feature1' to be available}} - func7(); // expected-error {{use of 'func7' requires feature 'feature1' to be unavailable}} - func19(); // expected-error {{use of 'func19' requires feature 'feature1' to be available}} - - if (__builtin_available(domain:feature1, domain:feature2)) // expected-error {{cannot pass a domain argument along with other arguments}} - ; - - if (__builtin_available(domain:feature1)) { - func12(); - func7(); // expected-error {{use of 'func7' requires feature 'feature1' to be unavailable}} - func13(); // expected-error {{use of 'func13' requires feature 'feature2' to be available}} - if (__builtin_available(domain:feature2)) { - func13(); - func9(); // expected-error {{use of 'func9' requires feature 'feature2' to be unavailable}} - func12(); - } else { - func13(); // expected-error {{use of 'func13' requires feature 'feature2' to be available}} - func9(); - func12(); - } - } else { - func12(); // expected-error {{use of 'func12' requires feature 'feature1' to be available}} - func7(); - } -} - - __attribute__((availability(domain:feature1, AVAIL))) -void test1(void) { - func12(); - func7(); // expected-error {{use of 'func7' requires feature 'feature1' to be unavailable}} -} - - __attribute__((availability(domain:feature1, UNAVAIL))) -void test2(void) { - func12(); // expected-error {{use of 'func12' requires feature 'feature1' to be available}} - func7(); -} - -__attribute__((availability(domain:feature3, AVAIL))) -void test3(void) { - ^ { - func12(); // expected-error {{use of 'func12' requires feature 'feature1' to be available}} - func7(); // expected-error {{use of 'func7' requires feature 'feature1' to be unavailable}} - func20(); - }(); - - if (__builtin_available(domain:feature1)) { - ^{ - func12(); - func7(); // expected-error {{use of 'func7' requires feature 'feature1' to be unavailable}} - func20(); - if (__builtin_available(domain:feature2)) { - func13(); - func9(); // expected-error {{use of 'func9' requires feature 'feature2' to be unavailable}} - } else { - func13(); // expected-error {{use of 'func13' requires feature 'feature2' to be available}} - func9(); - } - }(); - } else { - ^{ - func12(); // expected-error {{use of 'func12' requires feature 'feature1' to be available}} - func7(); - func20(); - }(); - } -} - -void test4(struct S0 *s0) { // expected-error {{use of 'S0' requires feature 'feature1' to be available}} - g11.i0 = 0; // expected-error {{use of 'g11' requires feature 'feature1' to be available}} expected-error {{use of 'i0' requires feature 'feature1' to be available}} -} - -void test5(void) { - if (__builtin_available(domain:feature1)) - label0: // expected-error {{labels cannot appear in regions conditionally guarded by features}} - ; - label1: - ; -} - -void test6(void) { - if (__builtin_available(domain:feature1)) { - if (__builtin_available(domain:feature2)) { - func15(); - func16(); // expected-error {{use of 'func16' requires feature 'feature2' to be unavailable}} - func17(); // expected-error {{use of 'func17' requires feature 'feature1' to be unavailable}} - func18(); // expected-error {{use of 'func18' requires feature 'feature1' to be unavailable}} expected-error {{use of 'func18' requires feature 'feature2' to be unavailable}} - } else { - func15(); // expected-error {{use of 'func15' requires feature 'feature2' to be available}} - func16(); - func17(); // expected-error {{use of 'func17' requires feature 'feature1' to be unavailable}} expected-error {{use of 'func17' requires feature 'feature2' to be available}} - func18(); // expected-error {{use of 'func18' requires feature 'feature1' to be unavailable}} - } - } else { - if (__builtin_available(domain:feature2)) { - func15(); // expected-error {{use of 'func15' requires feature 'feature1' to be available}} - func16(); // expected-error {{use of 'func16' requires feature 'feature1' to be available}} expected-error {{use of 'func16' requires feature 'feature2' to be unavailable}} - func17(); - func18(); // expected-error {{use of 'func18' requires feature 'feature2' to be unavailable}} - } else { - func15(); // expected-error {{use of 'func15' requires feature 'feature1' to be available}} expected-error {{use of 'func15' requires feature 'feature2' to be available}} - func16(); // expected-error {{use of 'func16' requires feature 'feature1' to be available}} - func17(); // expected-error {{use of 'func17' requires feature 'feature2' to be available}} - func18(); - } - } -} - -void test7(void) { - enum E e; // expected-error {{use of 'E' requires feature 'feature1' to be available}} - struct S0 s0; // expected-error {{use of 'S0' requires feature 'feature1' to be available}} - - if (__builtin_available(domain:feature1)) { - enum E e; - e = EA; - e = EB; // expected-error {{use of 'EB' requires feature 'feature2' to be available}} - } - - if (__builtin_available(domain:feature2)) { - enum E e; // expected-error {{use of 'E' requires feature 'feature1' to be available}} - e = EA; // expected-error {{use of 'EA' requires feature 'feature1' to be available}} - e = EB; // expected-error {{use of 'EB' requires feature 'feature1' to be available}} - } -} diff --git a/clang/test/SemaObjC/feature-availability.m b/clang/test/SemaObjC/feature-availability.m deleted file mode 100644 index 6d9acebcd4727..0000000000000 --- a/clang/test/SemaObjC/feature-availability.m +++ /dev/null @@ -1,172 +0,0 @@ -// RUN: %clang_cc1 -fblocks -ffeature-availability=feature1:ON -ffeature-availability=feature2:OFF -fsyntax-only -verify %s -// RUN: %clang_cc1 -fblocks -fsyntax-only -verify -DUSE_DOMAIN %s - -#include - -#define AVAIL 0 -#define UNAVAIL 1 - -#ifdef USE_DOMAIN -int pred1(void); -static struct __AvailabilityDomain feature1 __attribute__((availability_domain(feature1))) = {__AVAILABILITY_DOMAIN_ENABLED, 0}; -static struct __AvailabilityDomain feature2 __attribute__((availability_domain(feature2))) = {__AVAILABILITY_DOMAIN_DISABLED, 0}; -#endif - -__attribute__((availability(domain:feature1, AVAIL))) int func1(void); -__attribute__((availability(domain:feature1, UNAVAIL))) void func3(void); - -struct __attribute__((availability(domain:feature1, UNAVAIL))) S0 {}; -struct __attribute__((availability(domain:feature1, AVAIL))) S1 {}; - -@interface C0 { - struct S0 ivar0; // expected-error {{use of 'S0' requires feature 'feature1' to be unavailable}} - struct S1 ivar1; // expected-error {{use of 'S1' requires feature 'feature1' to be available}} - struct S1 ivar2 __attribute__((availability(domain:feature1, AVAIL))); - struct S1 ivar3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{use of 'S1' requires feature 'feature1' to be available}} -} -@property struct S0 prop0; // expected-error {{use of 'S0' requires feature 'feature1' to be unavailable}} -@property struct S1 prop1; // expected-error {{use of 'S1' requires feature 'feature1' to be available}} -@property struct S1 prop2 __attribute__((availability(domain:feature1, AVAIL))); -@property struct S1 prop3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{use of 'S1' requires feature 'feature1' to be available}} --(struct S0)m0; // expected-error {{use of 'S0' requires feature 'feature1' to be unavailable}} --(struct S1)m1; // expected-error {{use of 'S1' requires feature 'feature1' to be available}} --(struct S1)m2 __attribute__((availability(domain:feature1, AVAIL))); --(struct S1)m3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{use of 'S1' requires feature 'feature1' to be available}} -@end - -__attribute__((availability(domain:feature1, AVAIL))) // expected-note 2 {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} -@interface Base0 { - struct S0 ivar0; // expected-error {{use of 'S0' requires feature 'feature1' to be unavailable}} - struct S1 ivar1; - struct S1 ivar2 __attribute__((availability(domain:feature1, AVAIL))); - struct S1 ivar3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{cannot merge incompatible feature attribute to this decl}} expected-note {{feature attribute __attribute__((availability(domain:feature1, 1)))}} -} -@property struct S0 prop0; // expected-error {{use of 'S0' requires feature 'feature1' to be unavailable}} -@property struct S1 prop1; -@property struct S1 prop2 __attribute__((availability(domain:feature1, AVAIL))); -@property struct S1 prop3 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error {{cannot merge incompatible feature attribute to this decl}} expected-note {{feature attribute __attribute__((availability(domain:feature1, 1)))}} -@end - -__attribute__((availability(domain:feature1, AVAIL), // expected-note {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} - availability(domain:feature1, UNAVAIL))) // expected-note {{feature attribute __attribute__((availability(domain:feature1, 1))}} -@interface Base1 // expected-error {{cannot add feature availability to this decl}} -@end - -@interface NSObject -@end - -@interface Base7 : NSObject -@end - -@interface Derived3 : Base7 // expected-error {{use of 'Base0' requires feature 'feature1' to be available}} -@end - -__attribute__((availability(domain:feature1, AVAIL))) // expected-note {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} expected-note 2 {{feature attribute __attribute__((availability(domain:feature1, 0)))}} -@interface Derived0 : Base0 { - struct S1 *ivar4; -} -@property struct S1 *p0; -@property int p1 __attribute__((availability(domain:feature1, AVAIL))); -@property int prop0_derived0 __attribute__((availability(domain:feature1, UNAVAIL))); // expected-error 3 {{cannot merge incompatible feature attribute to this decl}} expected-note {{feature attribute __attribute__((availability(domain:feature1, 1)))}} expected-note 2 {{is incompatible with __attribute__((availability(domain:feature1, 1)))}} -@end - -@interface Derived0() -@property struct S1 *p0_Ext; -@end - -@implementation Derived0 --(void)m0 { - func1(); - func3(); // expected-error {{use of 'func3' requires feature 'feature1' to be unavailable}} -} --(void)m1 { - self.p1 = 1; -} -@end - -@interface Derived0(C0) -@property struct S1 *p0_C0; -@end - -__attribute__((availability(domain:feature1, AVAIL))) // expected-note {{is incompatible with __attribute__((availability(domain:feature1, 0)))}} -@interface Derived1 : Base0 { - struct S1 *ivar4; -} -@property struct S1 *p0; -@end - -@interface Derived1() -@property struct S1 *p0_Ext; -@end - -@implementation Derived1 --(void)m0 { - func1(); -} -@end - -@interface Derived1(C0) -@property struct S1 *p0_C0; -@end - -__attribute__((availability(domain:feature1, UNAVAIL))) // expected-note {{feature attribute __attribute__((availability(domain:feature1, 1)))}} -@interface Derived1(C1) // expected-error {{cannot merge incompatible feature attribute to this decl}} -@end - -@protocol P0 -@property struct S1 *p0; // expected-error {{use of 'S1' requires feature 'feature1' to be available}} -@end - -__attribute__((availability(domain:feature1, AVAIL))) -@interface Derived2 : Base0 -@end - -__attribute__((availability(domain:feature1, AVAIL))) // expected-error {{feature attributes cannot be applied to ObjC class implementations}} -@implementation Derived2 -@end - -__attribute__((availability(domain:feature1, AVAIL))) -@interface Derived2(Cat1) -@end - -__attribute__((availability(domain:feature1, AVAIL))) // expected-error {{feature attributes cannot be applied to ObjC category implementations}} -@implementation Derived2(Cat1) -@end - -__attribute__((availability(domain:feature1, UNAVAIL))) -@protocol P1 -@end - -__attribute__((availability(domain:feature1, UNAVAIL))) -@interface Base2 -@end - -__attribute__((availability(domain:feature1, UNAVAIL))) -@interface Base3 -@end - -__attribute__((availability(domain:feature1, AVAIL))) -@interface Base4 // expected-error {{use of 'P1' requires feature 'feature1' to be unavailable}} -@end - -__attribute__((availability(domain:feature1, AVAIL))) -@protocol P2 -@end - -@interface Base5 -@end - -__attribute__((availability(domain:feature1, AVAIL))) -@interface Base5(Cat2) -@end - -__attribute__((availability(domain:feature1, AVAIL))) -@interface Base5(Cat3) -@end - -__attribute__((availability(domain:feature1, UNAVAIL))) -@interface Base5(Cat4) // expected-error {{use of 'P2' requires feature 'feature1' to be available}} -@end - -@interface Base6 // expected-error {{use of 'P1' requires feature 'feature1' to be unavailable}} expected-error {{use of 'P2' requires feature 'feature1' to be available}} -@end