summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
authorAlex Lorenz <arphaman@gmail.com>2019-01-24 19:14:39 +0000
committerAlex Lorenz <arphaman@gmail.com>2019-01-24 19:14:39 +0000
commit3cfe9d5c22e7b47384c17b6950cf120f109366b3 (patch)
treec61282ed48dbb4d1f6ff5dc319ed0b516a5291d2 /clang/lib/Sema
parentc43f673090d86237d6eb832c4244fc121070486d (diff)
downloadbcm5719-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.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp12
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp95
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);
}
}
}
OpenPOWER on IntegriCloud