diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-01-15 22:43:08 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-01-15 22:43:08 +0000 |
commit | f4d918fdf7da64215db8abe63945798c66e6d132 (patch) | |
tree | 3e7e4638ae49e8361b6d3c3a746b38075a8fb8bd /lib/Sema/SemaDecl.cpp | |
parent | 041e6aab2f48574009aebfb41ffcb74d00758a1f (diff) |
When checking availability attributes for consistency between an
overriding and overridden method, allow the overridden method to have
a narrower contract (introduced earlier, deprecated/obsoleted later)
than the overriding method. Fixes <rdar://problem/12992023>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172567 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDecl.cpp')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 34 |
1 files changed, 23 insertions, 11 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 537e70bfbe..5d655e24c0 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1822,13 +1822,14 @@ DeclHasAttr(const Decl *D, const Attr *A) { return false; } -bool Sema::mergeDeclAttribute(NamedDecl *D, InheritableAttr *Attr) { +bool Sema::mergeDeclAttribute(NamedDecl *D, InheritableAttr *Attr, + bool Override) { InheritableAttr *NewAttr = NULL; if (AvailabilityAttr *AA = dyn_cast<AvailabilityAttr>(Attr)) NewAttr = mergeAvailabilityAttr(D, AA->getRange(), AA->getPlatform(), AA->getIntroduced(), AA->getDeprecated(), AA->getObsoleted(), AA->getUnavailable(), - AA->getMessage()); + AA->getMessage(), Override); else if (VisibilityAttr *VA = dyn_cast<VisibilityAttr>(Attr)) NewAttr = mergeVisibilityAttr(D, VA->getRange(), VA->getVisibility()); else if (DLLImportAttr *ImportA = dyn_cast<DLLImportAttr>(Attr)) @@ -1902,7 +1903,7 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) { /// mergeDeclAttributes - Copy attributes from the Old decl to the New one. void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, - bool MergeDeprecation) { + AvailabilityMergeKind AMK) { // attributes declared post-definition are currently ignored checkNewAttributesAfterDef(*this, New, Old); @@ -1919,14 +1920,25 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, i = Old->specific_attr_begin<InheritableAttr>(), e = Old->specific_attr_end<InheritableAttr>(); i != e; ++i) { + bool Override = false; // Ignore deprecated/unavailable/availability attributes if requested. - if (!MergeDeprecation && - (isa<DeprecatedAttr>(*i) || - isa<UnavailableAttr>(*i) || - isa<AvailabilityAttr>(*i))) - continue; + if (isa<DeprecatedAttr>(*i) || + isa<UnavailableAttr>(*i) || + isa<AvailabilityAttr>(*i)) { + switch (AMK) { + case AMK_None: + continue; + + case AMK_Redeclaration: + break; + + case AMK_Override: + Override = true; + break; + } + } - if (mergeDeclAttribute(New, *i)) + if (mergeDeclAttribute(New, *i, Override)) foundAny = true; } @@ -2475,7 +2487,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, ObjCMethodDecl *oldMethod) { // Merge the attributes, including deprecated/unavailable - mergeDeclAttributes(newMethod, oldMethod, /* mergeDeprecation */true); + mergeDeclAttributes(newMethod, oldMethod, AMK_Override); // Merge attributes from the parameters. ObjCMethodDecl::param_const_iterator oi = oldMethod->param_begin(), @@ -2485,7 +2497,7 @@ void Sema::mergeObjCMethodDecls(ObjCMethodDecl *newMethod, ni != ne && oi != oe; ++ni, ++oi) mergeParamDeclAttributes(*ni, *oi, Context); - CheckObjCMethodOverride(newMethod, oldMethod, true); + CheckObjCMethodOverride(newMethod, oldMethod); } /// MergeVarDeclTypes - We parsed a variable 'New' which has the same name and |