diff options
author | Alex Lorenz <arphaman@gmail.com> | 2019-01-24 19:14:39 +0000 |
---|---|---|
committer | Alex Lorenz <arphaman@gmail.com> | 2019-01-24 19:14:39 +0000 |
commit | 3cfe9d5c22e7b47384c17b6950cf120f109366b3 (patch) | |
tree | c61282ed48dbb4d1f6ff5dc319ed0b516a5291d2 /clang/lib/Sema | |
parent | c43f673090d86237d6eb832c4244fc121070486d (diff) | |
download | bcm5719-llvm-3cfe9d5c22e7b47384c17b6950cf120f109366b3.tar.gz bcm5719-llvm-3cfe9d5c22e7b47384c17b6950cf120f109366b3.zip |
Add a priority field to availability attributes to prioritize explicit
attributes from declaration over attributes from '#pragma clang attribute'
Before this commit users had an issue when using #pragma clang attribute with
availability attributes:
The explicit attribute that's specified next to the declaration is not
guaranteed to be preferred over the attribute specified in the pragma.
This commit fixes this by introducing a priority field to the availability
attribute to control how they're merged. Attributes with higher priority are
applied over attributes with lower priority for the same platform. The
implicitly inferred attributes are given the lower priority. This ensures that:
- explicit attributes are preferred over all other attributes.
- implicitly inferred attributes that are inferred from an explicit attribute
are discarded if there's an explicit attribute or an attribute specified
using a #pragma for the same platform.
- implicitly inferred attributes that are inferred from an attribute in the
#pragma are not used if there's an explicit, explicit #pragma, or an
implicit attribute inferred from an explicit attribute for the declaration.
This is the resulting ranking:
`platform availability > platform availability from pragma > inferred availability > inferred availability from pragma`
rdar://46390243
Differential Revision: https://reviews.llvm.org/D56892
llvm-svn: 352084
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 95 |
3 files changed, 43 insertions, 67 deletions
diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 0cff8d3acc3..e1929e3ec2d 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -522,6 +522,7 @@ attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) { void Sema::ActOnPragmaAttributeAttribute( ParsedAttr &Attribute, SourceLocation PragmaLoc, attr::ParsedSubjectMatchRuleSet Rules) { + Attribute.setIsPragmaClangAttribute(); SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules; // Gather the subject match rules that are supported by the attribute. SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> @@ -679,6 +680,8 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) { for (auto &Entry : Group.Entries) { ParsedAttr *Attribute = Entry.Attribute; assert(Attribute && "Expected an attribute"); + assert(Attribute->isPragmaClangAttribute() && + "expected #pragma clang attribute"); // Ensure that the attribute can be applied to the given declaration. bool Applies = false; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c4a5b9cc5c7..9f00a5ee2ac 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2430,13 +2430,11 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D, InheritableAttr *NewAttr = nullptr; unsigned AttrSpellingListIndex = Attr->getSpellingListIndex(); if (const auto *AA = dyn_cast<AvailabilityAttr>(Attr)) - NewAttr = S.mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(), - AA->isImplicit(), AA->getIntroduced(), - AA->getDeprecated(), - AA->getObsoleted(), AA->getUnavailable(), - AA->getMessage(), AA->getStrict(), - AA->getReplacement(), AMK, - AttrSpellingListIndex); + NewAttr = S.mergeAvailabilityAttr( + D, AA->getRange(), AA->getPlatform(), AA->isImplicit(), + AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(), + AA->getUnavailable(), AA->getMessage(), AA->getStrict(), + AA->getReplacement(), AMK, AA->getPriority(), AttrSpellingListIndex); else if (const auto *VA = dyn_cast<VisibilityAttr>(Attr)) NewAttr = S.mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility(), AttrSpellingListIndex); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 010095da577..cf7e97a67b0 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2283,18 +2283,11 @@ static bool versionsMatch(const VersionTuple &X, const VersionTuple &Y, return false; } -AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, - IdentifierInfo *Platform, - bool Implicit, - VersionTuple Introduced, - VersionTuple Deprecated, - VersionTuple Obsoleted, - bool IsUnavailable, - StringRef Message, - bool IsStrict, - StringRef Replacement, - AvailabilityMergeKind AMK, - unsigned AttrSpellingListIndex) { +AvailabilityAttr *Sema::mergeAvailabilityAttr( + NamedDecl *D, SourceRange Range, IdentifierInfo *Platform, bool Implicit, + VersionTuple Introduced, VersionTuple Deprecated, VersionTuple Obsoleted, + bool IsUnavailable, StringRef Message, bool IsStrict, StringRef Replacement, + AvailabilityMergeKind AMK, int Priority, unsigned AttrSpellingListIndex) { VersionTuple MergedIntroduced = Introduced; VersionTuple MergedDeprecated = Deprecated; VersionTuple MergedObsoleted = Obsoleted; @@ -2328,16 +2321,15 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, } // If there is an existing availability attribute for this platform that - // is explicit and the new one is implicit use the explicit one and - // discard the new implicit attribute. - if (!OldAA->isImplicit() && Implicit) { + // has a lower priority use the existing one and discard the new + // attribute. + if (OldAA->getPriority() < Priority) return nullptr; - } - // If there is an existing attribute for this platform that is implicit - // and the new attribute is explicit then erase the old one and - // continue processing the attributes. - if (!Implicit && OldAA->isImplicit()) { + // If there is an existing attribute for this platform that has a higher + // priority than the new attribute then erase the old one and continue + // processing the attributes. + if (OldAA->getPriority() > Priority) { Attrs.erase(Attrs.begin() + i); --e; continue; @@ -2436,11 +2428,10 @@ AvailabilityAttr *Sema::mergeAvailabilityAttr(NamedDecl *D, SourceRange Range, if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced, MergedDeprecated, MergedObsoleted) && !OverrideOrImpl) { - auto *Avail = ::new (Context) AvailabilityAttr(Range, Context, Platform, - Introduced, Deprecated, - Obsoleted, IsUnavailable, Message, - IsStrict, Replacement, - AttrSpellingListIndex); + auto *Avail = ::new (Context) + AvailabilityAttr(Range, Context, Platform, Introduced, Deprecated, + Obsoleted, IsUnavailable, Message, IsStrict, + Replacement, Priority, AttrSpellingListIndex); Avail->setImplicit(Implicit); return Avail; } @@ -2483,15 +2474,13 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { } } - AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, AL.getRange(), II, - false/*Implicit*/, - Introduced.Version, - Deprecated.Version, - Obsoleted.Version, - IsUnavailable, Str, - IsStrict, Replacement, - Sema::AMK_None, - Index); + int PriorityModifier = AL.isPragmaClangAttribute() + ? Sema::AP_PragmaClangAttribute + : Sema::AP_Explicit; + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( + ND, AL.getRange(), II, false /*Implicit*/, Introduced.Version, + Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict, + Replacement, Sema::AMK_None, PriorityModifier, Index); if (NewAttr) D->addAttr(NewAttr); @@ -2527,18 +2516,11 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { auto NewDeprecated = adjustWatchOSVersion(Deprecated.Version); auto NewObsoleted = adjustWatchOSVersion(Obsoleted.Version); - AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, - AL.getRange(), - NewII, - true/*Implicit*/, - NewIntroduced, - NewDeprecated, - NewObsoleted, - IsUnavailable, Str, - IsStrict, - Replacement, - Sema::AMK_None, - Index); + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( + ND, AL.getRange(), NewII, true /*Implicit*/, NewIntroduced, + NewDeprecated, NewObsoleted, IsUnavailable, Str, IsStrict, + Replacement, Sema::AMK_None, + PriorityModifier + Sema::AP_InferredFromOtherPlatform, Index); if (NewAttr) D->addAttr(NewAttr); } @@ -2552,20 +2534,13 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, const ParsedAttr &AL) { NewII = &S.Context.Idents.get("tvos_app_extension"); if (NewII) { - AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr(ND, - AL.getRange(), - NewII, - true/*Implicit*/, - Introduced.Version, - Deprecated.Version, - Obsoleted.Version, - IsUnavailable, Str, - IsStrict, - Replacement, - Sema::AMK_None, - Index); - if (NewAttr) - D->addAttr(NewAttr); + AvailabilityAttr *NewAttr = S.mergeAvailabilityAttr( + ND, AL.getRange(), NewII, true /*Implicit*/, Introduced.Version, + Deprecated.Version, Obsoleted.Version, IsUnavailable, Str, IsStrict, + Replacement, Sema::AMK_None, + PriorityModifier + Sema::AP_InferredFromOtherPlatform, Index); + if (NewAttr) + D->addAttr(NewAttr); } } } |