diff options
author | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-12-03 21:11:43 +0000 |
---|---|---|
committer | Argyrios Kyrtzidis <akyrtzi@gmail.com> | 2013-12-03 21:11:43 +0000 |
commit | fcded9b93a96e9a88405325b30caa4cd11120aee (patch) | |
tree | c06abf22140d0af2b7fe042a8be53f012ae1bb3e | |
parent | 22bfa2c28bdbca09949ba4cf8670c310d3e42c71 (diff) | |
download | bcm5719-llvm-fcded9b93a96e9a88405325b30caa4cd11120aee.tar.gz bcm5719-llvm-fcded9b93a96e9a88405325b30caa4cd11120aee.zip |
[objc] Emit warnings when the implementation of a designated initializer calls on
super an initializer that is not a designated one or any initializer on self.
llvm-svn: 196317
-rw-r--r-- | clang/include/clang/AST/DeclObjC.h | 7 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
-rw-r--r-- | clang/lib/AST/DeclObjC.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 31 | ||||
-rw-r--r-- | clang/test/SemaObjC/attr-designated-init.m | 25 |
6 files changed, 61 insertions, 19 deletions
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 774de1a4fed..12e2a0b727a 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -457,7 +457,12 @@ public: /// Returns true if the method selector resolves to a designated initializer /// in the class's interface. - bool isDesignatedInitializerForTheInterface() const; + /// + /// \param InitMethod if non-null and the function returns true, it receives + /// the method declaration that was marked with the designated initializer + /// attribute. + bool isDesignatedInitializerForTheInterface( + const ObjCMethodDecl **InitMethod = 0) const; /// \brief Determine whether this method has a body. virtual bool hasBody() const { return Body.isValid(); } diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 314d0375e67..52fc7981031 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2437,6 +2437,12 @@ def warn_objc_designated_init_missing_super_call : Warning< InGroup<ObjCDesignatedInit>; def note_objc_designated_init_marked_here : Note< "method marked as designated initializer of the class here">; +def warn_objc_designated_init_non_super_designated_init_call : Warning< + "designated initializer should only invoke a designated initializer on 'super'">, + InGroup<ObjCDesignatedInit>; +def warn_objc_designated_init_non_designated_init_call : Warning< + "designated initializer invoked a non-designated initializer">, + InGroup<ObjCDesignatedInit>; def err_ns_bridged_not_interface : Error< "parameter of 'ns_bridged' attribute does not name an Objective-C class">; diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index cb58ad482e1..b392e2f6619 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -655,12 +655,15 @@ bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const { hasAttr<ObjCDesignatedInitializerAttr>(); } -bool ObjCMethodDecl::isDesignatedInitializerForTheInterface() const { +bool ObjCMethodDecl::isDesignatedInitializerForTheInterface( + const ObjCMethodDecl **InitMethod) const { + if (getMethodFamily() != OMF_init) + return false; const DeclContext *DC = getDeclContext(); if (isa<ObjCProtocolDecl>(DC)) return false; if (const ObjCInterfaceDecl *ID = getClassInterface()) - return ID->isDesignatedInitializer(getSelector()); + return ID->isDesignatedInitializer(getSelector(), InitMethod); return false; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c14cc4b8619..f243c0e8d18 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9816,8 +9816,8 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, } if (getCurFunction()->ObjCWarnForNoDesignatedInitChain) { const ObjCMethodDecl *InitMethod = 0; - bool isDesignated = MD->getClassInterface() - ->isDesignatedInitializer(MD->getSelector(), &InitMethod); + bool isDesignated = + MD->isDesignatedInitializerForTheInterface(&InitMethod); assert(isDesignated && InitMethod); (void)isDesignated; Diag(MD->getLocation(), diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 20f4b4f7248..c4523064579 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -2447,14 +2447,33 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, } } - if (SuperLoc.isValid() && getCurFunction()->ObjCIsDesignatedInit) { - if (const ObjCObjectPointerType * - OCIType = ReceiverType->getAsObjCInterfacePointerType()) { - if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) { - if (ID->isDesignatedInitializer(Sel)) - getCurFunction()->ObjCWarnForNoDesignatedInitChain = false; + if (Method && Method->getMethodFamily() == OMF_init && + getCurFunction()->ObjCIsDesignatedInit && + (SuperLoc.isValid() || isSelfExpr(Receiver))) { + bool isDesignatedInitChain = false; + if (SuperLoc.isValid()) { + if (const ObjCObjectPointerType * + OCIType = ReceiverType->getAsObjCInterfacePointerType()) { + if (const ObjCInterfaceDecl *ID = OCIType->getInterfaceDecl()) { + if (ID->isDesignatedInitializer(Sel)) { + isDesignatedInitChain = true; + getCurFunction()->ObjCWarnForNoDesignatedInitChain = false; + } + } } } + if (!isDesignatedInitChain) { + const ObjCMethodDecl *InitMethod = 0; + bool isDesignated = + getCurMethodDecl()->isDesignatedInitializerForTheInterface(&InitMethod); + assert(isDesignated && InitMethod); + (void)isDesignated; + Diag(SelLoc, SuperLoc.isValid() ? + diag::warn_objc_designated_init_non_designated_init_call : + diag::warn_objc_designated_init_non_super_designated_init_call); + Diag(InitMethod->getLocation(), + diag::note_objc_designated_init_marked_here); + } } // Check the message arguments. diff --git a/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m index 3190d8a97fe..59d1357d9e2 100644 --- a/clang/test/SemaObjC/attr-designated-init.m +++ b/clang/test/SemaObjC/attr-designated-init.m @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -verify -fblocks %s #define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer)) @@ -35,7 +35,7 @@ __attribute__((objc_root_class)) @interface B1 -(id)initB1 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} -(id)initB2; --(id)initB3 NS_DESIGNATED_INITIALIZER; +-(id)initB3 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} @end @implementation B1 @@ -47,8 +47,8 @@ __attribute__((objc_root_class)) @interface S1 : B1 -(id)initS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} -(id)initS2 NS_DESIGNATED_INITIALIZER; --(id)initS3 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} --(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} +-(id)initS3 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} +-(id)initS4 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} -(id)initB1; @end @@ -60,10 +60,10 @@ __attribute__((objc_root_class)) return [super initB1]; } -(id)initS3 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} - return [super initB2]; + return [super initB2]; // expected-warning {{designated initializer invoked a non-designated initializer}} } -(id)initS4 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} - return [self initB1]; + return [self initB1]; // expected-warning {{designated initializer should only invoke a designated initializer on 'super'}} } -(id)initB1 { return [self initS1]; @@ -92,12 +92,12 @@ __attribute__((objc_root_class)) @end @interface SS3 : S3 --(id)initSS1 NS_DESIGNATED_INITIALIZER; // expected-note {{method marked as designated initializer of the class here}} +-(id)initSS1 NS_DESIGNATED_INITIALIZER; // expected-note 2 {{method marked as designated initializer of the class here}} @end @implementation SS3 -(id)initSS1 { // expected-warning {{designated initializer missing a 'super' call to a designated initializer of the super class}} - return [super initB1]; + return [super initB1]; // expected-warning {{designated initializer invoked a non-designated initializer}} } @end @@ -116,6 +116,7 @@ __attribute__((objc_root_class)) @end @interface S5 : B1 +-(void)meth; @end @implementation S5 @@ -123,6 +124,14 @@ __attribute__((objc_root_class)) return 0; } -(id)initB3 { + [self initB1]; // expected-warning {{designated initializer should only invoke a designated initializer on 'super'}} + S5 *s; + [s initB1]; + [self meth]; + void (^blk)(void) = ^{ + [self initB1]; + }; return [super initB3]; } +-(void)meth {} @end |