diff options
Diffstat (limited to 'lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 198 |
1 files changed, 111 insertions, 87 deletions
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 223e517c1f..280e3d7fca 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1729,76 +1729,101 @@ static bool checkAvailabilityAttr(Sema &S, SourceRange Range, return false; } -static void mergeAvailabilityAttr(Sema &S, Decl *D, SourceRange Range, - IdentifierInfo *Platform, - VersionTuple Introduced, - VersionTuple Deprecated, - VersionTuple Obsoleted, - bool IsUnavailable, - StringRef Message) { - VersionTuple MergedIntroduced; - VersionTuple MergedDeprecated; - VersionTuple MergedObsoleted; +bool Sema::mergeAvailabilityAttr(Decl *D, SourceRange Range, + bool Inherited, + IdentifierInfo *Platform, + VersionTuple Introduced, + VersionTuple Deprecated, + VersionTuple Obsoleted, + bool IsUnavailable, + StringRef Message) { + VersionTuple MergedIntroduced = Introduced; + VersionTuple MergedDeprecated = Deprecated; + VersionTuple MergedObsoleted = Obsoleted; bool FoundAny = false; - for (specific_attr_iterator<AvailabilityAttr> - i = D->specific_attr_begin<AvailabilityAttr>(), - e = D->specific_attr_end<AvailabilityAttr>(); - i != e ; ++i) { - const AvailabilityAttr *OldAA = *i; - IdentifierInfo *OldPlatform = OldAA->getPlatform(); - if (OldPlatform != Platform) - continue; - FoundAny = true; - VersionTuple OldIntroduced = OldAA->getIntroduced(); - VersionTuple OldDeprecated = OldAA->getDeprecated(); - VersionTuple OldObsoleted = OldAA->getObsoleted(); - bool OldIsUnavailable = OldAA->getUnavailable(); - StringRef OldMessage = OldAA->getMessage(); - - if ((!OldIntroduced.empty() && !Introduced.empty() && - OldIntroduced != Introduced) || - (!OldDeprecated.empty() && !Deprecated.empty() && - OldDeprecated != Deprecated) || - (!OldObsoleted.empty() && !Obsoleted.empty() && - OldObsoleted != Obsoleted) || - (OldIsUnavailable != IsUnavailable) || - (OldMessage != Message)) { - S.Diag(Range.getBegin(), diag::warn_mismatched_availability); - S.Diag(OldAA->getLocation(), diag::note_previous_attribute); - return; + if (D->hasAttrs()) { + AttrVec &Attrs = D->getAttrs(); + for (unsigned i = 0, e = Attrs.size(); i != e;) { + const AvailabilityAttr *OldAA = dyn_cast<AvailabilityAttr>(Attrs[i]); + if (!OldAA) { + ++i; + continue; + } + + IdentifierInfo *OldPlatform = OldAA->getPlatform(); + if (OldPlatform != Platform) { + ++i; + continue; + } + + FoundAny = true; + VersionTuple OldIntroduced = OldAA->getIntroduced(); + VersionTuple OldDeprecated = OldAA->getDeprecated(); + VersionTuple OldObsoleted = OldAA->getObsoleted(); + bool OldIsUnavailable = OldAA->getUnavailable(); + StringRef OldMessage = OldAA->getMessage(); + + if ((!OldIntroduced.empty() && !Introduced.empty() && + OldIntroduced != Introduced) || + (!OldDeprecated.empty() && !Deprecated.empty() && + OldDeprecated != Deprecated) || + (!OldObsoleted.empty() && !Obsoleted.empty() && + OldObsoleted != Obsoleted) || + (OldIsUnavailable != IsUnavailable) || + (OldMessage != Message)) { + Diag(OldAA->getLocation(), diag::warn_mismatched_availability); + Diag(Range.getBegin(), diag::note_previous_attribute); + Attrs.erase(Attrs.begin() + i); + --e; + continue; + } + + VersionTuple MergedIntroduced2 = MergedIntroduced; + VersionTuple MergedDeprecated2 = MergedDeprecated; + VersionTuple MergedObsoleted2 = MergedObsoleted; + + if (MergedIntroduced2.empty()) + MergedIntroduced2 = OldIntroduced; + if (MergedDeprecated2.empty()) + MergedDeprecated2 = OldDeprecated; + if (MergedObsoleted2.empty()) + MergedObsoleted2 = OldObsoleted; + + if (checkAvailabilityAttr(*this, OldAA->getRange(), Platform, + MergedIntroduced2, MergedDeprecated2, + MergedObsoleted2)) { + Attrs.erase(Attrs.begin() + i); + --e; + continue; + } + + MergedIntroduced = MergedIntroduced2; + MergedDeprecated = MergedDeprecated2; + MergedObsoleted = MergedObsoleted2; + ++i; } - if (MergedIntroduced.empty()) - MergedIntroduced = OldIntroduced; - if (MergedDeprecated.empty()) - MergedDeprecated = OldDeprecated; - if (MergedObsoleted.empty()) - MergedObsoleted = OldObsoleted; } if (FoundAny && MergedIntroduced == Introduced && MergedDeprecated == Deprecated && MergedObsoleted == Obsoleted) - return; - - if (MergedIntroduced.empty()) - MergedIntroduced = Introduced; - if (MergedDeprecated.empty()) - MergedDeprecated = Deprecated; - if (MergedObsoleted.empty()) - MergedObsoleted = Obsoleted; + return false; - if (!checkAvailabilityAttr(S, Range, Platform, MergedIntroduced, + if (!checkAvailabilityAttr(*this, Range, Platform, MergedIntroduced, MergedDeprecated, MergedObsoleted)) { - D->addAttr(::new (S.Context) AvailabilityAttr(Range, S.Context, - Platform, - Introduced, - Deprecated, - Obsoleted, - IsUnavailable, - Message)); + AvailabilityAttr *Attr = + ::new (Context) AvailabilityAttr(Range, Context, Platform, + Introduced, Deprecated, + Obsoleted, IsUnavailable, Message); + + if (Inherited) + Attr->setInherited(true); + D->addAttr(Attr); + return true; } + return false; } static void handleAvailabilityAttr(Sema &S, Decl *D, @@ -1820,13 +1845,32 @@ static void handleAvailabilityAttr(Sema &S, Decl *D, if (SE) Str = SE->getString(); - mergeAvailabilityAttr(S, D, Attr.getRange(), - Platform, - Introduced.Version, - Deprecated.Version, - Obsoleted.Version, - IsUnavailable, - Str); + S.mergeAvailabilityAttr(D, Attr.getRange(), + false, Platform, + Introduced.Version, + Deprecated.Version, + Obsoleted.Version, + IsUnavailable, + Str); +} + +bool Sema::mergeVisibilityAttr(Decl *D, SourceRange Range, + bool Inherited, + VisibilityAttr::VisibilityType Vis) { + VisibilityAttr *ExistingAttr = D->getAttr<VisibilityAttr>(); + if (ExistingAttr) { + VisibilityAttr::VisibilityType ExistingVis = ExistingAttr->getVisibility(); + if (ExistingVis == Vis) + return false; + Diag(ExistingAttr->getLocation(), diag::err_mismatched_visibility); + Diag(Range.getBegin(), diag::note_previous_attribute); + D->dropAttr<VisibilityAttr>(); + } + VisibilityAttr *Attr = ::new (Context) VisibilityAttr(Range, Context, Vis); + if (Inherited) + Attr->setInherited(true); + D->addAttr(Attr); + return true; } static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { @@ -1867,25 +1911,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr) { return; } - // Find the last Decl that has an attribute. - VisibilityAttr *PrevAttr = 0; - assert(D->redecls_begin() == D); - for (Decl::redecl_iterator I = D->redecls_begin(), E = D->redecls_end(); - I != E; ++I) { - PrevAttr = I->getAttr<VisibilityAttr>() ; - if (PrevAttr) - break; - } - - if (PrevAttr) { - VisibilityAttr::VisibilityType PrevVisibility = PrevAttr->getVisibility(); - if (PrevVisibility != type) { - S.Diag(Attr.getLoc(), diag::err_mismatched_visibility); - S.Diag(PrevAttr->getLocation(), diag::note_previous_attribute); - return; - } - } - D->addAttr(::new (S.Context) VisibilityAttr(Attr.getRange(), S.Context, type)); + S.mergeVisibilityAttr(D, Attr.getRange(), false, type); } static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl, @@ -3988,11 +4014,9 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, bool NonInheritable, bool Inheritable) { SmallVector<const AttributeList*, 4> attrs; for (const AttributeList* l = AttrList; l; l = l->getNext()) { + ProcessDeclAttribute(*this, S, D, *l, NonInheritable, Inheritable); attrs.push_back(l); } - for (int i = attrs.size() - 1; i >= 0; --i) { - ProcessDeclAttribute(*this, S, D, *attrs[i], NonInheritable, Inheritable); - } // GCC accepts // static int a9 __attribute__((weakref)); |