mirror of https://github.com/microsoft/clang.git
[Sema][ObjC] Warn about mismatches in attributes between overriding and
overridden methods when compiling for non-ARC. Previously, clang would error out when compiling for ARC, but didn't print any diagnostics when compiling for non-ARC. This was pointed out in the patch review for attribute noescape: https://reviews.llvm.org/D32210 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313717 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2351bad637
commit
cb0d01de81
|
@ -507,6 +507,9 @@ def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas,
|
|||
PragmaClangAttribute, PragmaPack]>;
|
||||
def UnknownWarningOption : DiagGroup<"unknown-warning-option">;
|
||||
def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
|
||||
def NSConsumedMismatch : DiagGroup<"nsconsumed-mismatch">;
|
||||
def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">;
|
||||
|
||||
def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
|
||||
def UnknownAttributes : DiagGroup<"unknown-attributes">;
|
||||
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
|
||||
|
|
|
@ -8244,12 +8244,12 @@ def err_c99_array_usage_cxx : Error<
|
|||
"feature, not permitted in C++">;
|
||||
def err_type_unsupported : Error<
|
||||
"%0 is not supported on this target">;
|
||||
def err_nsconsumed_attribute_mismatch : Error<
|
||||
def warn_nsconsumed_attribute_mismatch : Warning<
|
||||
"overriding method has mismatched ns_consumed attribute on its"
|
||||
" parameter">;
|
||||
def err_nsreturns_retained_attribute_mismatch : Error<
|
||||
" parameter">, InGroup<NSConsumedMismatch>;
|
||||
def warn_nsreturns_retained_attribute_mismatch : Warning<
|
||||
"overriding method has mismatched ns_returns_%select{not_retained|retained}0"
|
||||
" attributes">;
|
||||
" attributes">, InGroup<NSReturnsMismatch>;
|
||||
|
||||
def note_getter_unavailable : Note<
|
||||
"or because setter is declared here, but no getter method %0 is found">;
|
||||
|
|
|
@ -157,34 +157,36 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
|
|||
diag::note_related_result_type_overridden);
|
||||
}
|
||||
if (getLangOpts().ObjCAutoRefCount) {
|
||||
if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=
|
||||
Overridden->hasAttr<NSReturnsRetainedAttr>())) {
|
||||
Diag(NewMethod->getLocation(),
|
||||
diag::err_nsreturns_retained_attribute_mismatch) << 1;
|
||||
Diag(Overridden->getLocation(), diag::note_previous_decl)
|
||||
<< "method";
|
||||
}
|
||||
if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=
|
||||
Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {
|
||||
Diag(NewMethod->getLocation(),
|
||||
diag::err_nsreturns_retained_attribute_mismatch) << 0;
|
||||
Diag(Overridden->getLocation(), diag::note_previous_decl)
|
||||
<< "method";
|
||||
}
|
||||
ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(),
|
||||
oe = Overridden->param_end();
|
||||
for (ObjCMethodDecl::param_iterator
|
||||
ni = NewMethod->param_begin(), ne = NewMethod->param_end();
|
||||
ni != ne && oi != oe; ++ni, ++oi) {
|
||||
const ParmVarDecl *oldDecl = (*oi);
|
||||
ParmVarDecl *newDecl = (*ni);
|
||||
if (newDecl->hasAttr<NSConsumedAttr>() !=
|
||||
oldDecl->hasAttr<NSConsumedAttr>()) {
|
||||
Diag(newDecl->getLocation(),
|
||||
diag::err_nsconsumed_attribute_mismatch);
|
||||
Diag(oldDecl->getLocation(), diag::note_previous_decl)
|
||||
<< "parameter";
|
||||
}
|
||||
Diags.setSeverity(diag::warn_nsreturns_retained_attribute_mismatch,
|
||||
diag::Severity::Error, SourceLocation());
|
||||
Diags.setSeverity(diag::warn_nsconsumed_attribute_mismatch,
|
||||
diag::Severity::Error, SourceLocation());
|
||||
}
|
||||
|
||||
if ((NewMethod->hasAttr<NSReturnsRetainedAttr>() !=
|
||||
Overridden->hasAttr<NSReturnsRetainedAttr>())) {
|
||||
Diag(NewMethod->getLocation(),
|
||||
diag::warn_nsreturns_retained_attribute_mismatch) << 1;
|
||||
Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";
|
||||
}
|
||||
if ((NewMethod->hasAttr<NSReturnsNotRetainedAttr>() !=
|
||||
Overridden->hasAttr<NSReturnsNotRetainedAttr>())) {
|
||||
Diag(NewMethod->getLocation(),
|
||||
diag::warn_nsreturns_retained_attribute_mismatch) << 0;
|
||||
Diag(Overridden->getLocation(), diag::note_previous_decl) << "method";
|
||||
}
|
||||
|
||||
ObjCMethodDecl::param_const_iterator oi = Overridden->param_begin(),
|
||||
oe = Overridden->param_end();
|
||||
for (ObjCMethodDecl::param_iterator ni = NewMethod->param_begin(),
|
||||
ne = NewMethod->param_end();
|
||||
ni != ne && oi != oe; ++ni, ++oi) {
|
||||
const ParmVarDecl *oldDecl = (*oi);
|
||||
ParmVarDecl *newDecl = (*ni);
|
||||
if (newDecl->hasAttr<NSConsumedAttr>() !=
|
||||
oldDecl->hasAttr<NSConsumedAttr>()) {
|
||||
Diag(newDecl->getLocation(), diag::warn_nsconsumed_attribute_mismatch);
|
||||
Diag(oldDecl->getLocation(), diag::note_previous_decl) << "parameter";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1787,15 +1787,15 @@ CFArrayRef camel_copymachine() {
|
|||
|
||||
// rdar://problem/8024350
|
||||
@protocol F18P
|
||||
- (id) clone;
|
||||
- (id) clone; // expected-note 2 {{method declared here}}
|
||||
@end
|
||||
@interface F18 : NSObject<F18P> @end
|
||||
@interface F18(Cat)
|
||||
- (id) clone NS_RETURNS_RETAINED;
|
||||
- (id) clone NS_RETURNS_RETAINED; // expected-warning {{overriding method has mismatched ns_returns_retained attributes}}
|
||||
@end
|
||||
|
||||
@implementation F18
|
||||
- (id) clone {
|
||||
- (id) clone { // expected-warning {{overriding method has mismatched ns_returns_retained attributes}}
|
||||
return [F18 alloc];
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -verify -fblocks -triple x86_64-apple-darwin10.0.0 %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -verify -fblocks -triple x86_64-apple-darwin10.0.0 -DOBJCARC %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -fblocks -triple x86_64-apple-darwin10.0.0 %s
|
||||
// rdar://10187884
|
||||
|
||||
#ifdef OBJCARC
|
||||
typedef void (^blk)(id arg1, __attribute((ns_consumed)) id arg2);
|
||||
typedef void (^blk1)(__attribute((ns_consumed))id arg1, __attribute((ns_consumed)) id arg2);
|
||||
blk a = ^void (__attribute((ns_consumed)) id arg1, __attribute((ns_consumed)) id arg2){}; // expected-error {{incompatible block pointer types initializing}}
|
||||
|
@ -18,3 +20,12 @@ blk1 b2 = ^void (id arg1, __attribute((ns_consumed)) id arg2){}; // expected-err
|
|||
blk1 c3 = ^void (__attribute((ns_consumed)) id arg1, __attribute((ns_consumed)) id arg2){};
|
||||
|
||||
blk1 d4 = ^void (id arg1, id arg2) {}; // expected-error {{incompatible block pointer types initializing}}
|
||||
#else
|
||||
@interface Sub
|
||||
-(void) m:(id)p; // expected-note {{parameter declared here}}
|
||||
@end
|
||||
|
||||
@interface Super : Sub
|
||||
-(void) m:(__attribute__((ns_consumed)) id)p; // expected-warning {{overriding method has mismatched ns_consumed attribute on its parameter}}
|
||||
@end
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue