aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-01-15 22:43:08 +0000
committerDouglas Gregor <dgregor@apple.com>2013-01-15 22:43:08 +0000
commitf4d918fdf7da64215db8abe63945798c66e6d132 (patch)
tree3e7e4638ae49e8361b6d3c3a746b38075a8fb8bd /lib/Sema/SemaDecl.cpp
parent041e6aab2f48574009aebfb41ffcb74d00758a1f (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.cpp34
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