diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
-rw-r--r-- | clang/include/clang/Basic/IdentifierTable.h | 1 | ||||
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Basic/IdentifierTable.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 13 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 1 | ||||
-rw-r--r-- | clang/test/SemaObjC/warn-explicit-call-initialize.m | 19 |
8 files changed, 47 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4cdc6c084b9..a55538eed1e 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -6874,6 +6874,9 @@ def err_invalid_protocol_qualifiers : Error< def warn_ivar_use_hidden : Warning< "local declaration of %0 hides instance variable">, InGroup<DiagGroup<"shadow-ivar">>; +def warn_direct_initialize_call : Warning< + "explicit call to +initialize results in duplicate call to +initialize">, + InGroup<DiagGroup<"explicit-initialize-call">>; def error_ivar_use_in_class_method : Error< "instance variable %0 accessed in class method">; def error_implicit_ivar_access : Error< diff --git a/clang/include/clang/Basic/IdentifierTable.h b/clang/include/clang/Basic/IdentifierTable.h index 0c278a17a32..e63e04f7725 100644 --- a/clang/include/clang/Basic/IdentifierTable.h +++ b/clang/include/clang/Basic/IdentifierTable.h @@ -563,6 +563,7 @@ enum ObjCMethodFamily { OMF_retain, OMF_retainCount, OMF_self, + OMF_initialize, // performSelector families OMF_performSelector diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 4657cf371b2..e753feb3d9e 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -849,6 +849,11 @@ ObjCMethodFamily ObjCMethodDecl::getMethodFamily() const { family = OMF_None; break; + case OMF_initialize: + if (isInstanceMethod() || !getReturnType()->isVoidType()) + family = OMF_None; + break; + case OMF_performSelector: if (!isInstanceMethod() || !getReturnType()->isObjCIdType()) family = OMF_None; diff --git a/clang/lib/Basic/IdentifierTable.cpp b/clang/lib/Basic/IdentifierTable.cpp index 21984599632..01f60a9d695 100644 --- a/clang/lib/Basic/IdentifierTable.cpp +++ b/clang/lib/Basic/IdentifierTable.cpp @@ -428,6 +428,7 @@ ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) { if (name == "retain") return OMF_retain; if (name == "retainCount") return OMF_retainCount; if (name == "self") return OMF_self; + if (name == "initialize") return OMF_initialize; } if (name == "performSelector") return OMF_performSelector; diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 8e3e85ed281..90a6264cb12 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -201,6 +201,7 @@ bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) { case OMF_autorelease: case OMF_retainCount: case OMF_self: + case OMF_initialize: case OMF_performSelector: return false; @@ -353,6 +354,7 @@ void Sema::ActOnStartOfObjCMethodDef(Scope *FnBodyScope, Decl *D) { case OMF_copy: case OMF_new: case OMF_self: + case OMF_initialize: case OMF_performSelector: break; } @@ -1515,6 +1517,7 @@ static bool checkMethodFamilyMismatch(Sema &S, ObjCMethodDecl *impl, case OMF_finalize: case OMF_retainCount: case OMF_self: + case OMF_initialize: case OMF_performSelector: // Mismatches for these methods don't change ownership // conventions, so we don't care. @@ -3259,6 +3262,7 @@ Decl *Sema::ActOnMethodDeclaration( case OMF_mutableCopy: case OMF_release: case OMF_retainCount: + case OMF_initialize: case OMF_performSelector: break; diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 582e1834d48..cbf41b5069a 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -1137,6 +1137,7 @@ ExprResult Sema::ParseObjCSelectorExpression(Selector Sel, case OMF_mutableCopy: case OMF_new: case OMF_self: + case OMF_initialize: case OMF_performSelector: break; } @@ -2230,6 +2231,17 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, RequireCompleteType(LBracLoc, Method->getReturnType(), diag::err_illegal_message_expr_incomplete_type)) return ExprError(); + + // Warn about explicit call of +initialize on its own class. + if (Method && Method->getMethodFamily() == OMF_initialize) { + const ObjCInterfaceDecl *ID = + dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()); + if (ID == Class) { + Diag(Loc, diag::warn_direct_initialize_call); + Diag(Method->getLocation(), diag::note_method_declared_at) + << Method->getDeclName(); + } + } // Construct the appropriate ObjCMessageExpr. ObjCMessageExpr *Result; @@ -2652,6 +2664,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, case OMF_mutableCopy: case OMF_new: case OMF_self: + case OMF_initialize: break; case OMF_dealloc: diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index eb699d69408..6e49fbb5d60 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -1359,6 +1359,7 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD, // Check the method family, and apply any default annotations. switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) { case OMF_None: + case OMF_initialize: case OMF_performSelector: // Assume all Objective-C methods follow Cocoa Memory Management rules. // FIXME: Does the non-threaded performSelector family really belong here? diff --git a/clang/test/SemaObjC/warn-explicit-call-initialize.m b/clang/test/SemaObjC/warn-explicit-call-initialize.m new file mode 100644 index 00000000000..786894cb1d7 --- /dev/null +++ b/clang/test/SemaObjC/warn-explicit-call-initialize.m @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin10 -verify %s +// rdar://16628028 + +@interface NSObject ++ (void)initialize; // expected-note {{method 'initialize' declared here}} +@end + +@interface I : NSObject ++ (void)initialize; // expected-note {{method 'initialize' declared here}} +@end + +@implementation I +- (void) Meth { + [I initialize]; // expected-warning {{explicit call to +initialize results in duplicate call to +initialize}} + [NSObject initialize]; // expected-warning {{explicit call to +initialize results in duplicate call to +initialize}} +} ++ (void)initialize {} +@end + |